import Control.Exception (assert) import Data.Bits (bit) import Data.Char (digitToInt) import Data.List (group, intersect, maximumBy, minimumBy, sort, transpose) import Data.Ord (comparing) main :: IO () main = do diagnostics <- getContents putStrLn (solution1 diagnostics) putStrLn (solution2 diagnostics) solution1 :: String -> String solution1 diagnostics = show (calcGamma * calcEpsilon) where calcGamma = listToBit (map most (transpose (parseDiagnostics diagnostics))) calcEpsilon = listToBit (map least (transpose (parseDiagnostics diagnostics))) solution2 :: String -> String solution2 diagnostics = show (calcOxygen * calcCO2) where calcOxygen = listToBit (head (filterForLife most (parseDiagnostics diagnostics))) calcCO2 = listToBit (head (filterForLife least (parseDiagnostics diagnostics))) parseDiagnostics :: String -> [[Int]] parseDiagnostics diagnostics = map (map digitToInt) (lines diagnostics) enumerate :: [a] -> [(Int, a)] enumerate = zip [0..] most :: [Int] -> Int most = head . (maximumBy (comparing length)) . group . sort least :: [Int] -> Int least = head . (minimumBy (comparing length)) . group . sort listToBit :: [Int] -> Int listToBit list = foldr (\b acc -> (acc + toBit b)) 0 (enumerate (reverse list)) where -- Takes a location and value to converts it to the appropriate -- integer. toBit :: (Int, Int) -> Int toBit (i, b) = if b == 1 then bit i else 0 filterForLife :: ([Int] -> Int) -> [[Int]] -> [[Int]] filterForLife targetFilter list = foldl (filterIndex targetFilter) list [0..length(head list)-1] filterIndex :: ([Int] -> Int) -> [[Int]] -> Int -> [[Int]] filterIndex targetFilter list index = filter ((==filterTarget) . (!! index)) list where filterTarget :: Int filterTarget = targetFilter ((transpose list) !! index) -- Tests testInput1 :: String testInput1 = unlines [ "00100", "11110", "10110", "10111", "10101", "01111", "00111", "11100", "10000", "11001", "00010", "01010" ] test1 :: String test1 = assert ((solution1 testInput1) == "198") "success" test2 :: String test2 = assert ((solution2 testInput1) == "230") "success"