advent-2021/3/solution.hs

56 lines
1.4 KiB
Haskell

import Data.Bits ( complement, Bits (shift, shiftR, rotate, complementBit), shiftL, (.|.) )
import Data.List (transpose, isPrefixOf, inits, find, tails, sort)
import Debug.Trace
import Data.Maybe
main :: IO ()
main = readFile "3/input.txt" >>= print . solve . parse . lines
parse :: [String] -> [String]
parse = id
solve :: [String] -> (Int,Int)
solve input = (f input, g input)
where f = powerUse . transpose
g = lifeSupport
powerUse :: [String] -> Int
powerUse i = gamma i * epsilon i
where
gamma = pack . rate (>=)
epsilon = pack . rate (<)
rate :: (Int -> Int -> Bool) -> [String] -> [Int]
rate op = foldr (\c -> (:) (
let ones = count '1' c;
zeroes = count '0' c;
in if ones `op` zeroes
then 1
else 0
)) []
where
count x = length . filter (== x)
lifeSupport :: [String] -> Int
lifeSupport i = oxygen x * scrubber x
where
x = reverse i
oxygen = rating 0 (>=)
scrubber = rating 0 (<)
rating :: Int -> (Int -> Int -> Bool) -> [String] -> Int
rating _ _ [result] = convert result
rating n op list = rating (n + 1) op (filter (\a -> (a !! n) == (f (transpose list) !! n)) list)
where
f = map (head . show) . rate op
pack :: [Int] -> Int
pack = foldl f 0
where
f acc i = acc `shiftL` 1 .|. i
unpack :: String -> [Int]
unpack = map (\x -> if x == '0' then 0 else 1)
convert = pack . unpack