哈斯克尔:如果我尝试超过55步,骑士之旅永远不会结束?

时间:2016-11-06 12:52:39

标签: algorithm haskell

这是我的代码:

public void listAll() {
    if (songs.isEmpty()) // cant get this to check if there are songs on the
    {
        System.out.print("There are no songs on the playlist");
    } else {
        for (Song a : songs) {
            System.out.print(a);
        }
    }

}

你知道为什么它永远不会完成(也许我可以等待更多......)?你有其他解决方案来实现相同的强力算法,但会更快吗?

1 个答案:

答案 0 :(得分:2)

它会终止(它在我的电脑上运行大约1分钟)并产生正确的答案。

加快速度的一种简单方法是在列表前面添加一个新移动(并在打印前反转结果)。添加第一个元素需要恒定的时间,而在列表的后面追加一个元素的大小是线性的。

您的代码中还存在一个错误:m3m7相同。修复此错误并将新移动添加到列表的前面后,代码将在一秒钟内运行:

maxX = 8
maxY = 8
maxSteps = 60

move :: [(Int, Int)] -> [( Int, Int)]
move list 
   | lastX > maxX || lastY > maxY || lastX <= 0 || lastY <= 0 = []
   | lastMove `elem` (tail list) = []
   | length list == maxSteps = list
   | length m1 == maxSteps = m1
   | length m2 == maxSteps = m2
   | length m3 == maxSteps = m3
   | length m4 == maxSteps = m4
   | length m5 == maxSteps = m5
   | length m6 == maxSteps = m6
   | length m7 == maxSteps = m7
   | length m8 == maxSteps = m8
   | otherwise = []
   where lastMove = head list
         lastX = fst lastMove
         lastY = snd lastMove
         m1 = move ((lastX + 1, lastY + 2) : list)
         m2 = move ((lastX + 2, lastY + 1) : list)
         m3 = move ((lastX - 1, lastY + 2) : list)
         m4 = move ((lastX - 2, lastY + 1) : list)
         m5 = move ((lastX + 1, lastY - 2) : list)
         m6 = move ((lastX + 2, lastY - 1) : list)
         m7 = move ((lastX - 1, lastY - 2) : list)
         m8 = move ((lastX - 2, lastY - 1) : list)
y = move [(1, 1)]
main = print $ reverse y    

我做了一些更改。首先,我完全摆脱了#34;手动&#34;每步增加8个可能的动作。我们可以使用列表来做到这一点。这种方法有助于避免这样的错误。事实证明,执行时间取决于检查新移动的顺序。这个版本在大约一分钟内找到了一个公开的游览(在我看来,它比原始代码更具可读性):

maxX = 8
maxY = 8
maxSteps = 64
shifts = [-1, 1, -2, 2]

move :: [(Int, Int)] -> [(Int, Int)]
move path
   | lastX > maxX || lastY > maxY || lastX <= 0 || lastY <= 0 = []
   | lastMove `elem` tail path = []
   | length path == maxSteps = path
   | not (null validNewPaths) = head validNewPaths
   | otherwise = []
   where lastMove@(lastX, lastY) = head path
         newPaths = [(lastX + x, lastY + y) : path | x <- shifts, y <- shifts, abs x /= abs y]
         validNewPaths = filter (\xs -> length xs == maxSteps) (map move newPaths) 

main = print $ reverse (move [(1, 1)])