Maze solving: Difference between revisions

Content added Content deleted
No edit summary
(→‎{{header|Haskell}}: Adjusted some names to side-step the wiki formatting issue)
Line 1,608: Line 1,608:
<lang haskell>#!/usr/bin/runhaskell
<lang haskell>#!/usr/bin/runhaskell


import Data.Maybe
import Data.Maybe (fromMaybe)


-- given two points, returns the average of them
-- given two points, returns the average of them
average :: (Int, Int) -> (Int, Int) -> (Int, Int)
average :: (Int, Int) -> (Int, Int) -> (Int, Int)
average (x, y) (x', y') = ((x + x') `div` 2, (y + y') `div` 2)
average (x, y) (x_, y_) = ((x + x_) `div` 2, (y + y_) `div` 2)


-- given a maze and a tuple of position and wall position, returns
-- given a maze and a tuple of position and wall position, returns
Line 1,630: Line 1,630:
-- given a maze and a position, draw a '*' at that position in the maze
-- given a maze and a position, draw a '*' at that position in the maze
draw :: [String] -> (Int, Int) -> [String]
draw :: [String] -> (Int, Int) -> [String]
draw maze (x,y) = substitute maze y $ substitute row x '*'
draw maze (x, y) =
where row = maze !! y
let row = maze !! y
in substitute maze y $ substitute row x '*'


-- given a maze, a previous position, and a list of tuples of potential
-- given a maze, a previous position, and a list of tuples of potential
-- new positions and their wall positions, returns the solved maze, or
-- new positions and their wall positions, returns the solved maze, or
-- None if it cannot be solved
-- None if it cannot be solved
tryMoves :: [String] -> (Int, Int) -> [((Int, Int), (Int, Int))] -> Maybe [String]
tryMoves :: [String]
-> (Int, Int)
-> [((Int, Int), (Int, Int))]
-> Maybe [String]
tryMoves _ _ [] = Nothing
tryMoves _ _ [] = Nothing
tryMoves maze prevPos ((newPos,wallPos):more) =
tryMoves maze prevPos ((newPos, wallPos):more) =
case solve' maze newPos prevPos
case solve_ maze newPos prevPos of
of Nothing -> tryMoves maze prevPos more
Nothing -> tryMoves maze prevPos more
Just maze' -> Just $ foldl draw maze' [newPos, wallPos]
Just maze_ -> Just $ foldl draw maze_ [newPos, wallPos]


-- given a maze, a new position, and a previous position, returns
-- given a maze, a new position, and a previous position, returns
-- the solved maze, or None if it cannot be solved
-- the solved maze, or None if it cannot be solved
-- (assumes goal is upper-left corner of maze)
-- (assumes goal is upper-left corner of maze)
solve' :: [String] -> (Int, Int) -> (Int, Int) -> Maybe [String]
solve_ :: [String] -> (Int, Int) -> (Int, Int) -> Maybe [String]
solve' maze (2, 1) _ = Just maze
solve_ maze (2, 1) _ = Just maze
solve' maze pos@(x, y) prevPos =
solve_ maze pos@(x, y) prevPos =
let newPositions = [(x, y - 2), (x + 4, y), (x, y + 2), (x - 4, y)]
let newPositions = [(x, y - 2), (x + 4, y), (x, y + 2), (x - 4, y)]
notPrev pos' = pos' /= prevPos
notPrev pos_ = pos_ /= prevPos
newPositions' = filter notPrev newPositions
newPositions_ = filter notPrev newPositions
wallPositions = map (average pos) newPositions'
wallPositions = map (average pos) newPositions_
zipped = zip newPositions' wallPositions
zipped = zip newPositions_ wallPositions
legalMoves = filter (notBlocked maze) zipped
legalMoves = filter (notBlocked maze) zipped
in tryMoves maze pos legalMoves
in tryMoves maze pos legalMoves
Line 1,660: Line 1,664:
-- (starts at lower right corner and goes to upper left corner)
-- (starts at lower right corner and goes to upper left corner)
solve :: [String] -> Maybe [String]
solve :: [String] -> Maybe [String]
solve maze = solve' (draw maze start) start (-1, -1)
solve maze = solve_ (draw maze start) start (-1, -1)
where
where startx = length (head maze) - 3
starty = length maze - 2
startx = length (head maze) - 3
starty = length maze - 2
start = (startx, starty)
start = (startx, starty)


-- takes unsolved maze on standard input, prints solved maze on standard output
-- takes unsolved maze on standard input, prints solved maze on standard output
main = interact main'
main =
where main' x = unlines $ fromMaybe ["can't solve"] $ solve $ lines x</lang>
let main_ = unlines . fromMaybe ["can_t solve"] . solve . lines
in interact main_

</lang>
{{out}}
{{out}}

<pre>
<pre>
+---+---+---+---+---+---+---+---+---+---+---+
+---+---+---+---+---+---+---+---+---+---+---+