; http://programmingpraxis.com/2013/06/28/a-programming-puzzle/
; Write a function f such that f(f(n)) = -n for all integers n
; Solution one "encodes" the integer into a list.
; This was the only one I came up with before looking at other solutions.
(define (f1 n)
(if (list? n)
(- (car n))
(list n)))
; Solution two "encodes" the integer into a fractional ratio.
(define (f2 n)
(if (= n 0)
0
(let ((a (abs n)))
(if (integer? a)
(let ((b (/ 1 (+ a 1))))
(if (< n 0)
(- b)
b))
(let ((b (- (/ 1 a) 1)))
(if (< n 0)
b
(- b)))))))
; Solution three uses complex numbers.
(define (f3 n)
(if (integer? n)
(+ n 0+1i)
(- (- n 0+1i))))
; This is a better one using complex numbers
(define (f4 n)
(* n 0+1i))
; A very Scheme-y solution using closures
; Works with numbers other than integers
(define (f5 n)
(if (number? n)
(lambda ()
(- n))
(n)))
; Using parity and sign...
(define (f6 n)
(cond ((and (positive? n) (even? n)) (- n 1))
((and (negative? n) (even? n)) (+ n 1))
((and (positive? n) (odd? n)) (- (- n) 1))
((and (negative? n) (odd? n)) (+ (- n) 1))
(else 0)))
(define (test f)
(let loop ((n -10))
(display n)
(display " -> ")
(display (f (f n)))
(newline)
(if (< n 10)
(loop (+ n 1))
#f))
(newline))
(test f1)
(test f2)
(test f3)
(test f4)
(test f5)
(test f6)