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