From: Neil Smith <neil.git@njae.me.uk> 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 @@ +<!DOCTYPE html> +<html lang="en-us"> +<head> +<meta charset="utf-8"/> +<title>Day 13 - 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?9"/> +<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">26*</span></div></div><div><h1 class="title-event"> <span class="title-event-wrap">λ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://www.detroitlabs.com/careers" target="_blank" onclick="if(ga)ga('send','event','sponsor','click',this.href);">Detroit Labs</a> - Build beautiful mobile apps.</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 13: A Maze of Twisty Little Cubicles ---</h2><p>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 <span title="You are in a twisty alike of little cubicles, all maze.">twisty little cubicles</span>, all alike.</p> +<p>Every location in this area is addressed by a pair of non-negative integers (<code>x,y</code>). Each such coordinate is either a wall or an open space. You can't move diagonally. The cube maze starts at <code>0,0</code> and seems to extend infinitely toward <em>positive</em> <code>x</code> and <code>y</code>; negative values are <em>invalid</em>, as they represent a location outside the building. You are in a small waiting area at <code>1,1</code>.</p> +<p>While it seems chaotic, a nearby morale-boosting poster explains, the layout is actually quite logical. You can determine whether a given <code>x,y</code> coordinate will be a wall or an open space using a simple system:</p> +<ul> +<li>Find <code>x*x + 3*x + 2*x*y + y + y*y</code>.</li> +<li>Add the office designer's favorite number (your puzzle input).</li> +<li>Find the <a href="https://en.wikipedia.org/wiki/Binary_number">binary representation</a> of that sum; count the <em>number</em> of <a href="https://en.wikipedia.org/wiki/Bit">bits</a> that are <code>1</code>. +<ul> +<li>If the number of bits that are <code>1</code> is <em>even</em>, it's an <em>open space</em>.</li> +<li>If the number of bits that are <code>1</code> is <em>odd</em>, it's a <em>wall</em>.</li> +</ul> +</li> +</ul> +<p>For example, if the office designer's favorite number were <code>10</code>, drawing walls as <code>#</code> and open spaces as <code>.</code>, the corner of the building containing <code>0,0</code> would look like this:</p> +<pre><code> 0123456789 +0 .#.####.## +1 ..#..#...# +2 #....##... +3 ###.#.###. +4 .##..#..#. +5 ..##....#. +6 #...##.### +</code></pre> +<p>Now, suppose you wanted to reach <code>7,4</code>. The shortest route you could take is marked as <code>O</code>:</p> +<pre><code> 0123456789 +0 .#.####.## +1 .O#..#...# +2 #OOO.##... +3 ###O#.###. +4 .##OO#OO#. +5 ..##OOO.#. +6 #...##.### +</code></pre> +<p>Thus, reaching <code>7,4</code> would take a minimum of <code>11</code> steps (starting from your current location, <code>1,1</code>).</p> +<p>What is the <em>fewest number of steps required</em> for you to reach <code>31,39</code>?</p> +</article> +<p>Your puzzle answer was <code>82</code>.</p><article class="day-desc"><h2>--- Part Two ---</h2><p><em>How many locations</em> (distinct <code>x,y</code> coordinates, including your starting location) can you reach in at most <code>50</code> steps?</p> +</article> +<p>Your puzzle answer was <code>138</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>Your puzzle input was <code class="puzzle-input">1362</code>.</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+%22A+Maze+of+Twisty+Little+Cubicles%22+%2D+Day+13+%2D+Advent+of+Code+2016&url=http%3A%2F%2Fadventofcode%2Ecom%2F2016%2Fday%2F13&related=ericwastl&hashtags=AdventOfCode" target="_blank">Twitter</a> + <a href="https://plus.google.com/share?url=http%3A%2F%2Fadventofcode%2Ecom%2F2016%2Fday%2F13" target="_blank">Google+</a> + <a href="http://www.reddit.com/submit?url=http%3A%2F%2Fadventofcode%2Ecom%2F2016%2Fday%2F13&title=I%27ve+completed+%22A+Maze+of+Twisty+Little+Cubicles%22+%2D+Day+13+%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