LINUX.ORG.RU

История изменений

Исправление nezamudich, (текущая версия) :

Наговнякал, не приходя в сознание:

type GenState = (Int, Int)

genNext :: Int -> Int -> Int -> GenState -> GenState
genNext a b m (xn, xn') = let xn'' = (a * xn + b * xn') `mod` m
                          in xn'' `seq` (xn', xn'')

floyd :: Eq a => (a -> a) -> a -> (Int, a)
floyd f x0 = z `seq` (go2 (f z) 1, z)
  where
    z = go1 (f x0) (f (f x0))
    go1 x y | x == y = x
            | otherwise = go1 (f x) (f (f y))
    go2 x n | x == z = n
            | otherwise = go2 (f x) (n + 1)

main :: IO ()
main = do
  let a = 2
      b = 3
      m = 23
      x0 = (1, 1)
  print . fst $ floyd (genNext a b m) x0 -- Output: 176

Думаю, на списках было бы идиоматичнее сделать. Но, как сделал, так сделал.

Исходная версия nezamudich, :

Наговнякал, не приходя в сознание:

type GenState = (Int, Int)

genNext :: Int -> Int -> Int -> GenState -> GenState
genNext a b m (xn, xn') = let xn'' = (a * xn + b * xn') `mod` m
                          in xn'' `seq` (xn', xn'')

genSeed :: Int -> Int -> GenState
genSeed = (,)

genExtract :: GenState -> Int
genExtract = fst

floyd :: Eq a => (a -> a) -> a -> (Int, a)
floyd f x0 = z `seq` (go2 (f z) 1, z)
  where
    z = go1 (f x0) (f (f x0))
    go1 x y | x == y = x
            | otherwise = go1 (f x) (f (f y))
    go2 x n | x == z = n
            | otherwise = go2 (f x) (n + 1)

main :: IO ()
main = do
  let a = 2
      b = 3
      m = 23
      x0 = (1, 1)
  print . fst $ floyd (genNext a b m) x0 -- Output: 176

Думаю, на списках было бы идиоматичнее сделать. Но, как сделал, так сделал.