From: Neil Smith Date: Tue, 13 Dec 2016 10:32:31 +0000 (+0000) Subject: Day 13 X-Git-Url: https://git.njae.me.uk/?a=commitdiff_plain;h=a8f5015eb056a15e732a2d53b0c79fc8e7267f79;p=advent-of-code-16.git Day 13 --- diff --git a/advent13.hs b/advent13.hs new file mode 100644 index 0000000..a6e56d9 --- /dev/null +++ b/advent13.hs @@ -0,0 +1,101 @@ +import Data.List ((\\), nub, sortOn) +import Numeric (showIntAtBase) +import Data.Char (intToDigit) +import Data.Bits (popCount) + +import qualified Data.Map.Lazy as Map -- day 4, 5 + +type Pos = (Int, Int) + +seed = 1362 + +goal1 = (31, 39) + +main :: IO () +main = do + part1 + part2 + + +part1 :: IO () +part1 = print $ length $ tail $ extractJust $ aStar [[(1, 1)]] [] + +part2 :: IO () +part2 = do print $ length $ tail $ edl 50 [[(1, 1)]] [] + putStrLn $ showRoomR 30 25 $ edl 50 [[(1, 1)]] [] +-- part2 = print $ length $ tail $ edl 50 [[(1, 1)]] [] + + +extractJust :: Maybe [a] -> [a] +extractJust Nothing = [] +extractJust (Just x) = x + +isWall :: Int -> Int -> Bool +isWall x y = (popCount n) `mod` 2 == 1 + where + n = x*x + 3*x + 2*x*y + y + y*y + seed + + +showRoom w h = unlines rows + where + rows = [row x | x <- [0..h]] + row x = [showCell x y | y <- [0..w]] + showCell x y = if (isWall x y) then '#' else '.' + +showRoomR w h reached = unlines rows + where + rows = [row x | x <- [0..h]] + row x = [showCell x y | y <- [0..w]] + showCell x y = if (isWall x y) + then '#' + else if (x, y) `elem` reached + then 'O' + else '.' + + +aStar :: [[Pos]] -> [Pos] -> Maybe [Pos] +aStar [] _ = Nothing +aStar (currentTrail:trails) closed = + if isGoal (head currentTrail) then Just currentTrail + else if (head currentTrail) `elem` closed then aStar trails closed + else aStar newAgenda ((head currentTrail): closed) + where newAgenda = + sortOn (\a -> trailCost a) $ + trails ++ (candidates currentTrail closed) + trailCost t = estimateCost (head t) + length t - 1 + + +-- exhaustive depth-limited +edl :: Int -> [[Pos]] -> [Pos] -> [Pos] +edl _ [] closed = nub closed +edl limit (currentTrail:trails) closed = + if (length currentTrail) > (limit+1) then edl limit trails ((head currentTrail):closed) + else if (head currentTrail) `elem` closed then edl limit trails closed + else edl limit newAgenda ((head currentTrail):closed) + where newAgenda = trails ++ (candidates currentTrail closed) + +candidates :: [Pos] -> [Pos] -> [[Pos]] +candidates currentTrail closed = newCandidates + where + (candidate:trail) = currentTrail + succs = legalSuccessors $ successors candidate + nonloops = (succs \\ trail) \\ closed + newCandidates = map (\n -> n:candidate:trail) nonloops + +isGoal :: Pos -> Bool +isGoal p = p == goal1 + +isLegal :: Pos -> Bool +isLegal (x, y) = + x >= 0 && y >= 0 && (not $ isWall x y) + +successors :: Pos -> [Pos] +successors (x, y) = [(x-1, y), (x+1, y), (x, y-1), (x, y+1)] + +legalSuccessors :: [Pos] -> [Pos] +legalSuccessors = filter (isLegal) + +estimateCost :: Pos -> Int +estimateCost (x, y) = abs (x - gx) + abs (y - gy) + where (gx, gy) = goal1 + diff --git a/day13.html b/day13.html new file mode 100644 index 0000000..600952c --- /dev/null +++ b/day13.html @@ -0,0 +1,166 @@ + + + + +Day 13 - Advent of Code 2016 + + + + + + +

Advent of Code

Neil Smith (AoC++) 26*

       Î»y.2016

+ + + +
+

--- Day 13: A Maze of Twisty Little Cubicles ---

You arrive at the first floor of this new building to discover a much less welcoming environment than the shiny atrium of the last one. Instead, you are in a maze of twisty little cubicles, all alike.

+

Every location in this area is addressed by a pair of non-negative integers (x,y). Each such coordinate is either a wall or an open space. You can't move diagonally. The cube maze starts at 0,0 and seems to extend infinitely toward positive x and y; negative values are invalid, as they represent a location outside the building. You are in a small waiting area at 1,1.

+

While it seems chaotic, a nearby morale-boosting poster explains, the layout is actually quite logical. You can determine whether a given x,y coordinate will be a wall or an open space using a simple system:

+
    +
  • Find x*x + 3*x + 2*x*y + y + y*y.
  • +
  • Add the office designer's favorite number (your puzzle input).
  • +
  • Find the binary representation of that sum; count the number of bits that are 1. +
      +
    • If the number of bits that are 1 is even, it's an open space.
    • +
    • If the number of bits that are 1 is odd, it's a wall.
    • +
    +
  • +
+

For example, if the office designer's favorite number were 10, drawing walls as # and open spaces as ., the corner of the building containing 0,0 would look like this:

+
  0123456789
+0 .#.####.##
+1 ..#..#...#
+2 #....##...
+3 ###.#.###.
+4 .##..#..#.
+5 ..##....#.
+6 #...##.###
+
+

Now, suppose you wanted to reach 7,4. The shortest route you could take is marked as O:

+
  0123456789
+0 .#.####.##
+1 .O#..#...#
+2 #OOO.##...
+3 ###O#.###.
+4 .##OO#OO#.
+5 ..##OOO.#.
+6 #...##.###
+
+

Thus, reaching 7,4 would take a minimum of 11 steps (starting from your current location, 1,1).

+

What is the fewest number of steps required for you to reach 31,39?

+
+

Your puzzle answer was 82.

--- Part Two ---

How many locations (distinct x,y coordinates, including your starting location) can you reach in at most 50 steps?

+
+

Your puzzle answer was 138.

Both parts of this puzzle are complete! They provide two gold stars: **

+

At this point, you should return to your advent calendar and try another puzzle.

+

Your puzzle input was 1362.

+

You can also this puzzle.

+
+ + + + + + \ No newline at end of file