aboutsummaryrefslogtreecommitdiffstats
path: root/day03/main.hs
diff options
context:
space:
mode:
Diffstat (limited to 'day03/main.hs')
-rw-r--r--day03/main.hs62
1 files changed, 62 insertions, 0 deletions
diff --git a/day03/main.hs b/day03/main.hs
new file mode 100644
index 0000000..3488d69
--- /dev/null
+++ b/day03/main.hs
@@ -0,0 +1,62 @@
+module Main where
+
+import Control.Applicative (ZipList (ZipList, getZipList))
+import Data.Char (digitToInt)
+import Data.List (maximumBy, minimumBy)
+import Data.Ord (comparing)
+import Utils
+
+convert :: [Int] -> Int
+-- Convert binary (list of zeros and ones) to decimal
+convert [] = 0
+convert (x : xs) = x + 2 * convert xs
+
+toIntMatrix :: [[Char]] -> [[Int]]
+toIntMatrix = map (map digitToInt)
+
+transpose :: [[a]] -> [[a]]
+transpose = getZipList . traverse ZipList
+
+mostCommon :: [Int] -> Int
+-- Appending [0, 1] is a hack to make maximumBy choose 1 in a tie due to semantics
+mostCommon lst = maximumBy (comparing (\x -> length $ filter (x ==) lst)) (lst ++ [0, 1])
+
+leastCommon :: [Int] -> Int
+-- Prepending [0, 1] is a hack to make minimumBy choose 0 in a tie due to semantics
+leastCommon lst = minimumBy (comparing (\x -> length $ filter (x ==) lst)) ([0, 1] ++ lst)
+
+e1 :: [String] -> Int
+e1 input =
+ let mtx = toIntMatrix input $> transpose
+ gamma = mtx $> map mostCommon .> reverse .> convert
+ epsilon = mtx $> map leastCommon .> reverse .> convert
+ in gamma * epsilon
+
+recur :: ([Int] -> Int) -> [[Int]] -> Int -> Int
+-- Recurse through the matrix from left to right (i = [0..columnN - 1]) and filter out
+-- rows not matching the criteria. If filter results in only one resulting value, stop recursion.
+recur criteriaFn mtx i =
+ let column = map (!! i) mtx
+ crit = criteriaFn column
+ filtered = filter (\row -> row !! i == crit) mtx
+ in if length filtered == 1
+ then convert $ reverse $ head filtered
+ else recur criteriaFn filtered (i + 1)
+
+e2 :: [String] -> Int
+e2 input =
+ let mtx = input $> toIntMatrix
+ oxyr = recur mostCommon mtx 0
+ co2r = recur leastCommon mtx 0
+ in oxyr * co2r
+
+main :: IO ()
+main =
+ do
+ contents <- getContents
+ let input =
+ contents
+ $> lines
+
+ e1 input $> print
+ e2 input $> print