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