AdventOfCode/2020/16_haskell.ipynb

142 lines
4 KiB
Text

{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"puzzle <- readFile \"16.txt\"\n",
"plines = lines puzzle"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Day 16"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Puzzle 1"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"25788"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"import Data.List.Split\n",
"\n",
"type Rule = (String, [(Int, Int)])\n",
"type Ticket = [Int]\n",
"\n",
"parseRule :: String -> Rule\n",
"parseRule line = (name, map ((\\[a, b] -> (a, b)) . map read . splitOn \"-\") $ splitOn \" or \" ranges)\n",
" where [name, ranges] = splitOn \": \" line\n",
"\n",
"rules = map parseRule . lines . head . splitOn \"\\n\\n\" $ puzzle :: [Rule]\n",
"\n",
"nearbyTickets = map (map read . splitOn \",\") . tail . lines . last . splitOn \"\\n\\n\" $ puzzle :: [Ticket]\n",
"\n",
"checkRule :: Int -> Rule -> Bool\n",
"checkRule num = any (\\(a, b) -> a <= num && num <= b) . snd\n",
"\n",
"fieldValid :: Int -> Bool\n",
"fieldValid field = any (checkRule field) rules\n",
"\n",
"sum [field | ticket <- nearbyTickets, field <- ticket, not $ fieldValid field]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Puzzle 2"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3902565915559"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"import qualified Data.Set as Set\n",
"import qualified Data.Map as Map\n",
"import Data.List (isPrefixOf)\n",
"import Data.Maybe\n",
"\n",
"n = length rules :: Int\n",
"\n",
"myTicket = map read . splitOn \",\" . last . lines . (!!1) . splitOn \"\\n\\n\" $ puzzle :: Ticket\n",
"\n",
"validTickets = filter (all fieldValid) nearbyTickets :: [Ticket]\n",
"\n",
"possibleAllocations = [Set.fromList $ filter (possible rule) [0..n-1] | rule <- [0..n-1]] :: [Set.Set Int]\n",
" where possible rule field = all (\\ticket -> checkRule (ticket !! field) (rules !! rule)) validTickets\n",
"\n",
"clearPossibility :: [Set.Set Int] -> Int -> [Set.Set Int]\n",
"clearPossibility possible num = map (Set.delete num) possible\n",
"\n",
"reduce :: [Maybe Int] -> [Set.Set Int] -> [Int]\n",
"reduce allocations possible = solve newAllocations newPossibleAllocations\n",
" where newAllocations = [case Set.toList $ possible !! i of \n",
" [x] -> Just x \n",
" _ -> y | (i, y) <- zip [0..n-1] allocations]\n",
" newPossibleAllocations = foldl clearPossibility possible $ catMaybes newAllocations\n",
"\n",
"solve :: [Maybe Int] -> [Set.Set Int] -> [Int]\n",
"solve allocations possible\n",
" | not $ any isNothing allocations = catMaybes allocations\n",
" | otherwise = reduce allocations possible\n",
"\n",
"departureValues :: [Int] -> Int\n",
"departureValues allocation = product $ map ((myTicket!!) . (allocation!!)) departureRules\n",
" where departureRules = [i | (i, (name, _)) <- zip [0..n-1] rules, \"departure\" `isPrefixOf` name]\n",
"\n",
"departureValues $ solve (replicate n Nothing) possibleAllocations"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Haskell",
"language": "haskell",
"name": "haskell"
},
"language_info": {
"codemirror_mode": "Haskell",
"file_extension": ".hs",
"mimetype": "text/x-haskell",
"name": "haskell",
"pygments_lexer": "Haskell",
"version": "8.8.4"
}
},
"nbformat": 4,
"nbformat_minor": 4
}