[hs] Clean up 2020_16
This commit is contained in:
parent
874c7f1e84
commit
155118b5f2
1 changed files with 17 additions and 33 deletions
|
|
@ -8,22 +8,16 @@ import Control.Monad
|
||||||
import Data.Bifunctor
|
import Data.Bifunctor
|
||||||
import Data.List
|
import Data.List
|
||||||
|
|
||||||
import qualified Data.Map as Map
|
|
||||||
import qualified Data.Set as Set
|
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
|
|
||||||
import Aoc.Day
|
import Aoc.Day
|
||||||
import Aoc.Parse
|
import Aoc.Parse
|
||||||
|
|
||||||
data Input = Input
|
data Input = Input [(T.Text, Int -> Bool)] [Int] [[Int]]
|
||||||
{ iFields :: Map.Map T.Text [(Int, Int)]
|
|
||||||
, iMyTicket :: [Int]
|
|
||||||
, iNearbyTickets :: [[Int]]
|
|
||||||
} deriving (Show)
|
|
||||||
|
|
||||||
parser :: Parser Input
|
parser :: Parser Input
|
||||||
parser = do
|
parser = do
|
||||||
fields <- Map.fromList <$> many (fieldLine <* newline)
|
fields <- many (fieldLine <* newline)
|
||||||
void $ string "\nyour ticket:\n"
|
void $ string "\nyour ticket:\n"
|
||||||
myTicket <- ticket <* newline
|
myTicket <- ticket <* newline
|
||||||
void $ string "\nnearby tickets:\n"
|
void $ string "\nnearby tickets:\n"
|
||||||
|
|
@ -33,48 +27,38 @@ parser = do
|
||||||
fieldLine = do
|
fieldLine = do
|
||||||
name <- takeWhileP Nothing $ \c -> (c /= ':') && (c /= '\n')
|
name <- takeWhileP Nothing $ \c -> (c /= ':') && (c /= '\n')
|
||||||
void $ string ": "
|
void $ string ": "
|
||||||
ranges <- sepBy ((,) <$> (decimal <* string "-") <*> decimal) (string " or ")
|
(a, b) <- (,) <$> (decimal <* string "-") <*> decimal
|
||||||
pure (name, ranges)
|
void $ string " or "
|
||||||
|
(c, d) <- (,) <$> (decimal <* string "-") <*> decimal
|
||||||
|
pure (name, \n -> (a <= n && n <= b) || (c <= n && n <= d))
|
||||||
ticket = decimal `sepBy` string ","
|
ticket = decimal `sepBy` string ","
|
||||||
|
|
||||||
valid :: Int -> [(Int, Int)] -> Bool
|
anyValid :: [(T.Text, Int -> Bool)] -> Int -> Bool
|
||||||
valid n = any (\(a, b) -> a <= n && n <= b)
|
anyValid fields n = any (($ n) . snd) fields
|
||||||
|
|
||||||
findValid :: Map.Map T.Text [(Int, Int)] -> Int -> Set.Set T.Text
|
|
||||||
findValid fields n = Set.fromList $ map fst $ filter (valid n . snd) $ Map.toList fields
|
|
||||||
|
|
||||||
anyValid :: Map.Map T.Text [(Int, Int)] -> Int -> Bool
|
|
||||||
anyValid fields = not . Set.null . findValid fields
|
|
||||||
|
|
||||||
anyOf :: [a] -> [(a, [a])]
|
anyOf :: [a] -> [(a, [a])]
|
||||||
anyOf [] = []
|
anyOf [] = []
|
||||||
anyOf (a:as) = (a, as) : map (second (a:)) (anyOf as)
|
anyOf (a:as) = (a, as) : map (second (a:)) (anyOf as)
|
||||||
|
|
||||||
findFields :: [(a, Set.Set T.Text)] -> [[(a, T.Text)]]
|
findFields :: [(a, [T.Text])] -> [[(a, T.Text)]]
|
||||||
findFields [] = pure []
|
findFields [] = pure []
|
||||||
findFields variants = do
|
findFields variants = do
|
||||||
((index, names), rest) <- anyOf variants
|
((i, [name]), rest) <- anyOf variants
|
||||||
case Set.toList names of
|
rest2 <- findFields $ map (second $ delete name) rest
|
||||||
[name] -> do
|
pure $ (i, name) : rest2
|
||||||
let rest' = map (second $ Set.delete name) rest
|
|
||||||
((index, name) :) <$> findFields rest'
|
|
||||||
_ -> []
|
|
||||||
|
|
||||||
solver :: Input -> IO ()
|
solver :: Input -> IO ()
|
||||||
solver input = do
|
solver (Input fields ownTicket nearbyTickets) = do
|
||||||
let Input fields ownTicket nearbyTickets = input
|
|
||||||
|
|
||||||
putStrLn ">> Part 1"
|
putStrLn ">> Part 1"
|
||||||
print $ sum $ filter (not . anyValid fields) $ concat nearbyTickets
|
print $ sum $ filter (not . anyValid fields) $ concat nearbyTickets
|
||||||
|
|
||||||
putStrLn ""
|
putStrLn ""
|
||||||
putStrLn ">> Part 2"
|
putStrLn ">> Part 2"
|
||||||
let validTickets = filter (all (anyValid fields)) nearbyTickets
|
let validTickets = filter (all (anyValid fields)) nearbyTickets
|
||||||
possibleFields = map (foldr1 Set.intersection) $ transpose $ map (map (findValid fields)) validTickets
|
possibleNames = map (\ns -> map fst $ filter (\(_, p) -> all p ns) fields) $ transpose validTickets
|
||||||
actualFields = Map.fromList $ head $ findFields $ zip [(0::Int)..] possibleFields
|
actualNames = map snd $ sortOn fst $ head $ findFields $ zip [(0::Int)..] possibleNames
|
||||||
namedOwnValues = zipWith (\i v -> (actualFields Map.! i, v)) [0..] ownTicket
|
relevantValues = map snd $ filter (T.isPrefixOf "departure" . fst) $ zip actualNames ownTicket
|
||||||
relevantOwnValues = map snd $ filter (T.isPrefixOf "departure" . fst) namedOwnValues
|
print $ product relevantValues
|
||||||
print $ product relevantOwnValues
|
|
||||||
|
|
||||||
day :: Day
|
day :: Day
|
||||||
day = dayParse parser solver
|
day = dayParse parser solver
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue