;; collatz.hs — Collatz (3n+1) sequences.

(define
  hk-as-list
  (fn
    (xs)
    (cond
      ((and (list? xs) (= (first xs) "[]")) (list))
      ((and (list? xs) (= (first xs) ":"))
        (cons (nth xs 1) (hk-as-list (nth xs 2))))
      (:else xs))))

(define
  hk-prog-val
  (fn
    (src name)
    (hk-deep-force (get (hk-eval-program (hk-core src)) name))))

(define
  hk-col-src
  "collatz 1 = [1]\ncollatz n = if n `mod` 2 == 0\n            then n : collatz (n `div` 2)\n            else n : collatz (3 * n + 1)\ncollatzLen n = length (collatz n)\n")

(hk-test
  "collatz 1 = [1]"
  (hk-as-list (hk-prog-val (str hk-col-src "r = collatz 1\n") "r"))
  (list 1))

(hk-test
  "collatz 2 = [2,1]"
  (hk-as-list (hk-prog-val (str hk-col-src "r = collatz 2\n") "r"))
  (list 2 1))

(hk-test
  "collatz 4 = [4,2,1]"
  (hk-as-list (hk-prog-val (str hk-col-src "r = collatz 4\n") "r"))
  (list 4 2 1))

(hk-test
  "collatz 6 starts 6,3,10"
  (hk-as-list (hk-prog-val (str hk-col-src "r = take 3 (collatz 6)\n") "r"))
  (list 6 3 10))

(hk-test
  "collatz 8 = [8,4,2,1]"
  (hk-as-list (hk-prog-val (str hk-col-src "r = collatz 8\n") "r"))
  (list 8 4 2 1))

(hk-test
  "collatzLen 1 = 1"
  (hk-prog-val (str hk-col-src "r = collatzLen 1\n") "r")
  1)

(hk-test
  "collatzLen 2 = 2"
  (hk-prog-val (str hk-col-src "r = collatzLen 2\n") "r")
  2)

(hk-test
  "collatzLen 4 = 3"
  (hk-prog-val (str hk-col-src "r = collatzLen 4\n") "r")
  3)

(hk-test
  "collatzLen 8 = 4"
  (hk-prog-val (str hk-col-src "r = collatzLen 8\n") "r")
  4)

(hk-test
  "collatzLen 16 = 5"
  (hk-prog-val (str hk-col-src "r = collatzLen 16\n") "r")
  5)

(hk-test
  "collatz last is always 1"
  (hk-prog-val (str hk-col-src "r = last (collatz 27)\n") "r")
  1)

(hk-test
  "collatz 3 = [3,10,5,16,8,4,2,1]"
  (hk-as-list (hk-prog-val (str hk-col-src "r = collatz 3\n") "r"))
  (list 3 10 5 16 8 4 2 1))

{:fails hk-test-fails :pass hk-test-pass :fail hk-test-fail}
