2009-12-03 56 views
1

我有項目歐拉question no. 74下面的遞歸函數:列表建設在Haskell

chain n | n `elem` xs = length xs 
     | otherwise = (chain (sumFac n)) : xs 
fac n = foldl (*) 1 $ enumFromTo 1 n 
sumFac n = sum $ map fac $ decToList n 

除了我不知道正確的語法來構建上chain n列表,以便它建立起來的xs列表,並然後返回xs的長度,一旦數字再次出現在xs的列表中並開始循環。

我如何糾正我的鏈功能,使其工作?

回答

5

使用一個輔助功能:

chain n = go [n] 
    where go xs | next `elem` xs = reverse $ next : xs 
       | otherwise  = go (next:xs) 
      where next = sumFac $ head xs 

fac = product . enumFromTo 1 

sumFac = sum . map fac . map digitToInt . show 

正如你所看到的,你接近你想要的東西,但你模糊了兩者結合起來。

爲了好玩,我扔了點無關當量facsumFac

下面是一個使用view pattern自由點清晰度(但是,唉,似乎胳肢#2395):

{-# LANGUAGE ViewPatterns #-} 

chain = head . filter hasDup . tail . inits . iterate sumFac 
    where hasDup (reverse -> (x:xs)) = x `elem` xs 
+0

我並不十分精通點自由符號的方式。有沒有比'$'更強大的語法糖之外的簡單解釋? – 2009-12-03 16:04:08

+0

@Jonno:'\ x - > f(g x)'=='\ x - >(f。g)x' =='f。g' - 因此刪除了「點」「x」,使其無點。 – ephemient 2009-12-03 16:10:00

+0

@gbacon:無論如何,你爲什麼需要視圖模式? '鏈n = let l =迭代sumFac n在$頭$ $過濾器(uncurry elem)$ zip l $ inits l' ...雖然我猜這不是無點。 – ephemient 2009-12-03 17:03:02

0

不知道如果這很簡單,但你沒有指定你想要一個頭部和尾部,而不是參數中的整個列表。

chain [n:xs] | n `elem` xs = length xs 
      | otherwise = chain (sumFac n) : xs 
fac n = foldl (*) 1 $ enumFromTo 1 n 
sumFac n = sum $ map fac $ decToList n 

我沒有decToList,所以我沒有測試,如果這工作與否。它雖然很酷,但我學到了很多東西。

+0

decToList只是讓一個數字號碼的清單,我想的頭和尾在這種情況下列表是無關緊要的 – 2009-12-03 15:18:27

+0

如果您使用xs然後頭vs尾是非常重要的。至少這是我嘗試這個時遇到的第一個錯誤。 – 2009-12-03 16:29:08

+0

decToList =返回 - ? – codebliss 2009-12-07 01:01:38

1

我覺得你的「連鎖」功能很混亂。你需要重新考慮它。您在其中使用的值「xs」似乎不在範圍內。 「xs」從哪裏來?據推測它應該是一個論據。

更好的方法是建立由問題生成的無限數字列表,然後檢測其中的循環。您可以使用起始值「n」獲得無限列表

numberSequence n = iterate sumFac n 

然後查找週期。你必須檢查每個號碼對所有前面的數字。一種簡單但低效的方法是隨時建立一個列表,根據當前列表檢查每個數字,然後在遞歸調用中將該數字前置到列表中。更有效的解決方案是使用Data.Set。

順便說一下,fac n = product [1..n]。你的版本可以工作,但它非常冗長。 (實際上,如果你用「產品」的定義來代替「des」「[1..n]」,你會得到你的版本)。

+0

我使用'foldl'因爲內存優化。它幾乎保證永遠不會導致堆棧溢出。 – 2009-12-03 15:29:46

+0

我建議閱讀這篇文章:http://www.haskell.org/haskellwiki/Foldr_Foldl_Foldl%27,通過使用嚴格摺疊foldl,我的函數不同於普通的'product = foldl(*)1'。 – 2009-12-05 14:11:33