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