Done day 22
authorNeil Smith <NeilNjae@users.noreply.github.com>
Tue, 24 Dec 2024 13:36:11 +0000 (13:36 +0000)
committerNeil Smith <NeilNjae@users.noreply.github.com>
Tue, 24 Dec 2024 13:36:11 +0000 (13:36 +0000)
advent22/Main.hs [new file with mode: 0644]
advent22/MainBruteForce.hs [new file with mode: 0644]
adventofcode24.cabal

diff --git a/advent22/Main.hs b/advent22/Main.hs
new file mode 100644 (file)
index 0000000..39657a1
--- /dev/null
@@ -0,0 +1,66 @@
+-- Writeup at https://work.njae.me.uk/2024/12/24/advent-of-code-2024-day-21/
+import AoC
+
+import Data.Bits
+import Data.List
+import Data.List.Split
+import qualified Data.IntMap.Strict as M
+
+type Prices = M.IntMap Int
+
+main :: IO ()
+main = 
+  do  dataFileName <- getDataFileName
+      text <- readFile dataFileName
+      let codes = fmap read $ lines text
+      -- print codes
+      -- print $ fmap (followingSecret 2000) codes
+      print $ part1 codes
+      print $ part2 codes
+
+part1 :: [Int] -> Int
+part1 codes = sum $ fmap (followingSecret 2000) codes
+
+part2 codes = maximum $ M.elems mergedPriceValues
+  where allPrices = fmap salePrices codes
+        allPriceValues = fmap windowsAndPrices allPrices
+        mergedPriceValues = M.unionsWith (+) allPriceValues
+
+nextSecret, step1, step2, step3, prune :: Int -> Int
+nextSecret = step3 . step2 . step1 
+step1 n = prune $ (n * 64) `mix` n
+step2 n = prune $ (n `div` 32) `mix` n
+step3 n = prune $ (n * 2048) `mix` n
+prune n = n `mod` 16777216
+
+mix :: Int -> Int -> Int
+mix s n = s `xor` n
+
+followingSecret :: Int -> Int -> Int
+followingSecret n s = (!! n) $ iterate nextSecret s
+
+salePrices :: Int -> [Int]
+salePrices s = take 2001 $ fmap (`mod` 10) $ iterate nextSecret s
+
+priceChanges :: [Int] -> [Int]
+priceChanges ps = zipWith (-) (tail ps) ps
+
+windows :: [Int] -> [Int]
+windows = fmap encode . divvy 4 1
+
+encode :: [Int] -> Int
+encode xs = foldl' (\a n -> a * 20 + n) 0 xs
+
+windowsAndPrices :: [Int] -> Prices
+windowsAndPrices ps = foldl' (\m (w, p) -> M.insertWith (flip const) w p m) M.empty wPs
+  where cs = priceChanges ps
+        wPs = zip (windows cs) (drop 4 ps)
+
+
+possibleWindows :: [[Int]]
+possibleWindows = [ [a, b, c, d]
+                  | a <- [-9..9]
+                  , b <- [-9..9]
+                  , c <- [-9..9]
+                  , d <- [-9..9]
+                  ]
diff --git a/advent22/MainBruteForce.hs b/advent22/MainBruteForce.hs
new file mode 100644 (file)
index 0000000..53156da
--- /dev/null
@@ -0,0 +1,64 @@
+-- Writeup at https://work.njae.me.uk/2024/12/24/advent-of-code-2024-day-21/
+import AoC
+
+import Data.Bits
+import Data.List.Split
+
+main :: IO ()
+main = 
+  do  dataFileName <- getDataFileName
+      text <- readFile dataFileName
+      let codes = fmap read $ lines text
+      -- print codes
+      -- print $ fmap (followingSecret 2000) codes
+      print $ part1 codes
+      print $ part2 codes
+
+part1 :: [Int] -> Int
+part1 codes = sum $ fmap (followingSecret 2000) codes
+
+part2 codes = maximum $ fmap valueOfWindow allWindows
+  where allPrices = fmap salePrices codes
+        allWindows = possibleWindows
+        valueOfWindow w = sum $ fmap (valueGivenWindow w) allPrices
+
+nextSecret, step1, step2, step3, prune :: Int -> Int
+nextSecret = step3 . step2 . step1 
+step1 n = prune $ (n * 64) `mix` n
+step2 n = prune $ (n `div` 32) `mix` n
+step3 n = prune $ (n * 2048) `mix` n
+prune n = n `mod` 16777216
+
+mix :: Int -> Int -> Int
+mix s n = s `xor` n
+
+followingSecret :: Int -> Int -> Int
+followingSecret n s = (!! n) $ iterate nextSecret s
+
+salePrices :: Int -> [Int]
+salePrices s = take 2001 $ fmap (`mod` 10) $ iterate nextSecret s
+
+priceChanges :: [Int] -> [Int]
+priceChanges ps = zipWith (-) (tail ps) ps
+
+windows :: [Int] -> [[Int]]
+windows = divvy 4 1
+
+pricesAndWindows :: [Int] -> [(Int, [Int])]
+pricesAndWindows ps = zip (drop 4 ps) $ windows cs
+  where cs = priceChanges ps
+
+valueGivenWindow :: [Int] -> [Int] -> Int
+valueGivenWindow window ps 
+  | null foundPrices = 0
+  | otherwise = fst $ head foundPrices
+  where vCs = pricesAndWindows ps
+        foundPrices = dropWhile (\(p, w) -> w /= window) vCs
+
+possibleWindows :: [[Int]]
+possibleWindows = [ [a, b, c, d]
+                  | a <- [-9..9]
+                  , b <- [-9..9]
+                  , c <- [-9..9]
+                  , d <- [-9..9]
+                  ]
index 57ca291fb7ac04fe3488aa050a3fe060c43b8297..35c9ac6ce790502d7b40ac4d0177d9d15f5605c9 100644 (file)
@@ -204,3 +204,12 @@ executable advent21
   import: warnings, common-extensions, build-directives, common-modules
   main-is: advent21/Main.hs
   build-depends: linear, containers
+
+executable advent22
+  import: warnings, common-extensions, build-directives, common-modules
+  main-is: advent22/Main.hs
+  build-depends: split, containers
+executable advent22bf
+  import: warnings, common-extensions, build-directives, common-modules
+  main-is: advent22/MainBruteForce.hs
+  build-depends: split  
\ No newline at end of file