168 lines
3.8 KiB
Markdown
168 lines
3.8 KiB
Markdown
|
# Solutions for all 4 challenges
|
||
|
Point estimates are fairly arbitrary and can be changed by the organizers.
|
||
|
|
||
|
## Category
|
||
|
All of these challenges can be put in something like a programming category.
|
||
|
|
||
|
## Challenge 0
|
||
|
### Difficulty
|
||
|
Free (5 points)
|
||
|
|
||
|
### How To Solve
|
||
|
`(lambda (a) (+ a 1))`
|
||
|
|
||
|
### Flag
|
||
|
IGCTF{YouPassedTheSanityCheck!}
|
||
|
|
||
|
-------------------------------------
|
||
|
## Challenge 1
|
||
|
### Difficulty
|
||
|
Easy (30 points)
|
||
|
|
||
|
### How To Solve
|
||
|
The algorithm is fairly simple to implement:
|
||
|
```scheme
|
||
|
(define (f n)
|
||
|
(if (zero? (- n 1))
|
||
|
0
|
||
|
(if (even? n)
|
||
|
(+ 1 (f (/ n 2)))
|
||
|
(+ 1 (f (+ 1 (* n 3)))))))
|
||
|
```
|
||
|
Applying the constraints from the challenge gives:
|
||
|
```scheme
|
||
|
(begin
|
||
|
(define (a b)
|
||
|
(if (zero? (- b 1))
|
||
|
0
|
||
|
(if (even? b)
|
||
|
(+ 1 (a (/ b 2)))
|
||
|
(+ 1 (a (+ 1 (* b 3)))))))
|
||
|
a)
|
||
|
```
|
||
|
|
||
|
### Flag
|
||
|
IGCTF{TJMtKPpKsQNRHkUmricn}
|
||
|
|
||
|
-----------------------------------------------
|
||
|
## Challenge 2
|
||
|
### Difficulty
|
||
|
Easy to Average (45 points)
|
||
|
|
||
|
### How To Solve
|
||
|
We can reuse the code from before, but we'll need to implement multiplication and division ourself. That's not very difficult to do.
|
||
|
```scheme
|
||
|
(begin
|
||
|
(define (times x y)
|
||
|
(if (= 0 y)
|
||
|
0
|
||
|
(+ x (times x (- y 1)))))
|
||
|
(define (div x y)
|
||
|
(if (= x 0)
|
||
|
0
|
||
|
(+ 1 (div (- x y) y))))
|
||
|
(define (f n)
|
||
|
(if (zero? (- n 1))
|
||
|
0
|
||
|
(if (even? n)
|
||
|
(+ 1 (f (div n 2)))
|
||
|
(+ 1 (f (+ 1 (times n 3)))))))
|
||
|
f)
|
||
|
```
|
||
|
|
||
|
Renaming all variables and turning it into a lambda gives us:
|
||
|
```scheme
|
||
|
(begin
|
||
|
(define (a b c)
|
||
|
(if (zero? c)
|
||
|
0
|
||
|
(+ b (a b (- c 1)))))
|
||
|
(define (b c d)
|
||
|
(if (zero? c)
|
||
|
0
|
||
|
(+ 1 (b (- c d) d))))
|
||
|
(define (c d)
|
||
|
(if (zero? (- d 1))
|
||
|
0
|
||
|
(if (even? d)
|
||
|
(+ 1 (c (b d 2)))
|
||
|
(+ 1 (c (+ 1 (a d 3)))))))
|
||
|
c)
|
||
|
```
|
||
|
|
||
|
### Flag
|
||
|
IGCTF{KMCxgtSxUqwVuZbqQZkg}
|
||
|
|
||
|
-------
|
||
|
## Challenge 3
|
||
|
### Difficulty
|
||
|
- Hard (75 points)
|
||
|
|
||
|
### How To Solve
|
||
|
We can start working from the solution to Challenge 1. Two problems need to be solved
|
||
|
|
||
|
1) We can't use define to bind variables, and we don't have any let either. We can work around this by using lambdas instead to bind values.
|
||
|
2) Without define or letrec, we can't explicitly do recursion. Writing a fixed-point/Y combinator can help us.
|
||
|
|
||
|
First, let's rewrite the solution from the first challenge using a Y combinator, ignoring the other constraints. This eliminates all explicit recursion, which is what we need define for.
|
||
|
|
||
|
```scheme
|
||
|
(define (collatz n)
|
||
|
(define Y
|
||
|
(lambda (le)
|
||
|
((lambda (f) (f f))
|
||
|
(lambda (f)
|
||
|
(le (lambda (x) ((f f) x)))))))
|
||
|
(define (collatz-rec f)
|
||
|
(lambda (n)
|
||
|
(if (zero? (- n 1))
|
||
|
0
|
||
|
(if (even? n)
|
||
|
(+ 1 (f (/ n 2)))
|
||
|
(+ 1 (f (+ 1 (* n 3))))))))
|
||
|
((Y collatz-rec) n))
|
||
|
```
|
||
|
|
||
|
Now all we need to do is apply two transformations:
|
||
|
1) Replace defines by lambdas, just as you can replace `let` by a lambda application.
|
||
|
2) Rename our variables.
|
||
|
|
||
|
The first transformation gives us the following code:
|
||
|
```scheme
|
||
|
(define (collatz n)
|
||
|
((lambda (Y collatz-rec)
|
||
|
((Y collatz-rec) n))
|
||
|
(lambda (le)
|
||
|
((lambda (f) (f f))
|
||
|
(lambda (f)
|
||
|
(le (lambda (x) ((f f) x))))))
|
||
|
(lambda (f)
|
||
|
(lambda (n)
|
||
|
(if (zero? (- n 1))
|
||
|
0
|
||
|
(if (even? n)
|
||
|
(+ 1 (f (/ n 2)))
|
||
|
(+ 1 (f (+ 1 (* n 3))))))))))
|
||
|
```
|
||
|
|
||
|
Finally, we can rename our variables to the ones required by the challenge and get rid of that top level define. We only have 3 variable names, but if we play it smart that is sufficient. This snipped yields the flag:
|
||
|
```scheme
|
||
|
(lambda (a)
|
||
|
((lambda (b c)
|
||
|
((b c) a))
|
||
|
(lambda (b)
|
||
|
((lambda (c) (c c))
|
||
|
(lambda (c)
|
||
|
(b (lambda (a) ((c c) a))))))
|
||
|
(lambda (b)
|
||
|
(lambda (c)
|
||
|
(if (zero? (- c 1))
|
||
|
0
|
||
|
(if (even? c)
|
||
|
(+ 1 (b (/ c 2)))
|
||
|
(+ 1 (b (+ 1 (* c 3))))))))))
|
||
|
```
|
||
|
|
||
|
### Flag
|
||
|
IGCTF{MEzFXubIUSRRLYQuJfdm}
|