上哈斯克尔研究一些“自我施加的功课”的一部分,我做了汉诺塔的经典解决方案:转化汉诺塔运动顺序为配置顺序
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
意义GET运动假设磁盘0.. n - 1
的asequence是在PEG from
,我们需要将它们移动到挂to
。)
这给运动的序列,例如
>>> doHanoi 3 0 2
[(0,2),(0,1),(2,1),(0,2),(1,0),(1,2),(0,2)]
然后我想看看是否可以将输出转换为一组配置(即最初,所有环都位于左侧挂钩上,然后存在中间配置,最后所有环都位于右侧挂钩上)。然后我可以使用scanl
通过编写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 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”的写法?
发现能否请您记录您的功能? 'n'究竟是什么?究竟是“使用”?你在哪里找到这个算法? – dfeuer
@dfeuer对不起,我添加了一个解释。如果有其他问题,请LMK不清楚。谢谢! –
请注意,'using'不必被指定为参数;它完全由'3 - (from + to)'指定。 – chepner