diff options
author | Aria <me@aria.rip> | 2023-01-02 21:58:56 +0000 |
---|---|---|
committer | Aria <me@aria.rip> | 2023-01-02 21:58:56 +0000 |
commit | 5eb58ad076f2cd435b11b140820da224b60b73d5 (patch) | |
tree | 2a67939595fbf993ff04f69b9cd3f0aa20827d96 /2020/15b.hs |
initial commit
Diffstat (limited to '2020/15b.hs')
-rw-r--r-- | 2020/15b.hs | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/2020/15b.hs b/2020/15b.hs new file mode 100644 index 0000000..1efe53e --- /dev/null +++ b/2020/15b.hs @@ -0,0 +1,44 @@ +module Main where + +import System.Environment (getArgs) +import Text.Printf +import qualified Data.IntMap.Strict as Map + +-- This does the same thing as 15a, it's just done in a more memory-optimised way. + +-- Parse a string, with one number per line +parseInput :: String -> [Int] +parseInput = map read . lines + +-- Parse a file given the path +-- Returns list of instructions +parseFromFile :: String -> IO [Int] +parseFromFile s = do + contents <- readFile s; + return $ parseInput contents; + +-- Generate a map from the list of initial numbers +mapFromInitial :: [Int] -> Map.IntMap Int +mapFromInitial xs = foldr (\(i,x) m -> Map.insert x i m) Map.empty (zip [0..] xs) + +-- Run till the given turn, this time using a map to store last occurences. +-- This means we don't get the full 'log', just the final turn. +-- map, prev, current index, stopping len +runTillTurn :: Map.IntMap Int -> Int -> Int -> Int -> Int +runTillTurn occ prev i n | i >= n = prev + | otherwise = runTillTurn occ' curr (i + 1) n + where curr = case Map.lookup prev occ of + Nothing -> 0 + Just x -> (i - 1) - x + occ' = Map.insert prev (i - 1) occ + +-- runghc 15b.hs inputs/day15 +main :: IO () +main = do + args <- getArgs; + ns <- parseFromFile (head args); + let x = runTillTurn (mapFromInitial ns) (last ns) (length ns) 30000000; + + printf "Answer = %d\n" x :: IO (); + + return (); |