簡體   English   中英

使用 haskell 投影歐拉 25 的慢速解決方案

[英]Slow solution to project euler 25 using haskell

我是 Haskell 語言的新手,為了學習我想我會跳進一些歐拉項目。 Project Euler 25中,我們的任務是執行以下操作:

第 12 項 F12 是第一個包含三位數字的項。 斐波那契數列中包含 1000 位數字的第一項的索引是多少?

這是我對問題的解決方案:

fibGen :: Int -> Int
fibGen 0 = 0
fibGen 1 = 1
fibGen n = fibGen (n-1) + fibGen (n-2)

stepper n
  | length (show ( fibGen n )) >= 1000 = n
  | otherwise = stepper n + 1

這里n只是序列的起點。 但是這種方法非常慢,在我決定嘗試另一種方法之前已經運行了一個多小時。 然后我找到了另一個解決方案,如下所示:

fibs = 0:1:(zipWith (+) fibs (tail fibs))
t = 10^999

problem_25 = length w
    where
      w = takeWhile (< t) fibs

這非常快。

所以我的問題是第一種方法有什么問題導致它如此緩慢。

所以我的問題是第一種方法有什么問題導致它如此緩慢。

您的第一種方法在stepper的定義中有一個無限循環,但是,即使沒有無限循環,由於指數分支策略,它也需要相當長的時間。


您的第一種方法導致指數遞歸。 實際上,除了兩個基本情況,所有其他情況都會導致兩個額外的調用:

fibGen :: Int -> Int
fibGen 0 = 0
fibGen 1 = 1
fibGen n = fibGen (n-1) + fibGen (n-2)

所以這意味着以fibGen 5為例,我們將評估為:

fibGen 5
  - fibGen 4
    - fibGen 3
      - fibGen 2
        - fibGen 1
        - fibGen 0
      - fibGen 1
    - fibGen 2
      - fibGen 1
      - fibGen 0
  - fibGen 3
    - fibGen 2
      - fibGen 1
      - fibGen 0
    - fibGen 1

因此,為了計算fibGen 5 ,我們將總共進行 15 次調用。 一個用於fibGen 4 ,兩個用於fibGen 3 ,三個用於fibGen 2 ,五個用於fibGen 1 ,三個用於fibGen 0

每次我們增加n時,我們的調用量幾乎會翻倍。 很明顯,對於一個大的n ,調用的數量是巨大的,現代機器仍然無法處理它。

此外,您的stepper function 被定義為無限循環。 實際上,您的 function 的一個更詳細的變體是:

stepper n
  | length (show ( fibGen n )) >= 1000 = n
  | otherwise = (stepper n) + 1

所以這意味着如果你計算stepper n ,並且約束失敗,你再次調用stepper n ,然后你會在這個結果上加1 ,但是你會陷入一個無限循環。

您可以通過添加括號來解決此問題:

stepper n
  | length (show ( fibGen n )) >= 1000 = n
  | otherwise = stepper (n + 1)

現在最終程序將終止,但由於遞歸定義中的分支,這將花費很多時間。 請注意,每次調用fibGen時,它都會再次分支,這意味着即使我們修復了無限循環,如果我們調用fibGen 5 ,那么如果我們稍后調用fibGen 6 ,我們將再次完成所有工作來計算fibGen 5計算fibGen 6 因此,我們在這里不使用記憶。


另一方面,您的第二個斐波那契程序會生成一個列表,並重用列表中的結果。 因此fib將評估為:

   0 : 1 : zipWith …
-> 0 : 1 : 1 : zipWith …
-> 0 : 1 : 1 : 2 : zipWith …
-> 0 : 1 : 1 : 2 : 3 : zipWith …
-> 0 : 1 : 1 : 2 : 3 : 5 : zipWith …

所以這不會受到分支的影響,因為它會重用列表中已經存在的結果。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM