48 lines
1.2 KiB
Haskell
48 lines
1.2 KiB
Haskell
|
import Data.List
|
||
|
import Data.Maybe
|
||
|
|
||
|
type Path = ([String], [(Int, Int)])
|
||
|
|
||
|
main :: IO ()
|
||
|
main = do
|
||
|
input <- lines <$> readFile "testinput"
|
||
|
let s = findLetter 'S' input
|
||
|
print $ walkTo 'E' (input, []) s
|
||
|
|
||
|
findLetter :: Char -> [String] -> (Int, Int)
|
||
|
findLetter c = f <*> fromJust . findIndex (/= Nothing) <$> map (elemIndex c)
|
||
|
where
|
||
|
f x y = (head $ catMaybes x, y)
|
||
|
|
||
|
walkTo :: Char -> Path -> (Int, Int) -> Int
|
||
|
walkTo c (field, visited) (x, y)
|
||
|
| field !! y !! x == c = 0
|
||
|
| null newCoords = (maxBound :: Int) `div` 2
|
||
|
| otherwise =
|
||
|
if length visited > lenX * lenY
|
||
|
then (maxBound :: Int) `div` 2
|
||
|
else succ $
|
||
|
minimum $
|
||
|
map (walkTo c (field, (x, y) : visited)) newCoords
|
||
|
where
|
||
|
lenX = length $ head field
|
||
|
lenY = length field
|
||
|
char = field !! y !! x
|
||
|
current =
|
||
|
if char == 'S'
|
||
|
then pred 'a'
|
||
|
else char
|
||
|
newCoords =
|
||
|
[ (x + x', y + y')
|
||
|
| x' <- [-1 .. 1]
|
||
|
, x' + x >= 0
|
||
|
, x' + x < lenX
|
||
|
, y' <- [-1 .. 1]
|
||
|
, y' + y >= 0
|
||
|
, y + y' < lenY
|
||
|
, abs x' /= abs y'
|
||
|
, let a = field !! (y + y') !! (x + x')
|
||
|
in (a `elem` ['a' .. succ current] || (a == 'E' && current == 'z'))
|
||
|
, (x + x', y + y') `notElem` visited
|
||
|
]
|