Commit 75e48d45 authored by Nicolas Lenz's avatar Nicolas Lenz

Refactored Day 01

With Data.IntSet from containers (sorted) part 2 now takes 1 second instead of 2 Minutes *yay*
parent de17393e
......@@ -4,7 +4,7 @@ cabal-version: 1.12
--
-- see: https://github.com/sol/hpack
--
-- hash: 59b58714fd0ab373f1ebc055b9329a7968e4a1f9085f331dfd682c2e853ca733
-- hash: a31d69558fb7c391bf70ef12c046d4b4a10a2fd42e24f572cc4592799a825b1b
name: advent-of-code
version: 0.0.0
......@@ -37,5 +37,7 @@ executable advent-of-code
ghc-options: -O2 -threaded -rtsopts -with-rtsopts=-N
build-depends:
base >=4.7 && <5
, containers
, parsec
, text
default-language: Haskell2010
......@@ -16,6 +16,8 @@ description: Please see the README at <https://git.eisfunke.com/research
dependencies:
- base >= 4.7 && < 5
- text
- containers
- parsec
executables:
advent-of-code:
......
module Day01 (part1, part2) where
import Data.IntSet (IntSet)
import qualified Data.IntSet as IntSet
part1 :: [String] -> String
part1 input = show $ last $ applySeq (toFunction <$> input) 0
part1 input = show $ last $ scanl (flip ($)) 0 (toFunction <$> input)
part2 :: [String] -> String
part2 input = show $ firstTwice $ applySeq (cycle (toFunction <$> input)) 0
part2 input = show $ firstTwice $ scanl (flip ($)) 0 (toFunction <$> cycle input)
example :: [String]
example = ["+1", "-2", "+3", "+1"]
-- |Parses a String like "+32" or "-23" to the corresponding function.
......@@ -13,15 +19,11 @@ toFunction :: String -> (Int -> Int)
toFunction ('+':as) = (+(read as))
toFunction ('-':as) = (\x -> x - read as)
-- |Sequentially applies a list of functions to a start value, returning a list of all intermediate results. Can be used on infinite lists.
applySeq :: [a -> a] -> a -> [a]
applySeq [] start = [start]
applySeq (f:fs) start = start : applySeq fs (f start)
-- |Finds the first element that occurs twice in a list. Works on infinite list (but in that case doesn't terminate if there's no element occuring twice).
firstTwice :: Eq a => [a] -> Maybe a
firstTwice as = loop as [] where
-- |Finds the first element that occurs twice in a list. Works on infinite lists (but in that case doesn't terminate if there's no element occuring twice).
firstTwice :: [Int] -> Maybe Int
firstTwice as = loop as IntSet.empty where
loop :: [Int] -> IntSet -> Maybe Int
loop [] found = Nothing
loop todo@(x:xs) found
| x `elem` found = Just x
| otherwise = loop xs (x:found)
loop (x:xs) found
| x `IntSet.member` found = Just x
| otherwise = loop xs (x `IntSet.insert` found)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment