גלע*_*רקן 15 algorithm haskell
这是我第一次尝试使用(我理解的)动态编程.我正试图解决这个有趣的问题:A*允许的启发式,用于在网格上滚动
该q函数尝试向后递归,跟踪骰子的方向(visited技术上是下一个单元格,但在递归方面"访问"以防止无限的来回循环).虽然我不确定它提供的答案是否是最佳解决方案,但它似乎确实提供了答案.
我希望有关如何实现某种记忆以加速它的想法 - 我试图实现类似memoized_fib(在这里看到)的东西lookup而不是成功,而不是!!映射q到组合列表(i,j)但是Nothing没有双关语意图.
Haskell代码:
import Data.List (minimumBy)
import Data.Ord (comparing)
fst3 (a,b,c) = a
rollDie die@[left,right,top,bottom,front,back] move
| move == "U" = [left,right,front,back,bottom,top]
| move == "D" = [left,right,back,front,top,bottom]
| move == "L" = [top,bottom,right,left,front,back]
| move == "R" = [bottom,top,left,right,front,back]
dieTop die = die!!2
leftBorder = max 0 (min startColumn endColumn - 1)
rightBorder = min columns (max startColumn endColumn + 1)
topBorder = endRow
bottomBorder = startRow
infinity = 6*rows*columns
rows = 10
columns = 10
startRow = 1
startColumn = 1
endRow = 6
endColumn = 6
dieStartingOrientation = [4,3,1,6,2,5] --left,right,top,bottom,front,back
q i j visited
| i < bottomBorder || i > topBorder
|| j < leftBorder || j > rightBorder = (infinity,[1..6],[])
| i == startRow && j == startColumn = (dieTop dieStartingOrientation,dieStartingOrientation,[])
| otherwise = (pathCost + dieTop newDieState,newDieState,move:moves)
where previous
| visited == (i, j-1) = zip [q i (j+1) (i,j),q (i-1) j (i,j)] ["L","U"]
| visited == (i, j+1) = zip [q i (j-1) (i,j),q (i-1) j (i,j)] ["R","U"]
| otherwise = zip [q i (j-1) (i,j),q i (j+1) (i,j),q (i-1) j (i,j)] ["R","L","U"]
((pathCost,dieState,moves),move) = minimumBy (comparing (fst3 . fst)) previous
newDieState = rollDie dieState move
main = putStrLn (show $ q endRow endColumn (endRow,endColumn))
Run Code Online (Sandbox Code Playgroud)
ham*_*mar 15
我遇到这种问题的工具是data-memocombinators库.
要使用它,只需导入Data.MemoCombinators,重命名q为其他类似的东西q'(但保留递归调用),并定义一个q像这样的新东西:
q = M.memo3 M.integral M.integral (M.pair M.integral M.integral) q'
Run Code Online (Sandbox Code Playgroud)
memo3 为每个参数给出一个三个参数函数的memoizer,给出memoizer.integral 是一个简单的积分类型的memoizer.pair 结合两个记忆器为这些类型的对组成一个记忆器.q'来获取memoized版本.就是这样.您的功能现在已被记忆.是时候测试一下了:
> :set +s
> q endRow endColumn (endRow,endColumn)
(35,[5,2,4,3,6,1],["R","R","R","R","R","U","U","U","U","U"])
(0.01 secs, 516984 bytes)
Run Code Online (Sandbox Code Playgroud)
完整代码如下:
import Data.List (minimumBy)
import Data.Ord (comparing)
import qualified Data.MemoCombinators as M
fst3 (a,b,c) = a
rollDie die@[left,right,top,bottom,front,back] move
| move == "U" = [left,right,front,back,bottom,top]
| move == "D" = [left,right,back,front,top,bottom]
| move == "L" = [top,bottom,right,left,front,back]
| move == "R" = [bottom,top,left,right,front,back]
dieTop die = die!!2
leftBorder = max 0 (min startColumn endColumn - 1)
rightBorder = min columns (max startColumn endColumn + 1)
topBorder = endRow
bottomBorder = startRow
infinity = 6*rows*columns
rows = 10
columns = 10
startRow = 1
startColumn = 1
endRow = 6
endColumn = 6
dieStartingOrientation = [4,3,1,6,2,5] --left,right,top,bottom,front,back
q = M.memo3 M.integral M.integral (M.pair M.integral M.integral) q'
where
q' i j visited
| i < bottomBorder || i > topBorder || j < leftBorder || j > rightBorder = (infinity,[1..6],[])
| i == startRow && j == startColumn = (dieTop dieStartingOrientation,dieStartingOrientation,[])
| otherwise = (pathCost + dieTop newDieState,newDieState,move:moves)
where previous
| visited == (i, j-1) = zip [q i (j+1) (i,j),q (i-1) j (i,j)] ["L","U"]
| visited == (i, j+1) = zip [q i (j-1) (i,j),q (i-1) j (i,j)] ["R","U"]
| otherwise = zip [q i (j-1) (i,j),q i (j+1) (i,j),q (i-1) j (i,j)] ["R","L","U"]
((pathCost,dieState,moves),move) = minimumBy (comparing (fst3 . fst)) previous
newDieState = rollDie dieState move
main = putStrLn (show $ q endRow endColumn (endRow,endColumn))
Run Code Online (Sandbox Code Playgroud)