2021-12-18 20:27:37 +01:00
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 "
2021-12-18 20:29:51 +01:00
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
2021-12-18 20:27:37 +01:00
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 )