【发布时间】:2018-06-05 16:41:55
【问题描述】:
当我尝试学习函数式编程时,我决定在 haskell 中应对代码挑战。
在挑战5时https://adventofcode.com/2017/day/5 输入数据https://adventofcode.com/2017/day/5/input 我遇到了几个问题。
这是我的代码
import Data.Array
import System.IO
listToArray l =
let n_elem = length l
pos_val = zip (range (0, n_elem)) l
in array (0, n_elem-1) pos_val
getData filename = do
s <- readFile filename
let l = map read (lines s) ::[Int]
a = listToArray l
return a
-- Part 1
updatePosArray i a =
let i_val = a ! i
in (i+i_val, a//[(i, i_val + 1)])
solution1 a n_steps i
| i >= length a || i < 0 = n_steps
| otherwise =
let ai = updatePosArray i a
in solution1 (snd ai) (n_steps+1) (fst ai)
-- Part 2
updatePosArray2 i a =
let i_val = a ! i
in
if i_val>=3 then (i+i_val, a//[(i, i_val-1)])
else (i+i_val, a//[(i, i_val+1)])
solution2 a n_steps i
| i >= length a || i < 0 = n_steps
| otherwise =
let ai = updatePosArray2 i a
in solution2 (snd ai) (n_steps+1) (fst ai)
main = do
x <- getData "/Users/lucapuggini/Documents/AdventOfCode/data/data_ch5_p1.txt"
let x_ex = array (0,4) [(0, 0), (1, 3), (2, 0), (3, 1), (4, -3)]
let n_steps_ex1 = solution1 x_ex 0 0
print $ n_steps_ex1
let n_steps1 = solution1 x 0 0
print $ n_steps1
let n_steps_ex2 = solution2 x_ex 0 0
print $ n_steps_ex2
-- very slow. Probably due to the immutable array
let n_steps2 = solution2 x 0 0
print $ n_steps2
这是我得到的结果:
lucas-MacBook-Pro:src lucapuggini$ stack runhaskell challenge5.hs
5
381680
10
stack overflow
代码运行缓慢,但这可能是意料之中的,因为我使用的是不可变数组,但堆栈溢出错误令我感到惊讶。我认为尾递归不应该发生这种情况。
最后我有两个问题:
1) 为什么会出现 stackoverflow 错误?我是否错误地使用了尾递归?
2) 运行此代码的更有效但仍然有效的方法是什么?不可变数组是一个糟糕的选择吗?
我对haskell很陌生,所以请清楚。
【问题讨论】:
-
Haskell 中的“栈”不是函数调用栈;这就是尾递归不相关的原因。
-
运行该代码的正确方法是什么?
-
这工作
lucas-MacBook-Pro:src lucapuggini$ stack ghc challenge5.hs [1 of 1] Compiling Main ( challenge5.hs, challenge5.o ) Linking challenge5 ... lucas-MacBook-Pro:src lucapuggini$ ./challenge5 5 381680 10 29717847 -
你使用的是什么 Haskell 实现,什么版本?我不认为 GHC 有 堆栈溢出错误了。
-
另外,是的,如果您正在编写这样的代码,那么使用不可变数组实际上没有任何意义。切换到可变数组,或者使用更快的纯操作,例如
Data.IntMap.Strict。
标签: arrays performance haskell recursion