查找一系列数字的Collat​​z序列

时间:2018-11-30 08:09:38

标签: haskell sequence

我是Haskell的新手,我正在尝试做Project Euler问题14。我还没有完成该程序,但是我所做的部分没有用。这段代码应该打印出2到100之间的数字的Collat​​z序列的长度。

main = print $ collatzSeq [] [2..100]

collatzSeq xs (x:s) = collatzSeq (collatzLength x []):xs s

collatzLength x y
    | x < 2 = length (x:y)
    | even x = collatzLength (x / 2) (x / 2):y
    | otherwise = collatzLength (3 * x + 1) (3 * x + 1):y

我试图以各种方式修改代码,并且我认为问题出在collat​​zLength函数中。但是从到目前为止我对Haskell的了解来看,该功能应该可以工作,但是不能用,我也不会得到我所缺少的东西。我只是遇到一个编译时错误。

1 个答案:

答案 0 :(得分:0)

嗯,您的代码中有一些错误。对于Haskell的新手来说,这是常见的错误。我将它们列出如下:

  
      
  1. 功能应用程序始终具有左关联性,并且优先级高于所有运算符。
  2.   

因此,代码:

even x = collatzLength (x / 2) (x / 2):y

等同于

even x = (collatzLength (x / 2) (x / 2)):y

这显然是错误的,因为collatzLength的第二个参数是[Int],而不是Int

  
      
  1. (/)函数或/运算符不能应用于Int类型或Num类。
  2.   

请参见(/)应用于仅作为Fractional实例的数据类型,而不适用于Int。在您的代码中,除法仅适用于偶数,因此可以使用quot代替:

even x = collatzLength (x `quot` 2) ((x `quot` 2):y)
  
      
  1. 缺少递归函数的基本情况。
  2.   

正如talex在评论中提到的那样,递归函数collatzSeq永无止境。由于它错过了指示函数应如何结束其计算的基本情况。在您的情况下,通常检查输入列表是否为空:

collatzSeq xs []    = xs
collatzSeq xs (x:s) = collatzSeq ((collatzLength x []):xs) s

最后,最好为函数提供类型签名,以使代码清晰易读。

将它们放在一起,更正如下:

collatzSeq::[Int]->[Int]->[Int]
collatzSeq xs []    = xs
collatzSeq xs (x:s) = collatzSeq ((collatzLength x []):xs) s

collatzLength::Int->[Int]->Int
collatzLength x y
    | x < 2 = length (x:y)
    | even x = collatzLength (x `quot` 2) ((x `quot` 2):y)
    | otherwise = collatzLength (3 * x + 1) ((3 * x + 1):y)