Day 24 at last
authorNeil Smith <neil.git@njae.me.uk>
Sun, 25 Dec 2016 16:01:27 +0000 (16:01 +0000)
committerNeil Smith <neil.git@njae.me.uk>
Sun, 25 Dec 2016 16:01:27 +0000 (16:01 +0000)
adventofcode1624/adventofcode1624.cabal [new file with mode: 0644]
adventofcode1624/app/advent24.hs [new file with mode: 0644]
data/advent24.txt [new file with mode: 0644]
day24.html [new file with mode: 0644]
stack.yaml

diff --git a/adventofcode1624/adventofcode1624.cabal b/adventofcode1624/adventofcode1624.cabal
new file mode 100644 (file)
index 0000000..f016db1
--- /dev/null
@@ -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 (file)
index 0000000..fc97d16
--- /dev/null
@@ -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 (file)
index 0000000..771b64d
--- /dev/null
@@ -0,0 +1,45 @@
+#######################################################################################################################################################################################
+#.......#.....#.....#.#.....#.#...#.#.......#.....#.#...#.......#...........#...#.............#.....#.......#.........#.....#.....#...........#.#...................#.....#...........#
+#.#######.#.#.#.###.#.#####.#.#.#.#.#####.#.#.###.#.#######.#.###.#.#.#.#.#####.#.#########.#.###.#.#.#.#.#.#.#.#.###.#.#####.#.#.#.#.#.#.#.#.#.#.#.###.#####.#.#.#.#.#.#.#.#.#.#.#.#.#
+#....0#.#.....#.#...#.......#.......#...#...#.#......1#.....#.....#.........#...#...#.....#.........#.#...#.#.#.#.#...#.#...#.....#...#...#...#.#...#.#.#.#...........#.#.......#.#..3#
+#.#####.#.#.#.#.#.###.###.#.###.#.#.#.###.#.#.#.#.#.#.###.#.#.#######.#.#.#.###.#.#.#.#.#######.#.###.###.#.#.###.#####.#.#.#.#####.###.#.#.#########.#.#.#.###.#####.#.#.#####.#.#.###
+#...#...#.#.#.....#...#.............#.#.......#.......#.#...#.#.........#.......#.#.....#.......#.......................#.#...#.#.#...#...#.#.#...#...#.......#.........#...#.#.....#.#
+#.#.###.#.#.#.#.#.#.#.#.#.###.#.#.#.#.#.###.###.###.#.#.#.#.###.###.###.#.#.#####.#.#.#.#.#.#.#.#.###.#.###########.#.#.#.#.#.#.#.###.###.#.#.#.#.#.#.#.#.#.#.#####.###.#.###.#.#####.#
+#...#...#...#...#.#.#.#...#...#...#...#.....#...................#...#.#.....#...........#.....#.#.#...#.#...#.........#.#.......#...........#...#.....#...#.#...............#.#.......#
+#.#.#.#.###.#.#.###.#######.#.#.#.#.#.#.###.#.###.#.#.#.###.#.#.#.#.#.#.#####.#.#.###.#.#.###.#.#.#.#.#.###.###.#.#.#.#####.#.###########.#.#.#.#########.#.#.###.###.###.#.#.###.#.#.#
+#.#.........#...#.....#.....#.#...#...#.....#...............#...#.......#.#.#.......#.#...#.....#.#.#.........#.#.........#...#...#.........#.#...#.#.#...........#.....#.......#.....#
+#.#.#.#.#.###.#.#.#.#.#.#.###.#########.#.#.###.#.#.#####.#####.#.#####.#.#.###.#.#.#.#.#.#.#.#.#.#.#.#.#.###.###.###.#.#.###.###.#.#.#.#.#.###.#.#.#.#.#.#####.###.#.#.#######.#.###.#
+#...#.........#...#.#...#.#.#...........#.#.#...........#.......#.#.#.....#...#.#.#.#...#.......#.........#...#.....#...#.....#.#.....#.#...#.....#.#...#.....#.#.#.#.............#...#
+#.#.###########.###.#.###.#.#####.#.#.#.###.#.###.#.#.#.#########.#.#.#####.#.#.#.#.#.#.#####.#.#.#.###.#.#.#.#.###############.#.###.#.#.#.#.#.###.###.#.#.#.#.#.#.#####.#.#.###.#.###
+#.....#.#...........#.#.............#.#...........#.....#.#.....#...#.#.#.#...........#.#.....#...#.....#...#.....#...........#.#.#...#.........#.#.....#...#.......#.....#...#.......#
+#####.#.#.#.#.#.#####.#.#####.#.#.#.#.###.#.#.###.#######.#.#.#####.#.#.#.#.#.#####.###.#.###.#.#.#.#####.#.#.###.#.###.#.###.#.#.###.#.###.###.#.#.#.#.###.#.#####.#.#.#.#####.#.###.#
+#.....#.#.....#.#.......#.......#.....#...#...#...............#.....#...........#.........#.....#.#.#.............#.#...#.#.....#.#...#...#...#.........#.....#...#...#...........#...#
+#.#.#.###.#.###.#.#.#.###.#.###.#.#.#.###.###.#.###.#.#.#.#####.#.#.#.###.#####.#####.#.#.#.###.#.###.###.#####.#.#.#.#.#.###.###.#.###.#.#.#.#.#.#####.#####.#.#.#.###.#.#.#.#####.###
+#...#.....#.#.......#.....#.#.....#...#...#.#.#.....#...#.#...#.#.....................#.....#.....#.....#.......#.........#...#...#...#.#.#.#...#.#.#...#...#.....#.#.......#...#.....#
+#####.###.###.#.#.#.#.#.#.###.#.#.#.#####.#.#.#.#.#.#######.#.#.#.#.#.#######.###.#.###.#.#.###.#.#.#.#.#.#####.#.#.#.###.#.###.###.#.###.#.###.#.#.#.#.###.#.###.###.#####.###.#.#####
+#.....#.....#...#.....#.#...#...#.........#...................#.....#...#.........#.....#...........#...#.#.......#.#...#...#...............#.......#...#.........#.............#.....#
+#.#.#.#.#######.#.#.#########.#######.###.#####.###.#.###.#.#######.#.###.#.###.###.###.#####.#####.###.#.#.#.#.#.#.#.###.#.#.#######.#.#.#.#.#.#.#.#.#####.#.#.#.#.#.#.###.#.#.###.#.#
+#2#.#.......#...#.#...#.......#.................#.....#...#.......#.#.....#.....#.#...#.#.....#...#.#.......#...#.....#.....#.....#.......#.....#...#.#...#.....#...#.#.#7..#...#.....#
+###.#.#####.#.###.###.#.#.###.#.###.#####.#.#.#######.#.#########.#####.#.#.#.###.#.#.#.###.#######.#.#########.#.#.#.#.#.#.#####.###.###.###.#.#.#.#.#.#.#.###.#.#.#.#.#####.#.#.###.#
+#.#...#.....#.....#.#.....#...#...#.#...#...#.#.#.#.....#.....#.#.#.#.....#.................#.#.#...#...#...#.#.#.#.#.#...#...#.#.............#.#...#...#.#.#.......#.........#.#.....#
+#.###.#.###.#.#.#.#.###.#.#.###.#####.#.###.#.#.#.#.#.###.#.#.#.#.#.#.#.#.#.#.#####.###.#.###.#.#.###.#.#.#.#.#.#.#.#.#.###.#.#.###.#.#.#.#######.#.###.#.#.#.###.#.#.#.###.###.#.#.#.#
+#.#...#.....#.....#.#...#...#.......#...#.....#.#.#.....#.#...#...#...#.#.........#.....#...#.#...#...#...#.#.#.......#...#.#...#...#.#...#.....#.......#.......#.#.....#.#...#.#.....#
+#.#.#.#.#.#.#.###.#.###.#.#.#.###.###.#.#.###.###.#.#.#.#.###.#.#.#.#.#.#.#########.#.#.#.#.#.#######.#.###.#.#.#.#.#.#.###.#.###.#######.#.#.#.#.###.#.#.#.#.#.#.#.#####.###.#.#.###.#
+#.....#.....#.#...#.#.#...#.....#.....#.#...#.....#.....#.....#.#.#...#...#.#.....#.#.#...#...#.......#.....#...........#...#.#...#.......#.......#.#.#...#.#...#.#.#...........#.....#
+#.#####.#####.#####.#.###.#########.#.#.#.#.###.#.#.#.#.#.#.#.#####.###.#.#.#.###.#.###.#.#####.###.#####.#####.#.###.###.#.#.#.#.#.###.#.#.#####.#.#.###.###.###.#.#.#.#.#.###.###.#.#
+#.....#...#...#.#...#.........#.................#.#.....#.#.....#.........#...#.....#...#.#.....#.......#.......#.....#.#.#.......#.#...#.#...#.#.........#.........#...#.....#.....#.#
+#.###.#####.#.#.#.#.#.#######.#.#####.#########.#.#.###.#.#####.#.#####.###.#.#.#.#.###.#.#.#.#.###.#.#####.#.###.###.#.#.#.###.#.#.#.#.#.#.#.#.#.#####.#.#.###.#.#.#.#.#.#.#.###.###.#
+#.#...#.#.....#...#.#.#.......#.#.................#...#.....#...............#.........#...#.#.#...#.#...#...#.........#.....#...........#.#...........#.....#.#.#.#...#...#...#.#.#...#
+#.#.#.#.#.###.#######.#.#.#.###.#.#.#.###.#.#.###.###.#.###.#.#####.#.#.#.#.#.###.#########.#.#.#.#.#.#.#######.###.#.#.###.#.#.###.#.###.#.#.###.#.#.#.#.#.#.#.#.#.###.#####.#.###.#.#
+#.#.....#.....#.#.......#...#...#...#.#...#.....#.......#...#...#...#.#.#...#...#.....#.#...#...........#.........#...#.#...#...#...#...#...........#5#.#...#...........#.....#.#.....#
+###.#.###.#####.#.#.#.#.#.###.#.#.#####.#.#.#.#.#.#.#.###.###.#.#.###.#.###.###.#####.#.#.###.#.#.###.#.#.#.###.#####.###.#####.#.#.###.#.#####.#.#.#.#####.###.###.###.#.#.#.#.#.#.###
+#.........#.....#.....#...#...............#.#...#.#.#.....#.#...#...#.#...............#.......#.......#.#...#.#...........#.#.#...............#...#.........#...............#...#...#.#
+#.#.#.###.#.#####.#.#.#.#.#.#.###.###.###.#####.#.#####.###.#.#.###.#.###.###.#####.#####.#####.#########.###.#.#.#.#.#.#.#.#.#.#.#.#.###.#.#.###.#####.###.#####.###.#.###.###.#.#.#.#
+#.....#.#.............#...#.......#.#.............#.#...#.#...#...#.#.....#.#.#...#.#.....#...#...........#.....#.#.#...#...................#.....#.....#...............#.....#.#.....#
+#.#####.#.###.#.#######.###.###.#.#.#.###.###.#.###.#.#.#.###.#.#.#.#####.#.###.###.#########.#.#####.#.#.#.#.#.#.#.#####.#########.#.#.#.#.###.###.#.#####.#.#.###.#####.#.#.###.###.#
+#...#.....#4#.#.#...............#.........#.....#.......#.........#...........#...#.......#.#...#.......#.....#...#.#...#.#...#.#.....#...........#.................#...#.#.#.#...#.#.#
+#.#.#.#####.#.###.###.#.#.#####.#.#####.###.#.###.#.#######.#.#.###.###.###.#.#.#.#.#.#.#.#.#.#.#.#.#######.#######.#.#.###.###.#.###.#.###.#.#.#.#.#.#######.#.#.###.#.###.#####.#.#.#
+#.....#.#.....#...#...#.#.......#...#.............#...#.....#...#.#.......#.....#...#...#.#.....#.#...........#.......#.#...#...#.#...#.#.#.....#...............#...#.#.#...#...#.....#
+#####.#.#.#.###.#.###.#.#####.#######.#############.#.#.#.#.#.###.#.#.###.#.#####.#.#.#.#####.#.#.###.###.#.#.#.###.#.#.###.#.#.#.#.#.#.#.#.#.###.###.#.#######.###.#.#####.#######.###
+#.....#...........#.....#.....#.......#...#...#.......#.....#.#...#.#.#...#.#...#.....#.......#...#...#...#.#.#.#.....#.....#...#.#...#......6#...#...#.....#...#...#.........#.#.....#
+#######################################################################################################################################################################################
diff --git a/day24.html b/day24.html
new file mode 100644 (file)
index 0000000..54becd2
--- /dev/null
@@ -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">&nbsp;&nbsp;&nbsp;<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&amp;url=http%3A%2F%2Fadventofcode%2Ecom%2F2016%2Fday%2F24&amp;related=ericwastl&amp;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&amp;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
index 48e2e2e7544e29afa60afc1985e49e804c4c03e3..b51ba57042d141bea041e024fb3d1f301bc779ed 100644 (file)
@@ -4,6 +4,7 @@ packages:
 - adventofcode16
 - adventofcode1601
 - adventofcode1602
+- adventofcode1624
 system-ghc: true
 extra-deps:
 - astar-0.3.0.0