关于Project Euler 14的Haskell解决方案的问题

时间:2015-09-13 15:25:18

标签: haskell lazy-evaluation memoization

这是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

以上是Project Euler Q14 on wiki.haskell.org的建议解决方案。该算法与我的算法大致相同(但是我的算法在2秒内运行时永远运行)。

问题:

在第2行中,它调用syr n x。假设x = 3x' = 1010 < n,它将继续then子句:a ! 10。但目前尚未计算a ! 10。那么程序如何进行呢?

1 个答案:

答案 0 :(得分:2)

Haskell98报告statesfloat scaleWidth = ((float) destWidth) / width; float scaleHeight = ((float) destHeight) / height; float scale = Math.max(scaleWidth, scaleHeight); Matrix matrix = new Matrix(); matrix.postScale(scale, scale); Bitmap roundBitmap = Bitmap.createBitmap(destWidth + 20, destHeight + 20, Bitmap.Config.ARGB_8888) // This creates a square bitmap of 220*220 BitmapShader shader = new BitmapShader(bitmap, TileMode.CLAMP, TileMode.CLAMP); // The original size of bitmap is 200*200 shader.setLocalMatrix(matrix); Paint paint = new Paint(); paint.setAntiAlias(true); paint.setShader(shader); Canvas canvas = new Canvas(roundBitmap); canvas.drawCircle((destWidth + 20) / 2, (destHeight + 20) / 2, destWidth / 2, paint) 在bounds参数和关联列表的索引中是严格的,但在值”中是非严格的。 array类似。

这意味着数组的结构是立即创建的 - 即用于保存数组的 n “cells”值 - 但本身是懒惰的,就像在Haskell中一样。

你的函数的定义是简化的

listArray

有了它,

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

当值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 时,它将根据上述定义计算,然后存储在数组a ! 10中的索引10下。计算它将以通常的方式进行,即。将要求a,触发计算,并有条件地将结果存储在数组中。

所以,在伪代码中,

a ! 5

对Haskell的通常的,递归的,懒惰的评估。