![](/img/trans.png)
[英]2 Dimensional Mutable Array in Haskell and coloring the output with ANSI
[英]Haskell Mutable Array not modified
我有一個可變的IOArray
來存儲我已經計算出的Collatz長度:
import Data.Array.IO
import Control.Monad
import Data.Array
p14 :: IO [Int]
p14 = do
array <- p14extra
forM_ [1..1000000] $ \i -> do
e <- readArray array i
if e == 0
then do
let col = collatz i
forM_ col $ \(v,i) -> do
writeArray array i v
else return ()
frozen <- freeze array
return $ elems frozen
-- an `IOArray` from `1` to `1000000` full of `0`
p14extra :: IO (IOArray Int Int)
p14extra = newArray (1,1000000) 0
collatz :: Int -> [(Int, Int)]
collatz n
| n == 1 = [(1,1)]
| otherwise = (n, (snd $ head hack) + 1) : hack
where
hack = collatz $ if even n then (n `div` 2) else (3 * n + 1)
其中第一個元素是要計算的數字,第二個數字是其Collatz序列的長度。
事實是,在p14
我執行writeArray array iv
但它始終包含一個零(0s)數組。 這是為什么?
我運行了您的確切代碼,發現數組已更改。
由於結尾處有很多零,因此您需要一直滾動到開頭以查找數字。
實際上,如果您替代
frozen <- freeze array
return $ elems frozen
與
sol <- getElems array
return (length . takeWhile (/=0) $ sol)
您將獲得525,這是正確的解決方案……更多有關該解決方案的說明。
但是有兩個問題:
forM_ col $ \\(v,i) -> do
,根據我的理解, (v,i)
應該是(i,v)
,就像collatz一樣,第一個值是索引,第二個是值。 forM_ [1..10]
和newArray (1,10)
運行代碼, forM_ [1..10]
得到*** Exception: Ix{Int}.index: Index (16) out of range ((1,10))
。 一旦將值再次設置為1000000
,也會發生這種情況,因為在某些情況下,為了計算數字的collatz,必須計算大於1000000
的數字的collatz。 例如,的在Collatz 837798
包括的計算1885048
后僅4個步驟。 嘗試寫入該索引會破壞事情。 對於第二種解決方案,您可以:
length . takeWhile (/=0) $ sol
之所以如此length . takeWhile (/=0) $ sol
length . takeWhile (/=0) $ sol
工作原理是,因為您使用了(v,i)
而不是(i,v)
,所以您在索引i中寫入了具有collatz序列長度i的最低編號 ,因此在索引525上得到了837799,然后從那里開始都是零,因為沒有collatz序列大於525。
我不知道您的意思是“不修改”。
使用此代碼(請注意,我已經更改了迭代和數組范圍):
import Control.Monad (forM_)
import Data.Array.IO
import Data.Array
p14 :: IO [Int]
p14 = do
array <- p14extra
forM_ [1..10] $ \i -> do
e <- readArray array i
if e == 0
then do
let col = collatz i
forM_ col $ \(v,i) -> do
writeArray array i v
else return ()
frozen <- freeze array
return $ elems frozen
p14extra :: IO (IOArray Int Int)
p14extra = newArray (1,100) 0
collatz :: Int -> [(Int, Int)]
collatz n
| n == 1 = [(1,1)]
| otherwise = (n, (snd $ head hack) + 1) : hack
where
hack = collatz $ if even n then (n `div` 2) else (3 * n + 1)
在ghci
運行p14
產生:
[1,2,4,8,16,5,10,20,40,13,26,52,17,34,11,22,7,14,28,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
萬一這是使您感到困惑的直覺:盡管p14
修改了它使用的數組,但p14extra
將不再包含該數組。 這是一個IO操作,每次運行時都會始終創建一個填充有零的新數組。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.