如何确定"重复"假定的值的数量? Haskell中的函数?

时间:2015-09-23 19:43:46

标签: algorithm haskell

我有一个功能

f :: Eq a => a -> a

我知道它最终会重复(我不太确定这个函数是什么叫做;"定期"浮现在脑海中,但是这有点不同,不是'它),我想确定它产生多少个唯一值。

天真,像

import Data.List (nub)
length $ nub $ take n $ iterate f a0

其中a0是一些初始an是我知道的一些大数字超过f的唯一值的数量,会起作用。但是,除了有明显的缺点,我必须猜测或试错n,这是不切实际的(在我的情况下,无论如何),因为f可能是耗时的。

找到重复应用此类"重复"生成的唯一值列表的最佳方法是什么? (或者无论正确的术语是什么)Haskell中的函数?

2 个答案:

答案 0 :(得分:9)

这确实是https://en.wikipedia.org/wiki/Cycle_detection解决的问题。该页面指出了该问题的几个众所周知的解决方案。

这是一个未经测试的基本乌龟和野兔算法的Haskell实现:

floyd :: Eq a => (a -> a) -> a -> (Int, Int)
floyd f x0 = (lam, mu) where
  hare0 = head
    [t | (h, t) <- tail $ zip (iterate f x0) (iterate (f . f) x0), h == t]
  (mu, tortoise1) = head 
    [(m, t) | (m, t, h) <- zip3 [0..] (iterate f x0) (iterate f hare0), t == h]
  lam = head [l | (l, h) <- zip [1..] (iterate f (f tortoise1)), h == tortoise1]

答案 1 :(得分:2)

好的,这是我评论的非常基本的想法:

import Data.List(unfoldr, genericLength)

cycleLen :: Eq a => (a -> a) -> a -> Integer
cycleLen f a0 = 1 + genericLength (unfoldr gen [a0])
  where gen xs@(x:_) =
          let a' = f x
          in if a' `elem` xs then Nothing else Just (a',a':xs)
        gen [] = undefined

让我们用一些非常基本的功能测试它:

test :: Int -> Int
test x = (x*2+1) `mod` 10

λ> cycleLen test 0
5
λ> take 6 (iterate test 0)
[0,1,3,7,5,1]

λ> cycleLen test 4
2
λ> take 6 (iterate test 4)
[4,9,9,9,9,9]

似乎很好;)

但要注意:它肯定不是最佳方式 - 但它适用于我认为的小东西