git.haldean.org aoc-2018 / cf34f03
clean up day 1, v1 is too embarassing Haldean Brown 4 years ago
1 changed file(s) with 17 addition(s) and 7 deletion(s). Raw diff Collapse all Expand all
00 import qualified Data.Set as S
11 import System.Environment
22
3 -- simple loading and parsing functions
34 toint :: String -> Integer
45 toint ('+':val) = read val
56 toint ('-':val) = - (read val)
67 toint val = read val :: Integer
7
88 loadlist :: String -> [Integer]
99 loadlist = map toint . filter (not . null) . lines
1010
11 -- challenge 1: just sum the list
12 main1 :: IO ()
13 main1 = fmap (sum . loadlist) (readFile "input.txt") >>= print
14
15 -- this turns a list of integers into an infinite list of pairs of (set of sums
16 -- seen so far, current running sum). the list is made infinite by cycling the
17 -- input list
1118 dofold :: [Integer] -> [(S.Set Integer, Integer)]
12 dofold lst1 =
13 let lst = cycle lst1 in
14 scanl (\(seenfreqs, lastfreq) offset -> let newfreq = lastfreq + offset in (S.insert newfreq seenfreqs, newfreq)) (S.empty, 0) lst
19 dofold lst =
20 let scanfunc = \(seenfreqs, lastfreq) offset -> let newfreq = lastfreq + offset in (S.insert newfreq seenfreqs, newfreq)
21 in scanl scanfunc (S.empty, 0) (cycle lst)
1522
23 -- this finds the first frequency to appear twice by pairing up the frequencies
24 -- seen after frame i with the frequency at frame i + 1. If the frequency in a
25 -- pair also exists in the set of the pair, it means that it had been seen in
26 -- frame i, so it's a duplicate. The first element in our infinite list that
27 -- satisfies that is our answer.
1628 finddup :: [Integer] -> Integer
1729 finddup lst1 = let folded = dofold lst1 in
1830 snd $ head $ dropWhile (\(seenfreq, newfreq) -> not $ S.member newfreq seenfreq) $ zip (map fst folded) (drop 1 $ map snd folded)
1931
20 main1 :: IO ()
21 main1 = fmap (sum . loadlist) (readFile "input.txt") >>= print
22
2332 main2 :: IO ()
2433 main2 = fmap (finddup . loadlist) (readFile "input.txt") >>= print
2534
35 -- runs the first or second challenge depending on the command line argument
2636 main :: IO ()
2737 main = fmap head getArgs >>= \a -> if a == "1" then main1 else main2