56 lines
1.4 KiB
Haskell
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
|