简体   繁体   中英

Questions regarding Haskell solution of Project Euler 14

This is the Question 14 .

import Data.Array
import Data.List
import Data.Ord (comparing)

syrs n = a
  where 

    -- For those who don't want to lookup array in the reference
    -- the following line creates an array indexed from 1 to n 
    -- using the list provided. And a ! x is the syntax for a[x] in some other languages.

    a = listArray (1,n) $ 0 : [1 + syr n x | x <- [2..n]]   -------- 2
    syr n x = if x' <= n                                    -------- 1
            then a ! x'                                     -------- 1
            else 1 + syr n x'                               
      where 
        x' = if even x
             then x `div` 2
             else 3 * x + 1

main = print $ maximumBy (comparing snd) $ assocs $ syrs 1000000

Above is the suggested solution for Project Euler Q14 on wiki.haskell.org . The algorithm is largely the same to mine (but mine runs forever while this runs in 2sec).

Question:

In line 2, it calls syr nx . Suppose x = 3 , x' = 10 , 10 < n , it will proceed with then clause : a ! 10 a ! 10 . But at this time, a ! 10 a ! 10 is not yet calculated. How does the program proceed then?


Haskell98 Report states , " array is strict in the bounds argument and in the indices of the association list, but nonstrict in the values" . listArray is similar.

What this means is that the structure of an array is created right away – ie the n "cells" that are to hold the values – but the values themselves are lazy, as is usual in Haskell.

Your function's definition, simplified, is

import Data.Array
import Data.List
import Data.Ord (comparing)

syrs n = 
    a
    where 
    a = listArray (1,n) $ 0 : map syr [2..n]
    syr x = 
        if y <= n then 1 + a ! y else 1 + syr y
        where 
        y = if even x then x `div` 2 else 3 * x + 1

With it,

a ! i === (0 : map syr [2..n]) !! (i-1) , i = 1..n
      === if i==1 then 0
                  else (map syr [2..n]) !! (i-2) , i = 2..n
      === if i==1 then 0
                  else syr i

When the value a ! 10 a ! 10 is needed , it is calculated according to the above definition, and then stored under the index 10 in the array a . Calculating it will proceed in the usual fashion, viz. a ! 5 a ! 5 will be demanded, triggering its calculation, and conditionally storing the result in the array.

So, in pseudocode,

syr x = a ! x     , if already calculated and stored in the array
      = 1 + syr y , storing the result in the array under x, if x <= n
      = 1 + syr y , otherwise
  where
  y = ....

The usual, recursive, lazy evaluation of Haskell.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM