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.