1 -- Writeup at https://work.njae.me.uk/2022/12/21/advent-of-code-2022-day-20/
4 import Data.List hiding (elemIndex)
6 import Data.CircularList
7 import Control.Lens hiding (element)
9 data IndexedElem = IndexedElem { _idx :: Int, _shift :: Int, _value :: Int}
10 deriving (Show, Eq, Ord)
11 makeLenses ''IndexedElem
13 type MixList = CList IndexedElem
20 do dataFileName <- getDataFileName
21 text <- readFile dataFileName
22 let mixlist = successfulParse text
27 part1, part2 :: [IndexedElem] -> Int
28 part1 mixlist = findGrove $ mixRound $ fromList mixlist
30 part2 mixlist = findGrove $ (!!10) $ iterate mixRound cMixlist
31 where cMixlist = fromList $ fmap scaleElem mixlist
32 scaleElem e = e & value %~ (* key) & shift .~ (((e ^. value) * key) `mod` (scale - 1))
33 scale = length mixlist
35 mixRound :: MixList -> MixList
36 mixRound mixlist = foldl' mixOne mixlist [1..(size mixlist)]
38 mixOne :: MixList -> Int -> MixList
39 mixOne mixlist elemIndex = insertL element $ rotN (element ^. shift) $ removeL elementFocused
40 where elementFocused = fromJust $ findRotateTo (\e -> e ^. idx == elemIndex) mixlist
41 element = fromJust $ focus elementFocused
43 findGrove :: MixList -> Int
44 findGrove mixlist = focus1 + focus2 + focus3
45 where mixlist0 = fromJust $ findRotateTo (\ep -> ep ^. value == 0) mixlist
46 focus1 = (fromJust $ focus $ rotN 1000 mixlist0) ^. value
47 focus2 = (fromJust $ focus $ rotN 2000 mixlist0) ^. value
48 focus3 = (fromJust $ focus $ rotN 3000 mixlist0) ^. value
50 successfulParse :: String -> [IndexedElem]
51 successfulParse text = fmap mkElem $ zip [1..] tns
52 where tns = fmap read $ lines text
54 IndexedElem {_idx = i, _value = n,
55 _shift = n `mod` (l - 1) }