河内塔 - 移动列表,检查是否有效
Towers of Hanoi - List of moves, check if valid
我正在为 Haskell 中的一项编程任务而苦苦挣扎。
我必须写一个函数:
move ::([Move],Towers) -> ([Move],Towers)
它需要一个动作列表和一个游戏配置。该函数必须检查第一步是否有效,然后执行此步。您可以在下面看到该函数的可能输出。我是 Haskell 的新手,这个编程任务对我来说太难了。我不知道如何以及从哪里开始。解决该问题的基本策略是什么?我很想学,如果你能给我一些建议,我会很高兴。
谢谢
type Position = Int
type Move = (Position,Position)
type Towers = ([Int],[Int],[Int])
hanoi :: Int -> Position -> Position -> [Move]
hanoi 1 i j = [(i, j)]
hanoi n i j = (hanoi (n-1) i other) ++ [(i, j)] ++ (hanoi (n-1) other j)
where
other = 1+2+3-i-j
输出:move ::([Move],Towers) -> ([Move],Towers)
> hanoi 3 1 3 [(1,3),(1,2),(3,2),(1,3),(2,1),(2,3),(1,3)]
> move (it, ([1,2,3],[],[])) ([(1,2),(3,2),(1,3),(2,1),(2,3),(1,3)],([2,3],[],[1]))
> move it ([(3,2),(1,3),(2,1),(2,3),(1,3)],([3],[2],[1]))
> move it ([(1,3),(2,1),(2,3),(1,3)],([3],[1,2],[]))
> move ([(1,4)],([3],[1,2],[])) ([],*** Exception: Move not valid!
> move ([(1,2),(1,3)],([3,4],[1,2],[])) ([(2,3)],([4],*** Exception: Disc is to big!
move ::([Move],Towers) -> ([Move],Towers)
move ([],t) = ([],t)
move (x:xs,t) = move (xs,move1 x t)
move1::Move->Towers->Towers
move1 (i,j) (a,b,c)
| i==1 && j==2 && not (null a) = if inf a b then (tail a,head a:b,c) else error "Disk too large"
| i==1 && j==3 && not (null a) = if inf a c then (tail a,b,head a:c) else error "Disk too large"
| i==2 && j==1 && not (null b) = if inf b a then (head b:a,tail b,c) else error "Disk too large"
| i==2 && j==3 && not (null b) = if inf b c then (a,tail b,head b:c) else error "Disk too large"
| i==3 && j==1 && not (null c) = if inf c a then (head c:a,b,tail c) else error "Disk too large"
| i==3 && j==2 && not (null c) = if inf c b then (a,head c:b,tail c) else error "Disk too large"
| otherwise = error "Move not valid"
inf :: [Int]->[Int]->Bool
inf a b = null b || head a < minimum b
我正在为 Haskell 中的一项编程任务而苦苦挣扎。 我必须写一个函数:
move ::([Move],Towers) -> ([Move],Towers)
它需要一个动作列表和一个游戏配置。该函数必须检查第一步是否有效,然后执行此步。您可以在下面看到该函数的可能输出。我是 Haskell 的新手,这个编程任务对我来说太难了。我不知道如何以及从哪里开始。解决该问题的基本策略是什么?我很想学,如果你能给我一些建议,我会很高兴。
谢谢
type Position = Int
type Move = (Position,Position)
type Towers = ([Int],[Int],[Int])
hanoi :: Int -> Position -> Position -> [Move]
hanoi 1 i j = [(i, j)]
hanoi n i j = (hanoi (n-1) i other) ++ [(i, j)] ++ (hanoi (n-1) other j)
where
other = 1+2+3-i-j
输出:move ::([Move],Towers) -> ([Move],Towers)
> hanoi 3 1 3 [(1,3),(1,2),(3,2),(1,3),(2,1),(2,3),(1,3)]
> move (it, ([1,2,3],[],[])) ([(1,2),(3,2),(1,3),(2,1),(2,3),(1,3)],([2,3],[],[1]))
> move it ([(3,2),(1,3),(2,1),(2,3),(1,3)],([3],[2],[1]))
> move it ([(1,3),(2,1),(2,3),(1,3)],([3],[1,2],[]))
> move ([(1,4)],([3],[1,2],[])) ([],*** Exception: Move not valid!
> move ([(1,2),(1,3)],([3,4],[1,2],[])) ([(2,3)],([4],*** Exception: Disc is to big!
move ::([Move],Towers) -> ([Move],Towers)
move ([],t) = ([],t)
move (x:xs,t) = move (xs,move1 x t)
move1::Move->Towers->Towers
move1 (i,j) (a,b,c)
| i==1 && j==2 && not (null a) = if inf a b then (tail a,head a:b,c) else error "Disk too large"
| i==1 && j==3 && not (null a) = if inf a c then (tail a,b,head a:c) else error "Disk too large"
| i==2 && j==1 && not (null b) = if inf b a then (head b:a,tail b,c) else error "Disk too large"
| i==2 && j==3 && not (null b) = if inf b c then (a,tail b,head b:c) else error "Disk too large"
| i==3 && j==1 && not (null c) = if inf c a then (head c:a,b,tail c) else error "Disk too large"
| i==3 && j==2 && not (null c) = if inf c b then (a,head c:b,tail c) else error "Disk too large"
| otherwise = error "Move not valid"
inf :: [Int]->[Int]->Bool
inf a b = null b || head a < minimum b