day 15
This commit is contained in:
parent
a6421a5a35
commit
3cd7b2e5ee
4 changed files with 142 additions and 25 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,2 +1,3 @@
|
|||
**/input.txt
|
||||
**/input2.txt
|
||||
6/day-six
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
RRRRIICCFF
|
||||
RRRRIICCCF
|
||||
VVRRRCCFFF
|
||||
VVRCCCJFFF
|
||||
VVVVCJJCFE
|
||||
VVIVCCJJEE
|
||||
VVIIICJJEE
|
||||
MIIIIIJJEE
|
||||
MIIISIJEEE
|
||||
MMMISSJEEE
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
Button A: X+94, Y+34
|
||||
Button B: X+22, Y+67
|
||||
Prize: X=8400, Y=5400
|
||||
|
||||
Button A: X+26, Y+66
|
||||
Button B: X+67, Y+21
|
||||
Prize: X=12748, Y=12176
|
||||
|
||||
Button A: X+17, Y+86
|
||||
Button B: X+84, Y+37
|
||||
Prize: X=7870, Y=6450
|
||||
|
||||
Button A: X+69, Y+23
|
||||
Button B: X+27, Y+71
|
||||
Prize: X=18641, Y=10279
|
||||
141
15/solution.hs
Normal file
141
15/solution.hs
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
import qualified Data.List.Split as S
|
||||
import Data.Maybe
|
||||
import Data.List
|
||||
import Data.Array
|
||||
import Debug.Trace
|
||||
|
||||
traceOut :: Show a => a -> a
|
||||
traceOut x = (traceShow x x)
|
||||
|
||||
addFirst :: [[a]] -> a -> [[a]]
|
||||
addFirst [] x = [[x]]
|
||||
addFirst (y:ys) x = ([x] ++ y) : ys
|
||||
|
||||
split :: [Char] -> String -> [String]
|
||||
split _ [] = []
|
||||
split delims (x:xs)
|
||||
| elem x delims = [[]] ++ split delims xs
|
||||
| otherwise = addFirst (split delims xs) x
|
||||
|
||||
toTuple :: [a] -> Maybe (a, a)
|
||||
toTuple [] = Nothing
|
||||
toTuple (_:[]) = Nothing
|
||||
toTuple (x:y:_) = Just (x, y)
|
||||
|
||||
data Square = Robot | Box | BoxL | BoxR | Block | Empty deriving Eq
|
||||
|
||||
instance Show Square where
|
||||
show x
|
||||
| x == Robot = "@"
|
||||
| x == Box = "O"
|
||||
| x == BoxL = "["
|
||||
| x == BoxR = "]"
|
||||
| x == Block = "#"
|
||||
| x == Empty = "."
|
||||
|
||||
toSquare :: Char -> Maybe Square
|
||||
toSquare '@' = Just Robot
|
||||
toSquare 'O' = Just Box
|
||||
toSquare '[' = Just BoxL
|
||||
toSquare ']' = Just BoxR
|
||||
toSquare '#' = Just Block
|
||||
toSquare '.' = Just Empty
|
||||
toSquare _ = Nothing
|
||||
|
||||
data Direction = DirUp | DirDown | DirLeft | DirRight deriving Eq
|
||||
|
||||
instance Show Direction where
|
||||
show x
|
||||
| x == DirUp = "^"
|
||||
| x == DirDown = "v"
|
||||
| x == DirLeft = "<"
|
||||
| x == DirRight = ">"
|
||||
|
||||
toDirection :: Char -> Maybe Direction
|
||||
toDirection '^' = Just DirUp
|
||||
toDirection 'v' = Just DirDown
|
||||
toDirection '<' = Just DirLeft
|
||||
toDirection '>' = Just DirRight
|
||||
toDirection _ = Nothing
|
||||
|
||||
apply :: ((a -> b), (c -> d)) -> (a, c) -> (b, d)
|
||||
apply (f, g) (x, y) = (f x, g y)
|
||||
|
||||
splitInput :: [String] -> (Array (Int, Int) Square, [Direction])
|
||||
splitInput inputs = apply ((\x -> listArray ((0, 0), ((length x)-1, (length $ head x)-1)) (concat $ map (map (fromJust . toSquare)) x)) . split "\n",
|
||||
map (fromJust . toDirection) . concat . split "\n"
|
||||
) $ fromJust $ toTuple inputs
|
||||
|
||||
-- y ->
|
||||
-- x
|
||||
-- |
|
||||
-- v
|
||||
|
||||
getPushRow :: (Array (Int, Int) Square) -> Direction -> [(Int, Int)]
|
||||
getPushRow arr dir = case dir of
|
||||
DirUp -> [(x, roboty) | x <- reverse [0..robotx]]
|
||||
DirDown -> [(x, roboty) | x <- [robotx..]]
|
||||
DirLeft -> [(robotx, y) | y <- reverse [0..roboty]]
|
||||
DirRight -> [(robotx, y) | y <- [roboty..]]
|
||||
where (robotx, roboty) = (\(a, _) -> a) $ head $ filter (\(_, b) -> b==Robot) $ assocs arr
|
||||
|
||||
firstWhere :: Show a => (a -> Bool) -> [a] -> Maybe a
|
||||
firstWhere _ [] = Nothing
|
||||
firstWhere f (x:xs) = if f x then Just x else firstWhere f xs
|
||||
|
||||
addDir :: Direction -> (Int, Int) -> (Int, Int)
|
||||
addDir dir (x, y) = case dir of
|
||||
DirUp -> (x-1, y)
|
||||
DirDown -> (x+1, y)
|
||||
DirLeft -> (x, y-1)
|
||||
DirRight -> (x, y+1)
|
||||
|
||||
doMove :: (Array (Int, Int) Square) -> Direction -> (Array (Int, Int) Square)
|
||||
doMove arr dir = case arr!square of
|
||||
Empty -> arr // [(square, Box), ((addDir dir rpos), Robot), (rpos, Empty)]
|
||||
Block -> arr
|
||||
where square = fromJust $ firstWhere (\x -> arr!x==Empty || arr!x==Block) $ getPushRow arr dir
|
||||
rpos = (\(a, _) -> a) $ head $ filter (\(_, b) -> b==Robot) $ assocs arr
|
||||
|
||||
solve1 :: ((Array (Int, Int) Square), [Direction]) -> Int
|
||||
solve1 = sum . map (\(x, y) -> 100*x + y) . map (\(a, _) -> a) . filter (\(_, b) -> b==Box) . assocs . uncurry (foldl doMove)
|
||||
|
||||
printGrid :: (Array (Int, Int) Square) -> String
|
||||
printGrid arr = concat $ [concat [show (arr!(x, y)) | y <- [0..99]] ++ "\n" | x <- [0..49]]
|
||||
|
||||
consequentPushes :: (Array (Int, Int) Square) -> Direction -> [(Int, Int)] -> Maybe [(Int, Int)]
|
||||
consequentPushes arr dir = (\x -> if elem Block (map (arr!) x) then Nothing else Just x) . nub . concat . map (\(a, b) -> case arr!(a, b) of
|
||||
BoxL -> [(a, b), (a, b+1)]
|
||||
BoxR -> [(a, b), (a, b-1)]
|
||||
_ -> [(a, b)]
|
||||
) . map (addDir dir)
|
||||
|
||||
needToPush :: (Array (Int, Int) Square) -> Direction -> [(Int, Int)] -> Maybe [(Int, Int)]
|
||||
needToPush arr dir pushes = case nextPushes of
|
||||
Nothing -> Nothing
|
||||
Just xs -> if (filteredPushes == [] || filteredPushes == pushes) then Just pushes else case tail of
|
||||
Nothing -> Nothing
|
||||
Just tail' -> Just (pushes ++ filteredPushes ++ tail')
|
||||
where filteredPushes = filter (\x -> arr!x /= Empty) $ fromJust nextPushes
|
||||
nextPushes = consequentPushes arr dir pushes
|
||||
tail = needToPush arr dir filteredPushes
|
||||
|
||||
doMove2 :: (Array (Int, Int) Square) -> Direction -> (Array (Int, Int) Square)
|
||||
doMove2 arr dir = case needToPush arr dir [rpos] of
|
||||
Nothing -> arr
|
||||
Just pospos -> arr // [(pos, Empty) | pos <- pospos] // [((addDir dir pos), arr!pos) | pos <- pospos] // [(rpos, Empty)]
|
||||
where rpos = (\(a, _) -> a) $ head $ filter (\(_, b) -> b==Robot) $ assocs arr
|
||||
|
||||
solve2 :: ((Array (Int, Int) Square), [Direction]) -> Int
|
||||
solve2 = sum . map (\(x, y) -> 100*x + y) . map (\(a, _) -> a) . filter (\(_, b) -> b==BoxL) . assocs . uncurry (foldl (\x y -> doMove2 x y))
|
||||
|
||||
main :: IO()
|
||||
main = do
|
||||
fileinp1 <- readFile "input.txt"
|
||||
fileinp2 <- readFile "input2.txt"
|
||||
let parsed1 = splitInput $ S.splitOn "\n\n" fileinp1
|
||||
let parsed2 = splitInput $ S.splitOn "\n\n" fileinp2
|
||||
let solved1 = solve1 parsed1
|
||||
let solved2 = solve2 parsed2
|
||||
print solved1
|
||||
print solved2
|
||||
Loading…
Add table
Add a link
Reference in a new issue