48 lines
1.6 KiB
Haskell
48 lines
1.6 KiB
Haskell
import Data.List.Split
|
|
import Data.List
|
|
import qualified Data.Map.Strict as M
|
|
|
|
main :: IO ()
|
|
main = do
|
|
input <- map (map (map sort . words) . splitOn "|") <$> lines <$> readFile "day08/input"
|
|
let output = map (!!1) input
|
|
print $ length $ filter (`elem` [2,3,4,7]) $ map length (concat output)
|
|
print $ day08 input
|
|
|
|
findDict :: [String] -> M.Map Char Char
|
|
findDict wire = M.fromList $ zip (a++b++c++d++e++f++g) "abcdefg"
|
|
where a = intersect (getX 3) (without [2,4])
|
|
b = intersect (charsWithLength 3 6) (charsWithLength 1 5)
|
|
c = intersect (charsWithLength 2 6) (getX 2)
|
|
d = intersect (charsWithLength 2 6) (charsWithLength 3 5)
|
|
e = intersect (charsWithLength 1 5) $ intersect (getX 7) $ without [2..4]
|
|
f = getX 2 \\ c
|
|
g = without [2..4] \\ e
|
|
without x = "abcdefg" \\ (concat $ filter (flip elem x . length) wire)
|
|
getXs x = filter (\y->length y == x) wire
|
|
getX = head . getXs
|
|
charsWithLength x c = nub $ concat $ filter (\y->length y == x) $ group $ sort $ concat $ getXs c
|
|
|
|
decode :: M.Map Char Char -> String -> String
|
|
decode _ [] = []
|
|
decode dict (x:xs) = dict M.! x : decode dict xs
|
|
|
|
findNum :: String -> Int
|
|
findNum x
|
|
| x=="abcefg" = 0
|
|
| x=="cf" = 1
|
|
| x=="acdeg" = 2
|
|
| x=="acdfg" = 3
|
|
| x=="bcdf" = 4
|
|
| x=="abdfg" = 5
|
|
| x=="abdefg" = 6
|
|
| x=="acf" = 7
|
|
| x=="abcdefg" = 8
|
|
| x=="abcdfg" = 9
|
|
|
|
day08 :: [[[String]]] -> Int
|
|
day08 [] = 0
|
|
day08 ((wire:output):xs) = day08 xs + (sum $ zipWith (*) decoded [10^x|x<-[0..]])
|
|
where dict = findDict wire
|
|
decoded = reverse $ map (findNum . sort . decode dict) (head output)
|