I've found pretty simple problem on Numberphiles channel: suppose we have a recursive function $$ \begin{equation} \begin{split} f_0 &= Z ^ 2+ C \\ f_i &= f_{i-1}^2 + C \; | \; i = 1 \dots \end{split} \end{equation} $$
What values of \$ Z \$ and \$ C \$ should be \$ |\{ f_i | \; i=0..5\}| = 6 \; \cap \; f_5 = Z \$ so that firs 6 elements of the sequence are unique, except last the one which should be equal to the initial \$ Z \$. In this case, lets say that initial pair \$ Z, C \$ forms a cycle of length 6.
As you may notices, there is no solution in integer numbers \$ Z, C \in \mathbf{ℤ} \$, but there may be solution in rational numbers.
So, the final question I'm trying to answer: is there initial pair of rational numbers that forms a cycle of length 6 and which numerator and denominator doesn't exceeds 100 by module $$ Z = \frac{a}{b}, \; C = \frac{c}{d} \\ |a,c| \le 100 ,\; 0 \lt b,d \le 100 \\ a, b, c, d \in \mathbf{ℤ} $$
import Control.Monad (liftM2)
import Data.List
import Data.Maybe
import Data.Ratio
import System.IO
-- Returns list of unique normalized fractions where
-- |numerator| <= abs
-- 0 < denominator <= abs
genRange :: Integral a => a -> [Ratio a]
genRange abs = map head $ group $ sort $ liftM2 (%) numerator denominator
where numerator = [(-abs)..abs]
denominator = [1..abs]
-- Returns list of initial values (Z, C)
initials :: Integral a => a -> [(Ratio a, Ratio a)]
initials abs = liftM2 (,) zs cs
where zs = genRange abs
cs = filter (<0) zs
-- Returns sequence of values of fi, i=[1..]
f :: Integral a => Ratio a -> Ratio a -> [Ratio a]
f z c = [zn] ++ (f zn c)
where zn = z ^ 2 + c
-- Returns `Just pair`, if it forms a cycle of specified length
hasCircleF :: (Integral a) => Int -> (Ratio a, Ratio a) -> Maybe (Ratio a, Ratio a)
hasCircleF len pair
| endsWith == z && amountUnique == 6 = Just pair
| otherwise = Nothing
where (z, c) = pair
circle = take len $ (f z c)
endsWith = last $ circle
amountUnique = length $ group $ sort circle
collectMatches :: Integral a => [(Ratio a, Ratio a)]
collectMatches = mapMaybe (hasCircleF 6) (initials 100)
main :: IO ()
main = mapM_ (putStrLn . show) collectMatches
Currently, it takes half an hour on my machine.