, ViewPatterns
common build-directives
- build-depends: base ^>=4.14
+ build-depends: base >=4.15
default-language: Haskell2010
ghc-options: -O2
-Wall
main-is: Main.hs
-- other-modules:
-- other-extensions:
- build-depends: base >=4.13 && < 4.15
+ build-depends: base >=4.15
-- hs-source-dirs:
default-language: Haskell2010
import: common-extensions, build-directives
main-is: advent02/Main.hs
build-depends: text, attoparsec
+
+executable advent03
+ import: common-extensions, build-directives
+ main-is: advent03/Main.hs
--- /dev/null
+import Data.List
+import Data.Char
+
+main :: IO ()
+main =
+ do numStrs <- readFile "data/advent03.txt"
+ let bits = map (map digitToInt) $ lines numStrs
+ print $ part1 bits
+ print $ part2 bits
+
+part1 :: [[Int]] -> Int
+part1 allBits = gamma * epsilon
+ where majorities = findMajorities allBits
+ gamma = bitsToNum majorities
+ epsilon = bitsToNum $ map not majorities
+
+part2 :: [[Int]] -> Int
+part2 allBits = oxygenRating * coFilterRating
+ where oxygenRating = bitsToNum $ oxygenFilter allBits 0
+ coFilterRating = bitsToNum $ coFilter allBits 0
+
+findMajorities :: [[Int]] -> [Bool]
+findMajorities allBits = map (>= threshold) columnSums
+ where addBits = zipWith (+)
+ columnSums = foldr1 addBits allBits
+ (t, m) = (length allBits) `divMod` 2
+ threshold = if m == 1 then t + 1 else t
+
+bitsToNum :: [Bool] -> Int
+bitsToNum bits = foldl' includeBit 0 bits
+ where includeBit n True = n * 2 + 1
+ includeBit n False = n * 2
+
+oxygenFilter :: [[Int]] -> Int -> [Bool]
+oxygenFilter = partFilter id
+
+coFilter :: [[Int]] -> Int -> [Bool]
+coFilter = partFilter not
+
+partFilter :: (Bool -> Bool) -> [[Int]] -> Int -> [Bool]
+partFilter filterFunc allBits n
+ | length allBits == 1 = majorities
+ | otherwise = partFilter filterFunc filteredBits (n + 1)
+ where majorities = findMajorities allBits
+ filterValue = if (filterFunc $ majorities !! n) then 1 else 0
+ filteredBits = filter (\bs -> bs !! n == filterValue) allBits