Day 17
authorNeil Smith <neil.git@njae.me.uk>
Sat, 17 Dec 2016 10:48:33 +0000 (10:48 +0000)
committerNeil Smith <neil.git@njae.me.uk>
Sat, 17 Dec 2016 10:48:33 +0000 (10:48 +0000)
advent17.hs [new file with mode: 0644]
day17.html [new file with mode: 0644]

diff --git a/advent17.hs b/advent17.hs
new file mode 100644 (file)
index 0000000..d255a09
--- /dev/null
@@ -0,0 +1,86 @@
+import Data.List (subsequences, (\\), sort, sortBy)
+import Data.Ord (comparing)
+import Data.ByteString.Char8 (pack)
+import Crypto.Hash (hash, Digest, MD5)
+
+
+type Position = (Int, Int)
+data Agendum = Agendum {position :: Position, path :: String, hsh :: String} deriving (Show, Eq)
+type Agenda = [Agendum]
+
+-- input = "hijkl"
+-- input = "ihgpwlah"
+
+input = "qljzarfv" -- my input
+
+
+
+main :: IO ()
+main = do 
+    part1 
+    part2 
+
+initialAgenda = [Agendum {position=(1, 1), path="", hsh=(getHash "")}]
+
+
+part1 :: IO ()
+part1 = print $ path $ extractJust $ bfs initialAgenda
+
+part2 :: IO ()
+part2 = print $ bfs2 initialAgenda 0
+
+
+getHash :: String -> String
+getHash path = show (hash $ pack (input ++ path) :: Digest MD5)
+
+
+extractJust :: Maybe Agendum -> Agendum
+extractJust Nothing = head initialAgenda
+extractJust (Just x) = x
+
+
+bfs :: Agenda -> Maybe Agendum
+bfs [] = Nothing
+bfs (current:agenda) = 
+    if isGoal current then Just current
+    else bfs (agenda ++ (successors current))
+
+
+bfs2 :: Agenda -> Int -> Int
+bfs2 [] l = l
+bfs2 (current:agenda) l = 
+    if isGoal current then bfs2 agenda (length $ path $ current)
+    else bfs2 (agenda ++ (successors current)) l
+
+
+isGoal :: Agendum -> Bool
+isGoal agendum = (position agendum) == (4, 4)
+
+isLegalPos :: Position -> Bool
+isLegalPos p = fst p >= 1 && fst p <= 4 && snd p >= 1 && snd p <= 4
+
+successors :: Agendum -> Agenda
+successors state = [Agendum {position = step p0 ld, 
+                             path = path0 ++ [ld],
+                             hsh = getHash (path0 ++ [ld])} | ld <- legalDoors ]
+    where 
+        p0 = position state
+        path0 = path state
+        h0 = hsh state
+        doors = openDoors h0
+        legalDoors = filter (isLegalPos . (step p0)) doors
+
+openDoors hash = (u hash) ++ (d hash) ++ (l hash) ++ (r hash)
+
+u hash = if hash!!0 `elem` "bcdef" then "U" else ""
+d hash = if hash!!1 `elem` "bcdef" then "D" else ""
+l hash = if hash!!2 `elem` "bcdef" then "L" else ""
+r hash = if hash!!3 `elem` "bcdef" then "R" else ""
+
+step (r, c) 'U' = (r-1, c)
+step (r, c) 'D' = (r+1, c)
+step (r, c) 'L' = (r, c-1)
+step (r, c) 'R' = (r, c+1)
+
+
+
diff --git a/day17.html b/day17.html
new file mode 100644 (file)
index 0000000..6b440f1
--- /dev/null
@@ -0,0 +1,164 @@
+<!DOCTYPE html>
+<html lang="en-us">
+<head>
+<meta charset="utf-8"/>
+<title>Day 17 - 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">34*</span></div></div><div><h1 class="title-event">&nbsp;&nbsp;&nbsp;<span class="title-event-wrap">$year=</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 17: Two Steps Forward ---</h2><p>You're trying to access a secure vault protected by a <code>4x4</code> grid of small rooms connected by doors. You start in the top-left room (marked <code>S</code>), and you can access the vault (marked <code>V</code>) once you reach the bottom-right room:</p>
+<pre><code>#########
+#S| | | #
+#-#-#-#-#
+# | | | #
+#-#-#-#-#
+# | | | #
+#-#-#-#-#
+# | | |  
+####### V
+</code></pre>
+<p>Fixed walls are marked with <code>#</code>, and doors are marked with <code>-</code> or <code>|</code>.</p>
+<p>The doors in your <em>current room</em> are either open or closed (and locked) based on the hexadecimal <a href="https://en.wikipedia.org/wiki/MD5">MD5</a> hash of a passcode (your puzzle input) followed by a sequence of uppercase characters representing the <em>path you have taken so far</em> (<code>U</code> for up, <code>D</code> for down, <code>L</code> for left, and <code>R</code> for right).</p>
+<p>Only the first four characters of the hash are used; they represent, respectively, the doors <em>up, down, left, and right</em> from your current position. Any <code>b</code>, <code>c</code>, <code>d</code>, <code>e</code>, or <code>f</code> means that the corresponding door is <em>open</em>; any other character (any number or <code>a</code>) means that the corresponding door is <em>closed and locked</em>.</p>
+<p>To access the vault, all you need to do is reach the bottom-right room; reaching this room opens the vault and all doors in the maze.</p>
+<p>For example, suppose the passcode is <code>hijkl</code>. Initially, you have taken no steps, and so your path is empty: you simply find the MD5 hash of <code>hijkl</code> alone. The first four characters of this hash are <code>ced9</code>, which indicate that up is open (<code>c</code>), down is open (<code>e</code>), left is open (<code>d</code>), and right is closed and locked (<code>9</code>). Because you start in the top-left corner, there are no "up" or "left" doors to be open, so your only choice is <em>down</em>.</p>
+<p>Next, having gone only one step (down, or <code>D</code>), you find the hash of <code>hijkl<em>D</em></code>. This produces <code>f2bc</code>, which indicates that you can go back up, left (but that's a wall), or right. Going right means hashing <code>hijkl<em>DR</em></code> to get <code>5745</code> - all doors closed and locked. However, going <em>up</em> instead is worthwhile: even though it returns you to the room you started in, your path would then be <code>DU</code>, opening a <em>different set of doors</em>.</p>
+<p>After going <code>DU</code> (and then hashing <code>hijkl<em>DU</em></code> to get <code>528e</code>), only the right door is open; after going <code>DUR</code>, all doors lock. (Fortunately, your actual passcode is <span title="It took four days to rescue the engineer that tried this.">not <code>hijkl</code></span>).</p>
+<p>Passcodes actually used by Easter Bunny Vault Security do allow access to the vault if you know the right path.  For example:</p>
+<ul>
+<li>If your passcode were <code>ihgpwlah</code>, the shortest path would be <code>DDRRRD</code>.</li>
+<li>With <code>kglvqrro</code>, the shortest path would be <code>DDUDRLRRUDRD</code>.</li>
+<li>With <code>ulqzkmiv</code>, the shortest would be <code>DRURDRUDDLLDLUURRDULRLDUUDDDRR</code>.</li>
+</ul>
+<p>Given your vault's passcode, <em>what is the shortest path</em> (the actual path, not just the length) to reach the vault?</p>
+</article>
+<p>Your puzzle answer was <code>DRLRDDURDR</code>.</p><article class="day-desc"><h2>--- Part Two ---</h2><p>You're curious how robust this security solution really is, and so you decide to find longer and longer paths which still provide access to the vault. You remember that paths always end the first time they reach the bottom-right room (that is, they can never pass through it, only end in it).</p>
+<p>For example:</p>
+<ul>
+<li>If your passcode were <code>ihgpwlah</code>, the longest path would take <code>370</code> steps.</li>
+<li>With <code>kglvqrro</code>, the longest path would be <code>492</code> steps long.</li>
+<li>With <code>ulqzkmiv</code>, the longest path would be <code>830</code> steps long.</li>
+</ul>
+<p></p>
+<p>What is the <em>length of the longest path</em> that reaches the vault?</p>
+</article>
+<p>Your puzzle answer was <code>500</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">qljzarfv</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+%22Two+Steps+Forward%22+%2D+Day+17+%2D+Advent+of+Code+2016&amp;url=http%3A%2F%2Fadventofcode%2Ecom%2F2016%2Fday%2F17&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%2F17" target="_blank">Google+</a>
+  <a href="http://www.reddit.com/submit?url=http%3A%2F%2Fadventofcode%2Ecom%2F2016%2Fday%2F17&amp;title=I%27ve+completed+%22Two+Steps+Forward%22+%2D+Day+17+%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