From 14719080465b4b525aeb9cfddcb6e5ec1c0ff544 Mon Sep 17 00:00:00 2001 From: Neil Smith <neil.git@njae.me.uk> Date: Sun, 25 Dec 2016 16:01:27 +0000 Subject: [PATCH] Day 24 at last --- adventofcode1624/adventofcode1624.cabal | 50 +++++++ adventofcode1624/app/advent24.hs | 175 ++++++++++++++++++++++++ data/advent24.txt | 45 ++++++ day24.html | 152 ++++++++++++++++++++ stack.yaml | 1 + 5 files changed, 423 insertions(+) create mode 100644 adventofcode1624/adventofcode1624.cabal create mode 100644 adventofcode1624/app/advent24.hs create mode 100644 data/advent24.txt create mode 100644 day24.html diff --git a/adventofcode1624/adventofcode1624.cabal b/adventofcode1624/adventofcode1624.cabal new file mode 100644 index 0000000..f016db1 --- /dev/null +++ b/adventofcode1624/adventofcode1624.cabal @@ -0,0 +1,50 @@ +name: adventofcode1624 +version: 0.1.0.0 +synopsis: Initial project template from stack +description: Please see README.md +homepage: https://github.com/neilnjae/adventofcode16#readme +license: BSD3 +license-file: LICENSE +author: Neil Smith +maintainer: noone@njae.me.uk +copyright: 2016 Neil Smith +category: None +build-type: Simple +extra-source-files: README.md +cabal-version: >=1.10 + +library + hs-source-dirs: src + build-depends: base >= 4.7 && < 5 + default-language: Haskell2010 + +executable advent24 + hs-source-dirs: app + main-is: advent24.hs + ghc-options: -O2 -threaded -rtsopts -with-rtsopts=-N + build-depends: base + , adventofcode1624 + , adventofcode16 + , containers + , astar + , hashable + , unordered-containers + default-language: Haskell2010 + +test-suite adventofcode1624-test + type: exitcode-stdio-1.0 + hs-source-dirs: test + main-is: Spec.hs + build-depends: base + , adventofcode1601 + , adventofcode16 + , containers + , astar + , hashable + , unordered-containers + ghc-options: -threaded -rtsopts -with-rtsopts=-N + default-language: Haskell2010 + +source-repository head + type: git + location: https://github.com/neilnjae/adventofcode16 diff --git a/adventofcode1624/app/advent24.hs b/adventofcode1624/app/advent24.hs new file mode 100644 index 0000000..fc97d16 --- /dev/null +++ b/adventofcode1624/app/advent24.hs @@ -0,0 +1,175 @@ +{-# LANGUAGE DeriveGeneric #-} + +module Main(main) where + +import GHC.Generics (Generic) +import Data.Maybe (catMaybes, fromJust) +import Data.List +import Data.Char (isDigit) +import qualified Data.Map.Strict as M +import Data.Map.Strict ((!)) +import qualified Data.HashSet as S +import Data.Graph.AStar +import Data.Hashable +import qualified Data.HashSet +import Debug.Trace + +type Point = (Int, Int) -- row, column, both zero based. +type Grid = M.Map Point Char + +data Path = Path { from :: Point + , to :: Point + , path :: Int + } deriving (Eq, Generic) +instance Hashable Path +-- instance Eq Path where +-- p1 == p2 = (joins p1) == (joins p2) +instance Show Path where + show p = "Path { " ++ show (from p) ++ " -> " ++ show (to p) ++ ", " ++ show (path p) ++ " }" + +type PathSet = S.HashSet Path + +-- Grid search state +data Gss = Gss { origin :: Point + , current :: Point + , goal :: Point + , gssPath :: [Point] + } deriving (Eq, Generic) +instance Hashable Gss +instance Ord Gss where + s1 `compare` s2 = ((heuristicG s1) + (length (gssPath s1))) `compare` ((heuristicG s2) + (length (gssPath s2))) +instance Show Gss where + show gss = "Gss { " ++ show (origin gss) ++ " -> " ++ show (current gss) ++ " -> " ++ show (goal gss) ++ " }" + +data Tour = Tour {at :: Point, tour :: [Path]} deriving (Show, Eq) + + +littleGrid = "\ +\###########\n\ +\#0.1.....2#\n\ +\#.#######.#\n\ +\#4.......3#\n\ +\###########" + +main :: IO () +main = do + text <- readFile "data/advent24.txt" + -- let text = littleGrid + let tl = lines text + let mp = M.fromList $ [((r, c), (tl!!r)!!c)| r <- [0..(length tl - 1)], c <- [0..(length (tl!!0) - 1)]] + let goals = M.filter (isDigit) mp + let start = head $ M.keys $ M.filter (=='0') mp + let aStarSearch s g = asG [startGss s g] mp [] + let paths = map (fromGss) $ catMaybes $ [aStarSearch st gl | st <- (M.keys goals), gl <- (M.keys goals), st /= gl] + + -- part0 mp + part1 start (M.keys goals) paths + part2 start (M.keys goals) paths + +part0 mp = print (length allPaths, allPaths) + where goals = M.filter (isDigit) mp + start = head $ M.keys $ M.filter (=='0') mp + -- goal = head $ M.keys goals + goal = head $ M.keys $ M.filter (=='2') mp + -- aStarSearch s g = aStar (successorsG mp) costG heuristicG isGoalG (startGss s g) + aStarSearch s g = asG [startGss s g] mp [] + traceSearch s g = trace ("Trace " ++ (show s) ++ " -> " ++ (show g)) (aStarSearch s g) + paths = S.fromList $ map (fromGss) $ catMaybes $ map (\gl -> aStarSearch start gl) $ M.keys goals + path = aStarSearch start goal + allPaths = map (fromGss) $ catMaybes $ [traceSearch st gl | st <- (M.keys goals), gl <- (M.keys goals), st /= gl] + +fromGss :: Gss -> Path +fromGss g = Path {from = origin g, to = goal g, path = (length (gssPath g)) - 1} + +part1 :: Point -> [Point] -> [Path] -> IO () +part1 start points paths = print $ shortestTour start points paths + + -- where goals = M.filter (isDigit) mp + -- start = head $ M.keys $ M.filter (=='0') mp + -- aStarSearch s g = asG [startGss s g] mp [] + -- paths = nub $ map (fromGss) $ catMaybes $ [aStarSearch st gl | st <- (M.keys goals), gl <- (M.keys goals), st /= gl] + +part2 :: Point -> [Point] -> [Path] -> IO () +part2 start points paths = print $ shortestReturningTour start points paths + +-- bfsG :: [Gss] -> Grid -> [Path] -> [Point] -> [Path] +-- -- bfsG ps _ paths closed | trace ((show ps) ++ " :: " ++ (show paths) ++ " X " ++ (show closed)) False = undefined +-- bfsG [] _ paths _ = paths +-- bfsG (p:ps) g paths closed = +-- if current p /= origin p && isDigit currentCell +-- then bfsG ps g (newPath:paths) ((current p):closed) +-- else bfsG (ps ++ extraAgenda) g paths ((current p):closed) +-- where currentCell = (g!(current p)) +-- newPath = Path {joins = S.fromList [current p, origin p], path = gssPath p} +-- nextPoints = filter (\np -> np `notElem` ((gssPath p) ++ closed)) $ gridNeighbours g $ current p +-- extraAgenda = map (\n -> Gss {origin = origin p, goal = goal p, current = n, gssPath = (n:(gssPath p))}) nextPoints + +asG :: [Gss] -> Grid -> [Point] -> Maybe Gss +-- asG ps _ closed | trace ((show ps) ++ " :: " ++ (show paths) ++ " X " ++ (show closed)) False = undefined +asG [] _ _ = Nothing +asG (p:ps) g closed = + if current p == goal p + then Just p + else if (head $ gssPath p) `elem` closed + then asG ps g closed + else asG newAgenda g ((current p):closed) + where -- currentCell = (g!(current p)) + -- newPath = Path {joins = S.fromList [current p, origin p], path = gssPath p} + nextPoints = filter (\np -> np `notElem` ((gssPath p) ++ closed)) $ gridNeighbours g $ current p + extraAgenda = map (\n -> Gss {origin = origin p, goal = goal p, current = n, gssPath = (n:(gssPath p))}) nextPoints + newAgenda = sort (ps ++ extraAgenda) + + +startGss :: Point -> Point -> Gss +startGss p g = Gss {origin = p, goal = g, current = p, gssPath = [p]} + + +gridNeighbours :: Grid -> Point -> [Point] +gridNeighbours g p@(r, c) = filter (\n -> (g!n) /= '#') ns + where ns = [(r-1, c), (r+1, c), (r, c-1), (r, c+1)] + +heuristicG :: Gss -> Int +heuristicG gss = abs (rg - rc) + abs (cg - cc) + where (rg, cg) = goal gss + (rc, cc) = current gss + +-- isGoalG :: Gss -> Bool +-- isGoalG st = current st == goal st + +-- successorsG :: Grid -> Gss -> Data.HashSet.HashSet Gss +-- successorsG grid st = Data.HashSet.fromList extraAgenda +-- where nextPoints = gridNeighbours grid $ current st +-- -- nextPoints = filter (\np -> np `notElem` (gssPath st)) $ gridNeighbours grid $ current st +-- extraAgenda = map (\n -> Gss {origin = origin st, goal = goal st, current = n, gssPath = (n:(gssPath st))}) nextPoints + +-- costG :: a -> b -> Int +-- costG = const $ const 1 + + + +shortestTour :: Point -> [Point] -> [Path] -> Int +shortestTour p0 points paths = minimum $ map (\p -> pathLength p paths) startRight + where pointPerms = permutations points + startRight = filter (\p -> (head p) == p0) pointPerms + +shortestReturningTour :: Point -> [Point] -> [Path] -> Int +shortestReturningTour p0 points paths = minimum $ map (\p -> pathLength p paths) startRight + where pointPerms = map (\p -> p ++ [p0]) $ permutations points + startRight = filter (\p -> (head p) == p0) pointPerms + +pathBetween :: [Path] -> Point -> Point -> Path +pathBetween paths a b = head $ filter (\p -> from p == a && to p == b) paths + +adjacents :: [a] -> [[a]] +adjacents ts = filter (\t -> (length t) == 2) $ map (\t -> take 2 t) $ tails ts + +pathLength :: [Point] -> [Path] -> Int +pathLength points paths = sum $ map (path) builtPath + where pairs = adjacents points + builtPath = foldl (addPath paths) [] pairs + +addPath :: [Path] -> [Path] -> [Point] -> [Path] +addPath paths built posPair = built ++ [toAdd] + where toAdd = pathBetween paths (posPair!!0) (posPair!!1) + + diff --git a/data/advent24.txt b/data/advent24.txt new file mode 100644 index 0000000..771b64d --- /dev/null +++ b/data/advent24.txt @@ -0,0 +1,45 @@ +####################################################################################################################################################################################### +#.......#.....#.....#.#.....#.#...#.#.......#.....#.#...#.......#...........#...#.............#.....#.......#.........#.....#.....#...........#.#...................#.....#...........# +#.#######.#.#.#.###.#.#####.#.#.#.#.#####.#.#.###.#.#######.#.###.#.#.#.#.#####.#.#########.#.###.#.#.#.#.#.#.#.#.###.#.#####.#.#.#.#.#.#.#.#.#.#.#.###.#####.#.#.#.#.#.#.#.#.#.#.#.#.# +#....0#.#.....#.#...#.......#.......#...#...#.#......1#.....#.....#.........#...#...#.....#.........#.#...#.#.#.#.#...#.#...#.....#...#...#...#.#...#.#.#.#...........#.#.......#.#..3# +#.#####.#.#.#.#.#.###.###.#.###.#.#.#.###.#.#.#.#.#.#.###.#.#.#######.#.#.#.###.#.#.#.#.#######.#.###.###.#.#.###.#####.#.#.#.#####.###.#.#.#########.#.#.#.###.#####.#.#.#####.#.#.### +#...#...#.#.#.....#...#.............#.#.......#.......#.#...#.#.........#.......#.#.....#.......#.......................#.#...#.#.#...#...#.#.#...#...#.......#.........#...#.#.....#.# +#.#.###.#.#.#.#.#.#.#.#.#.###.#.#.#.#.#.###.###.###.#.#.#.#.###.###.###.#.#.#####.#.#.#.#.#.#.#.#.###.#.###########.#.#.#.#.#.#.#.###.###.#.#.#.#.#.#.#.#.#.#.#####.###.#.###.#.#####.# +#...#...#...#...#.#.#.#...#...#...#...#.....#...................#...#.#.....#...........#.....#.#.#...#.#...#.........#.#.......#...........#...#.....#...#.#...............#.#.......# +#.#.#.#.###.#.#.###.#######.#.#.#.#.#.#.###.#.###.#.#.#.###.#.#.#.#.#.#.#####.#.#.###.#.#.###.#.#.#.#.#.###.###.#.#.#.#####.#.###########.#.#.#.#########.#.#.###.###.###.#.#.###.#.#.# +#.#.........#...#.....#.....#.#...#...#.....#...............#...#.......#.#.#.......#.#...#.....#.#.#.........#.#.........#...#...#.........#.#...#.#.#...........#.....#.......#.....# +#.#.#.#.#.###.#.#.#.#.#.#.###.#########.#.#.###.#.#.#####.#####.#.#####.#.#.###.#.#.#.#.#.#.#.#.#.#.#.#.#.###.###.###.#.#.###.###.#.#.#.#.#.###.#.#.#.#.#.#####.###.#.#.#######.#.###.# +#...#.........#...#.#...#.#.#...........#.#.#...........#.......#.#.#.....#...#.#.#.#...#.......#.........#...#.....#...#.....#.#.....#.#...#.....#.#...#.....#.#.#.#.............#...# +#.#.###########.###.#.###.#.#####.#.#.#.###.#.###.#.#.#.#########.#.#.#####.#.#.#.#.#.#.#####.#.#.#.###.#.#.#.#.###############.#.###.#.#.#.#.#.###.###.#.#.#.#.#.#.#####.#.#.###.#.### +#.....#.#...........#.#.............#.#...........#.....#.#.....#...#.#.#.#...........#.#.....#...#.....#...#.....#...........#.#.#...#.........#.#.....#...#.......#.....#...#.......# +#####.#.#.#.#.#.#####.#.#####.#.#.#.#.###.#.#.###.#######.#.#.#####.#.#.#.#.#.#####.###.#.###.#.#.#.#####.#.#.###.#.###.#.###.#.#.###.#.###.###.#.#.#.#.###.#.#####.#.#.#.#####.#.###.# +#.....#.#.....#.#.......#.......#.....#...#...#...............#.....#...........#.........#.....#.#.#.............#.#...#.#.....#.#...#...#...#.........#.....#...#...#...........#...# +#.#.#.###.#.###.#.#.#.###.#.###.#.#.#.###.###.#.###.#.#.#.#####.#.#.#.###.#####.#####.#.#.#.###.#.###.###.#####.#.#.#.#.#.###.###.#.###.#.#.#.#.#.#####.#####.#.#.#.###.#.#.#.#####.### +#...#.....#.#.......#.....#.#.....#...#...#.#.#.....#...#.#...#.#.....................#.....#.....#.....#.......#.........#...#...#...#.#.#.#...#.#.#...#...#.....#.#.......#...#.....# +#####.###.###.#.#.#.#.#.#.###.#.#.#.#####.#.#.#.#.#.#######.#.#.#.#.#.#######.###.#.###.#.#.###.#.#.#.#.#.#####.#.#.#.###.#.###.###.#.###.#.###.#.#.#.#.###.#.###.###.#####.###.#.##### +#.....#.....#...#.....#.#...#...#.........#...................#.....#...#.........#.....#...........#...#.#.......#.#...#...#...............#.......#...#.........#.............#.....# +#.#.#.#.#######.#.#.#########.#######.###.#####.###.#.###.#.#######.#.###.#.###.###.###.#####.#####.###.#.#.#.#.#.#.#.###.#.#.#######.#.#.#.#.#.#.#.#.#####.#.#.#.#.#.#.###.#.#.###.#.# +#2#.#.......#...#.#...#.......#.................#.....#...#.......#.#.....#.....#.#...#.#.....#...#.#.......#...#.....#.....#.....#.......#.....#...#.#...#.....#...#.#.#7..#...#.....# +###.#.#####.#.###.###.#.#.###.#.###.#####.#.#.#######.#.#########.#####.#.#.#.###.#.#.#.###.#######.#.#########.#.#.#.#.#.#.#####.###.###.###.#.#.#.#.#.#.#.###.#.#.#.#.#####.#.#.###.# +#.#...#.....#.....#.#.....#...#...#.#...#...#.#.#.#.....#.....#.#.#.#.....#.................#.#.#...#...#...#.#.#.#.#.#...#...#.#.............#.#...#...#.#.#.......#.........#.#.....# +#.###.#.###.#.#.#.#.###.#.#.###.#####.#.###.#.#.#.#.#.###.#.#.#.#.#.#.#.#.#.#.#####.###.#.###.#.#.###.#.#.#.#.#.#.#.#.#.###.#.#.###.#.#.#.#######.#.###.#.#.#.###.#.#.#.###.###.#.#.#.# +#.#...#.....#.....#.#...#...#.......#...#.....#.#.#.....#.#...#...#...#.#.........#.....#...#.#...#...#...#.#.#.......#...#.#...#...#.#...#.....#.......#.......#.#.....#.#...#.#.....# +#.#.#.#.#.#.#.###.#.###.#.#.#.###.###.#.#.###.###.#.#.#.#.###.#.#.#.#.#.#.#########.#.#.#.#.#.#######.#.###.#.#.#.#.#.#.###.#.###.#######.#.#.#.#.###.#.#.#.#.#.#.#.#####.###.#.#.###.# +#.....#.....#.#...#.#.#...#.....#.....#.#...#.....#.....#.....#.#.#...#...#.#.....#.#.#...#...#.......#.....#...........#...#.#...#.......#.......#.#.#...#.#...#.#.#...........#.....# +#.#####.#####.#####.#.###.#########.#.#.#.#.###.#.#.#.#.#.#.#.#####.###.#.#.#.###.#.###.#.#####.###.#####.#####.#.###.###.#.#.#.#.#.###.#.#.#####.#.#.###.###.###.#.#.#.#.#.###.###.#.# +#.....#...#...#.#...#.........#.................#.#.....#.#.....#.........#...#.....#...#.#.....#.......#.......#.....#.#.#.......#.#...#.#...#.#.........#.........#...#.....#.....#.# +#.###.#####.#.#.#.#.#.#######.#.#####.#########.#.#.###.#.#####.#.#####.###.#.#.#.#.###.#.#.#.#.###.#.#####.#.###.###.#.#.#.###.#.#.#.#.#.#.#.#.#.#####.#.#.###.#.#.#.#.#.#.#.###.###.# +#.#...#.#.....#...#.#.#.......#.#.................#...#.....#...............#.........#...#.#.#...#.#...#...#.........#.....#...........#.#...........#.....#.#.#.#...#...#...#.#.#...# +#.#.#.#.#.###.#######.#.#.#.###.#.#.#.###.#.#.###.###.#.###.#.#####.#.#.#.#.#.###.#########.#.#.#.#.#.#.#######.###.#.#.###.#.#.###.#.###.#.#.###.#.#.#.#.#.#.#.#.#.###.#####.#.###.#.# +#.#.....#.....#.#.......#...#...#...#.#...#.....#.......#...#...#...#.#.#...#...#.....#.#...#...........#.........#...#.#...#...#...#...#...........#5#.#...#...........#.....#.#.....# +###.#.###.#####.#.#.#.#.#.###.#.#.#####.#.#.#.#.#.#.#.###.###.#.#.###.#.###.###.#####.#.#.###.#.#.###.#.#.#.###.#####.###.#####.#.#.###.#.#####.#.#.#.#####.###.###.###.#.#.#.#.#.#.### +#.........#.....#.....#...#...............#.#...#.#.#.....#.#...#...#.#...............#.......#.......#.#...#.#...........#.#.#...............#...#.........#...............#...#...#.# +#.#.#.###.#.#####.#.#.#.#.#.#.###.###.###.#####.#.#####.###.#.#.###.#.###.###.#####.#####.#####.#########.###.#.#.#.#.#.#.#.#.#.#.#.#.###.#.#.###.#####.###.#####.###.#.###.###.#.#.#.# +#.....#.#.............#...#.......#.#.............#.#...#.#...#...#.#.....#.#.#...#.#.....#...#...........#.....#.#.#...#...................#.....#.....#...............#.....#.#.....# +#.#####.#.###.#.#######.###.###.#.#.#.###.###.#.###.#.#.#.###.#.#.#.#####.#.###.###.#########.#.#####.#.#.#.#.#.#.#.#####.#########.#.#.#.#.###.###.#.#####.#.#.###.#####.#.#.###.###.# +#...#.....#4#.#.#...............#.........#.....#.......#.........#...........#...#.......#.#...#.......#.....#...#.#...#.#...#.#.....#...........#.................#...#.#.#.#...#.#.# +#.#.#.#####.#.###.###.#.#.#####.#.#####.###.#.###.#.#######.#.#.###.###.###.#.#.#.#.#.#.#.#.#.#.#.#.#######.#######.#.#.###.###.#.###.#.###.#.#.#.#.#.#######.#.#.###.#.###.#####.#.#.# +#.....#.#.....#...#...#.#.......#...#.............#...#.....#...#.#.......#.....#...#...#.#.....#.#...........#.......#.#...#...#.#...#.#.#.....#...............#...#.#.#...#...#.....# +#####.#.#.#.###.#.###.#.#####.#######.#############.#.#.#.#.#.###.#.#.###.#.#####.#.#.#.#####.#.#.###.###.#.#.#.###.#.#.###.#.#.#.#.#.#.#.#.#.###.###.#.#######.###.#.#####.#######.### +#.....#...........#.....#.....#.......#...#...#.......#.....#.#...#.#.#...#.#...#.....#.......#...#...#...#.#.#.#.....#.....#...#.#...#......6#...#...#.....#...#...#.........#.#.....# +####################################################################################################################################################################################### diff --git a/day24.html b/day24.html new file mode 100644 index 0000000..54becd2 --- /dev/null +++ b/day24.html @@ -0,0 +1,152 @@ +<!DOCTYPE html> +<html lang="en-us"> +<head> +<meta charset="utf-8"/> +<title>Day 24 - Advent of Code 2016</title> +<!--[if lt IE 9]><script src="/static/html5.js"></script><![endif]--> +<link href='//fonts.googleapis.com/css?family=Source+Code+Pro:300&subset=latin,latin-ext' rel='stylesheet' type='text/css'> +<link rel="stylesheet" type="text/css" href="/static/style.css?10"/> +<link rel="shortcut icon" href="/favicon.ico?2"/> +</head><!-- + + + + +Oh, hello! Funny seeing you here. + +I appreciate your enthusiasm, but you aren't going to find much down here. +There certainly aren't clues to any of the puzzles. The best surprises don't +even appear in the source until you unlock them for real. + +Please be careful with automated requests; I'm not Google, and I can only take +so much traffic. Please be considerate so that everyone gets to play. + +If you're curious about how Advent of Code works, it's running on some custom +Perl code. Other than a few integrations (auth, analytics, ads, social media), +I built the whole thing myself, including the design, animations, prose, and +all of the puzzles. + +The puzzles probably took the longest; the easiest ones were around 45 minutes +each, but the harder ones took 2-3 hours, and a few even longer than that. A +lot of effort went into building this thing - I hope you're enjoying playing it +as much as I enjoyed making it for you! + +If you'd like to hang out, I'm @ericwastl on Twitter. + +- Eric Wastl + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +--> +<body> +<header><div><h1 class="title-global"><a href="/">Advent of Code</a></h1><nav><ul><li><a href="/2016/about">[About]</a></li><li><a href="/2016/support">[AoC++]</a></li><li><a href="/2016/events">[Events]</a></li><li><a href="/2016/settings">[Settings]</a></li><li><a href="/2016/auth/logout">[Log Out]</a></li></ul></nav><div class="user">Neil Smith <span class="supporter">(AoC++)</span> <span class="star-count">48*</span></div></div><div><h1 class="title-event"> <span class="title-event-wrap">int y=</span><a href="/2016">2016</a><span class="title-event-wrap">;</span></h1><nav><ul><li><a href="/2016">[Calendar]</a></li><li><a href="/2016/leaderboard">[Leaderboard]</a></li><li><a href="/2016/stats">[Stats]</a></li><li><a href="/2016/sponsors">[Sponsors]</a></li></ul></nav></div></header> + +<div id="sidebar"> +<div id="sponsor"><div class="quiet">Our <a href="/2016/sponsors">sponsors</a> help make AoC possible:</div><p><a href="https://info.esparklearning.com/join-our-team-full-stack-engineer" target="_blank" onclick="if(ga)ga('send','event','sponsor','click',this.href);">eSpark Learning</a> - Solve the greatest puzzle of our day - transform education</p></div> +<div id="ad"> +<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script> +<!-- Advent of Code Wide Skyscraper --> +<ins class="adsbygoogle" + style="display:inline-block;width:160px;height:600px" + data-ad-client="ca-pub-9420604735624631" + data-ad-slot="8014013294"></ins> +<script> +(adsbygoogle = window.adsbygoogle || []).push({}); +</script> +</div><!--/ad--> +</div><!--/sidebar--> + +<main> +<article class="day-desc"><h2>--- Day 24: Air Duct Spelunking ---</h2><p>You've finally met your match; the doors that provide access to the roof are locked tight, and all of the controls and related electronics are inaccessible. You simply can't reach them.</p> +<p>The robot that cleans the air ducts, however, <em>can</em>.</p> +<p>It's not a very fast <span title="The Brave Little Air Duct Cleaning Robot That Could">little robot</span>, but you reconfigure it to be able to interface with some of the exposed wires that have been routed through the <a href="https://en.wikipedia.org/wiki/HVAC">HVAC</a> system. If you can direct it to each of those locations, you should be able to bypass the security controls.</p> +<p>You extract the duct layout for this area from some blueprints you acquired and create a map with the relevant locations marked (your puzzle input). <code>0</code> is your current location, from which the cleaning robot embarks; the other numbers are (in <em>no particular order</em>) the locations the robot needs to visit at least once each. Walls are marked as <code>#</code>, and open passages are marked as <code>.</code>. Numbers behave like open passages.</p> +<p>For example, suppose you have a map like the following:</p> +<pre><code>########### +#0.1.....2# +#.#######.# +#4.......3# +########### +</code></pre> +<p>To reach all of the points of interest as quickly as possible, you would have the robot take the following path:</p> +<ul> +<li><code>0</code> to <code>4</code> (<code>2</code> steps)</li> +<li><code>4</code> to <code>1</code> (<code>4</code> steps; it can't move diagonally)</li> +<li><code>1</code> to <code>2</code> (<code>6</code> steps)</li> +<li><code>2</code> to <code>3</code> (<code>2</code> steps)</li> +</ul> +<p>Since the robot isn't very fast, you need to find it the <em>shortest route</em>. This path is the fewest steps (in the above example, a total of <code>14</code>) required to start at <code>0</code> and then visit every other location at least once.</p> +<p>Given your actual map, and starting from location <code>0</code>, what is the <em>fewest number of steps</em> required to visit every non-<code>0</code> number marked on the map at least once?</p> +</article> +<p>Your puzzle answer was <code>412</code>.</p><article class="day-desc"><h2>--- Part Two ---</h2><p>Of course, if you leave the cleaning robot somewhere weird, someone is bound to notice.</p> +<p>What is the fewest number of steps required to start at <code>0</code>, visit every non-<code>0</code> number marked on the map at least once, and then <em>return to <code>0</code></em>?</p> +</article> +<p>Your puzzle answer was <code>664</code>.</p><p class="day-success">Both parts of this puzzle are complete! They provide two gold stars: **</p> +<p>At this point, you should <a href="/2016">return to your advent calendar</a> and try another puzzle.</p> +<p>If you still want to see it, you can <a href="24/input" target="_blank">get your puzzle input</a>.</p> +<p>You can also <span class="share">[Share<span class="share-content">on + <a href="https://twitter.com/intent/tweet?text=I%27ve+completed+%22Air+Duct+Spelunking%22+%2D+Day+24+%2D+Advent+of+Code+2016&url=http%3A%2F%2Fadventofcode%2Ecom%2F2016%2Fday%2F24&related=ericwastl&hashtags=AdventOfCode" target="_blank">Twitter</a> + <a href="https://plus.google.com/share?url=http%3A%2F%2Fadventofcode%2Ecom%2F2016%2Fday%2F24" target="_blank">Google+</a> + <a href="http://www.reddit.com/submit?url=http%3A%2F%2Fadventofcode%2Ecom%2F2016%2Fday%2F24&title=I%27ve+completed+%22Air+Duct+Spelunking%22+%2D+Day+24+%2D+Advent+of+Code+2016" target="_blank">Reddit</a +></span>]</span> this puzzle.</p> +</main> + +<!-- ga --> +<script> +(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ +(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), +m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) +})(window,document,'script','//www.google-analytics.com/analytics.js','ga'); +ga('create', 'UA-69522494-1', 'auto'); +ga('send', 'pageview'); +</script> +<!-- /ga --> +</body> +</html> \ No newline at end of file diff --git a/stack.yaml b/stack.yaml index 48e2e2e..b51ba57 100644 --- a/stack.yaml +++ b/stack.yaml @@ -4,6 +4,7 @@ packages: - adventofcode16 - adventofcode1601 - adventofcode1602 +- adventofcode1624 system-ghc: true extra-deps: - astar-0.3.0.0 -- 2.43.0