81 lines
2.5 KiB
Plaintext
81 lines
2.5 KiB
Plaintext
= Collatz Chains in Haskell
|
|
|
|
== Title header
|
|
|
|
This is a literate haskell blog post. You can load and run this code!
|
|
|
|
The Simplest Math Problem No One Can Solve - Collatz Conjecture
|
|
<https://youtu.be/094y1Z2wpJg>
|
|
|
|
Why do we want to do this?
|
|
|
|
> collatzStep :: Integer -> Integer
|
|
> collatzStep n
|
|
> | even n = n `div` 2
|
|
> | odd n = 3 * n + 1
|
|
|
|
With this, we can iterate over it.
|
|
|
|
> collatzStep' :: Integer -> Integer
|
|
> collatzStep' n
|
|
> | n == 1 = error "done"
|
|
> | even n = n `div` 2
|
|
> | odd n = 3 * n + 1
|
|
|
|
> result :: [Integer]
|
|
> result = iterate collatzStep' 5
|
|
|
|
|
|
collatz collect
|
|
generate the collatz sequence and return it
|
|
|
|
> cc :: Integer -> [Integer]
|
|
> cc n = cc' [] n
|
|
> where
|
|
> cc' :: [Integer] -> Integer -> [Integer]
|
|
> cc' acc n
|
|
> | n == 1 = acc <> [1]
|
|
> | n == 0 = acc <> [0]
|
|
> | n == (-1) = acc <> [-1]
|
|
> | n == (-5) = acc <> [-5]
|
|
> | n == (-17) = acc <> [-17]
|
|
> | even n = cc' acc' (n `div` 2)
|
|
> | odd n = cc' acc' (3*n + 1)
|
|
> where acc' = acc <> [n]
|
|
|
|
> a :: [Integer]
|
|
> a = reverse $ cc $ 2^1_000+1
|
|
|
|
> b :: [Integer]
|
|
> b = reverse $ cc $ 2^1_000+2
|
|
|
|
> comparingChains :: [Bool]
|
|
> comparingChains = zipWith (==) a b
|
|
|
|
Now if we collect the chain lengths of large numbers we see something slightly horrifying:
|
|
|
|
> x = map (length . cc) [2^1_000+10..]
|
|
|
|
This prints us the list of lengths of the chain as:
|
|
[7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7430,7249,7249,7249,7249,7249,7249,7249,7249,7249,7430,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7430,7430,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7430,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7430,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7430,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249,7249...]
|
|
|
|
λ> cc 13
|
|
[13,40,20,10,5,16,8,4,2,1]
|
|
λ> cc 12
|
|
[12,6,3,10,5,16,8,4,2,1]
|
|
|
|
Now this makes sense with small numbers.
|
|
But I find it weird with large numbers.
|
|
|
|
> f :: Integer -> Integer
|
|
> f n = s 1 n
|
|
> where
|
|
> s :: Integer -> Integer -> Integer
|
|
> s i n
|
|
> | n == 1 = i
|
|
> | n == 0 = i
|
|
> | n == (-1) = i
|
|
> | n == (-5) = i
|
|
> | n == (-17) = i
|
|
> | even n = s (succ i) (n `div` 2)
|
|
> | odd n = s (succ i) (3 * n + 1) |