DEV Community

Discussion on: Advent of Code 2020 Solution Megathread - Day 22: Crab Combat

Collapse
 
bgaster profile image
Benedict Gaster • Edited

Ah today Haskell was a great choice, had fun and got it done really quick, which was lucky as spent a large amount of the day baking ginger bread houses for the kids to cover in icing and sweets :-)

parse :: String -> ([Int], [Int])
parse is = let xs = splitWhen (=="Player 2:") (lines is)
               players = (filter (/="") (tail (head xs)), head (tail xs))
           in bimap (map read) (map read) players


task1 :: ([Int], [Int]) -> Int
task1 ([], p2) = sum $ zipWith (*) p2 [length p2, length p2-1..1]
task1 (p1, [])  = sum $ zipWith (*) p1 [length p1, length p1-1..1]
task1 players = task1 (round players)
    where
        round (t:ts, t':ts') | t > t'    = (ts ++ [t,t'], ts')
                             | otherwise =  (ts, ts' ++ [t',t])

task2 = result . game S.empty
    where
        result ([], p2) = sum $ zipWith (*) p2 [length p2, length p2-1..1]
        result (p1, []) = sum $ zipWith (*) p1 [length p1, length p1-1..1]

        game _ (xs, []) = (xs, [])
        game _ ([], ys) = ([], ys)
        game s (xs, ys) | (xs, ys) `S.member` s = (xs, [])
                        | otherwise             = round (S.insert (xs, ys) s) xs ys

        round s (x:xs) (y:ys)
                | (x > length xs || y > length ys) && x < y = game s (xs, ys ++ [y, x])
                | (x > length xs || y > length ys) && x > y = game s (xs ++ [x, y], ys)
                | otherwise = case game S.empty (take x xs, take y ys) of
                    (_, []) -> game s (xs ++ [x, y], ys)
                    ([], _) -> game s (xs, ys ++ [y, x])


main = do
    is <- readFile "day22_input" <&> parse
    print (task1 is)
    print (task2 is)
Enter fullscreen mode Exit fullscreen mode