Done day 20
[advent-of-code-22.git] / advent20 / Main.hs
diff --git a/advent20/Main.hs b/advent20/Main.hs
new file mode 100644 (file)
index 0000000..2b6b507
--- /dev/null
@@ -0,0 +1,58 @@
+-- Writeup at https://work.njae.me.uk/2022/12/21/advent-of-code-2022-day-20/
+
+import Debug.Trace
+
+import AoC
+import Data.List
+import Data.Maybe
+import Data.CircularList
+import Control.Lens
+
+data IndexedElem = IndexedElem { _idx :: Int, _shift :: Int, _value :: Int}
+    deriving (Show, Eq, Ord)
+makeLenses ''IndexedElem
+
+type MixList = CList IndexedElem
+
+key :: Int
+key = 811589153
+
+main :: IO ()
+main = 
+  do  dataFileName <- getDataFileName
+      text <- readFile dataFileName
+      let mixlist = successfulParse text
+      -- print mixlist
+      print $ part1 mixlist
+      print $ part2 mixlist
+
+part1, part2 :: [IndexedElem] -> Int
+part1 mixlist = findGrove $ mixRound $ fromList mixlist
+
+part2 mixlist = findGrove $ (!!10) $ iterate mixRound cMixlist
+    where cMixlist = fromList $ fmap scaleElem mixlist
+          scaleElem e = e & value %~ (* key) & shift .~ (((e ^. value) * key) `mod` (scale - 1))
+          scale = length mixlist
+
+mixRound :: MixList -> MixList
+mixRound mixlist = foldl' mixOne mixlist [1..(size mixlist)]
+
+mixOne :: MixList -> Int -> MixList
+mixOne mixlist elemIndex = insertL element $ rotN (element ^. shift) $ removeL elementFocused
+    where elementFocused = fromJust $ findRotateTo (\e -> e ^. idx == elemIndex) mixlist
+          element = fromJust $ focus elementFocused
+
+findGrove :: MixList -> Int
+findGrove mixlist = focus1 + focus2 + focus3
+    where mixlist0 = fromJust $ findRotateTo (\ep -> ep ^. value == 0) mixlist
+          focus1 = (fromJust $ focus $ rotN 1000 mixlist0) ^. value
+          focus2 = (fromJust $ focus $ rotN 2000 mixlist0) ^. value
+          focus3 = (fromJust $ focus $ rotN 3000 mixlist0) ^. value
+
+successfulParse :: String -> [IndexedElem]
+successfulParse text = fmap mkElem $ zip [1..] tns
+    where tns =  fmap read $ lines text
+          mkElem (i, n) = 
+                IndexedElem {_idx = i, _value = n, 
+                    _shift = n `mod` (l - 1) }
+          l = length tns