Advent of Code solutions
1import Control.Arrow
2import Data.Either
3import Data.List
4import Data.Set qualified as Set
5
6score = sum . zipWith (*) [1..] . reverse
7
8play a b = play_ Set.empty a b
9 where
10 play_ _ a [] = Left $ score a
11 play_ _ [] b = Right $ score b
12 play_ cache a b | Set.member (a, b) cache = Left $ score a
13 play_ cache aa@(a:as) bb@(b:bs)
14 | a <= length as && b <= length bs = either (const awins) (const bwins) $ play (take a as) (take b bs)
15 | a > b = awins
16 | b > a = bwins
17 where
18 cache' = Set.insert (aa, bb) cache
19 awins = play_ cache' (as ++ [a, b]) bs
20 bwins = play_ cache' as (bs ++ [b, a])
21
22answer contents = either id id $ play p1 p2
23 where
24 (p1, p2) :: ([Int], [Int]) = (fmap read . tail *** fmap read . drop 2) $ break null $ lines contents
25
26main = getContents >>= print . answer