作为一些"自我强加的家庭作业的一部分"在Haskell研究中,我做了河内塔的经典解决方案:
doHanoi :: Int -> Int -> Int -> [(Int, Int)]
doHanoi 0 _ _ = []
doHanoi n from to = first ++ [(from, to)] ++ last
where
using = 3 - from - to;
first = doHanoi (n - 1) from using;
last = doHanoi (n - 1) using to
(假设磁盘doHanoi n from to using
处于挂钩0.. n - 1
,from
的含义得到了运动的后果,我们需要将它们移到挂钩to
。)
这给出了一系列动作,例如,
>>> doHanoi 3 0 2
[(0,2),(0,1),(2,1),(0,2),(1,0),(1,2),(0,2)]
然后我想看看我是否可以将输出转换为配置集(即,最初,所有环都在左侧挂钩上,然后是中间配置,最后所有环都在右侧挂钩上)。我可以通过编写changeConfig
函数
changeConfig :: [[Int]] -> (Int, Int) -> [[Int]]
changeConfig [e0:e0s, e1s, e2s] (0, 1) = [e0s, e0:e1s, e2s]
changeConfig [e0:e0s, e1s, e2s] (0, 2) = [e0s, e1s, e0:e2s]
changeConfig [e0s, e1:e1s, e2s] (1, 0) = [e1:e0s, e1s, e2s]
changeConfig [e0s, e1:e1s, e2s] (1, 2) = [e0s, e1s, e1:e2s]
changeConfig [e0s, e1s, e2:e2s] (2, 0) = [e2:e0s, e1s, e2s]
changeConfig [e0s, e1s, e2:e2s] (2, 1) = [e0s, e2:e1s, e2s]
然后使用scanl
:
>>> scanl changeConfig [[0.. 2], [], []] (doHanoi 3 0 2 1)
[[[0,1,2],[],[]],[[1,2],[],[0]],[[2],[1],[0]],[[2],[0,1],[]],[[],[0,1],[2]],[[0],[1],[2]],[[0],[],[1,2]],[[],[],[0,1,2]]]
虽然这有效,但我认为我在changeConfig
中遗漏了一些内容:这只是对所有配置的详尽列举,在具有某种形式的循环对称的设置中,恰好有效,因为那里是三个钉子,并且不会很好地扩展(就LOC而言)。什么是" Haskellic"写它的方式?
答案 0 :(得分:1)
感谢chepner和jberryman的亲切帮助,这就是我想出来的。
找到动作的功能没有改变:
doHanoi :: Int -> Int -> Int -> [(Int, Int)]
doHanoi 0 _ _ = []
doHanoi n from to = first ++ [(from, to)] ++ last
where
using = 3 - from - to;
first = doHanoi (n - 1) from using;
last = doHanoi (n - 1) using to
现在是辅助函数,changePeg es i from to new_e
将输出返回到peg i
,假设它包含元素es
,其索引为i
,移动来自from
} to
和new_e
元素。
changePeg :: [Int] -> Int -> Int -> Int -> Int -> [Int]
changePeg es i from to new_e
| i == from = tail es
| i == to = new_e: es
| otherwise = es
使用此功能,changeConfig
变为
changeConfig :: [[Int]] -> (Int, Int) -> [[Int]]
changeConfig es (from, to) = new_es where
new_e = head $ es !! from;
new_es = [changePeg (es !! i) i from to new_e | i <- [0.. 2]]
和以前一样,解决方案可以找到
>>> scanl changeConfig [[0.. 2], [], []] (doHanoi 3 0 2)
[[[0,1,2],[],[]],[[1,2],[],[0]],[[2],[1],[0]],[[2],[0,1],[]],[[],[0,1],[2]],[[0],[1],[2]],[[0],[],[1,2]],[[],[],[0,1,2]]]