Day 15
authorNeil Smith <neil.git@njae.me.uk>
Thu, 15 Dec 2016 11:03:43 +0000 (11:03 +0000)
committerNeil Smith <neil.git@njae.me.uk>
Thu, 15 Dec 2016 11:03:43 +0000 (11:03 +0000)
README.md
advent15.hs [new file with mode: 0644]
advent15.test.txt [new file with mode: 0644]
advent15.txt [new file with mode: 0644]
advent15f.hs [new file with mode: 0644]
day15.html [new file with mode: 0644]

index 5663158d2c8e117d5d580f44233e16e1c86243ec..2e4886ca28d1928ef768353217ce845fb803e444 100644 (file)
--- a/README.md
+++ b/README.md
@@ -33,7 +33,7 @@ advent01
 
 If you're profiling, compile and run with 
 ```
-ghc -O2 --make advent01.hs -prof -auto-all -caf-all -fforce-recomp
+ghc -O2 --make advent01.hs -prof -auto-all -caf-all -fforce-recomp -rstopts
 time ./advent01 +RTS -p -hy
 ```
 
@@ -44,4 +44,4 @@ Build this readme file wth
 pandoc -s README.md > README.html
 ```
 
-(Using the [Modest styles](https://github.com/markdowncss/modest).)
\ No newline at end of file
+(Using the [Modest style](https://github.com/markdowncss/modest).)
\ No newline at end of file
diff --git a/advent15.hs b/advent15.hs
new file mode 100644 (file)
index 0000000..e3c97fb
--- /dev/null
@@ -0,0 +1,37 @@
+import Text.Parsec 
+import Text.ParserCombinators.Parsec.Number
+
+main :: IO ()
+main = do 
+    text <- readFile "advent15.txt" 
+    let disks = successfulParse $ parseIfile text
+    part1 disks
+    part2 disks
+
+part1 :: [[Int]] -> IO ()
+part1 disks = print $ head $ filter (canFall disks) [0..]
+
+part2 :: [[Int]] -> IO ()
+part2 disks = print $ head $ filter (canFall disks2) [0..5000000]
+    where disks2 = id $! map (take 5000000) $ disks ++ [drop 7 $ drop 0 $ cycle [0..(11-1)]]
+
+canFall :: [[Int]] -> Int -> Bool
+canFall ds i = all (\d -> (d!!i) == 0) ds
+
+
+instructionFile = instructionLine `endBy` newline 
+instructionLine = diskify <$> (string "Disc #" *> int) 
+                          <*> (string " has " *> int)
+                          <*> (string " positions; at time=0, it is at position " *> int)
+                          <*  (string ".")
+                    where diskify n size pos0 = drop n $ drop pos0 $ cycle [0..(size-1)]
+
+parseIfile :: String -> Either ParseError [[Int]]
+parseIfile input = parse instructionFile "(unknown)" input
+
+parseIline :: String -> Either ParseError [Int]
+parseIline input = parse instructionLine "(unknown)" input
+
+successfulParse :: Either ParseError [a] -> [a]
+successfulParse (Left _) = []
+successfulParse (Right a) = a
diff --git a/advent15.test.txt b/advent15.test.txt
new file mode 100644 (file)
index 0000000..3683605
--- /dev/null
@@ -0,0 +1,3 @@
+Disc #1 has 5 positions; at time=0, it is at position 4.
+Disc #2 has 2 positions; at time=0, it is at position 1.
+
diff --git a/advent15.txt b/advent15.txt
new file mode 100644 (file)
index 0000000..d2463d1
--- /dev/null
@@ -0,0 +1,6 @@
+Disc #1 has 5 positions; at time=0, it is at position 2.
+Disc #2 has 13 positions; at time=0, it is at position 7.
+Disc #3 has 17 positions; at time=0, it is at position 10.
+Disc #4 has 3 positions; at time=0, it is at position 2.
+Disc #5 has 19 positions; at time=0, it is at position 9.
+Disc #6 has 7 positions; at time=0, it is at position 0.
diff --git a/advent15f.hs b/advent15f.hs
new file mode 100644 (file)
index 0000000..31866c0
--- /dev/null
@@ -0,0 +1,42 @@
+import Text.Parsec 
+import Text.ParserCombinators.Parsec.Number
+
+type Disk = (Int -> Bool)
+
+main :: IO ()
+main = do 
+    text <- readFile "advent15.txt" 
+    let disks = successfulParse $ parseIfile text
+    part1 disks
+    part2 disks
+
+part1 :: [Disk] -> IO ()
+part1 disks = print $ head $ filter (canFall disks) [0..]
+
+part2 :: [Disk] -> IO ()
+part2 disks = print $ head $ filter (canFall disks2) [0..]
+    -- where disks2 = disks ++ [(\i -> (11 + 7 + 0 + i) `mod` 11 == 0)]
+    where disks2 = disks ++ [diskify 7 11 0]
+
+canFall :: [Disk] -> Int -> Bool
+canFall ds i = all (\d -> (d i)) ds
+
+
+instructionFile = instructionLine `endBy` newline 
+instructionLine = diskify <$> (string "Disc #" *> int) 
+                          <*> (string " has " *> int)
+                          <*> (string " positions; at time=0, it is at position " *> int)
+                          <*  (string ".")
+
+diskify :: Int -> Int -> Int -> (Int -> Bool)
+diskify n size pos0 = (\i -> (size + n + pos0 + i) `mod` size == 0)
+
+parseIfile :: String -> Either ParseError [Disk]
+parseIfile input = parse instructionFile "(unknown)" input
+
+parseIline :: String -> Either ParseError Disk
+parseIline input = parse instructionLine "(unknown)" input
+
+successfulParse :: Either ParseError [a] -> [a]
+successfulParse (Left _) = []
+successfulParse (Right a) = a
diff --git a/day15.html b/day15.html
new file mode 100644 (file)
index 0000000..17dc477
--- /dev/null
@@ -0,0 +1,146 @@
+<!DOCTYPE html>
+<html lang="en-us">
+<head>
+<meta charset="utf-8"/>
+<title>Day 15 - 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">30*</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 15: Timing is Everything ---</h2><p>The halls open into an interior plaza containing a large kinetic sculpture. The sculpture is in a sealed enclosure and seems to involve a set of identical spherical capsules that are carried to the top and allowed to <a href="https://youtu.be/IxDoO9oODOk?t=177">bounce through the maze</a> of spinning pieces.</p>
+<p>Part of the sculpture is even interactive! When a button is pressed, a capsule is dropped and tries to fall through slots in a set of rotating discs to finally go through a little hole at the bottom and come out of the sculpture. If any of the slots aren't aligned with the capsule as it passes, the capsule bounces off the disc and soars away. You feel compelled to <span title="These machines are everywhere in Japan, but on a MUCH smaller scale.">get one of those capsules</span>.</p>
+<p>The discs pause their motion each second and come in different sizes; they seem to each have a fixed number of positions at which they stop.  You decide to call the position with the slot <code>0</code>, and count up for each position it reaches next.</p>
+<p>Furthermore, the discs are spaced out so that after you push the button, one second elapses before the first disc is reached, and one second elapses as the capsule passes from one disk to the one below it.  So, if you push the button at <code>time=100</code>, then the capsule reaches the top disc at <code>time=101</code>, the second disc at <code>time=102</code>, the third disc at <code>time=103</code>, and so on.</p>
+<p>The button will only drop a capsule at an integer time - no fractional seconds allowed.</p>
+<p>For example, at <code>time=0</code>, suppose you see the following arrangement:</p>
+<pre><code>Disc #1 has 5 positions; at time=0, it is at position 4.
+Disc #2 has 2 positions; at time=0, it is at position 1.
+</code></pre>
+<p>If you press the button exactly at <code>time=0</code>, the capsule would start to fall; it would reach the first disc at <code>time=1</code>. Since the first disc was at position <code>4</code> at <code>time=0</code>, by <code>time=1</code> it has ticked one position forward.  As a five-position disc, the next position is <code>0</code>, and the capsule falls through the slot.</p>
+<p>Then, at <code>time=2</code>, the capsule reaches the second disc. The second disc has ticked forward two positions at this point: it started at position <code>1</code>, then continued to position <code>0</code>, and finally ended up at position <code>1</code> again.  Because there's only a slot at position <code>0</code>, the capsule bounces away.</p>
+<p>If, however, you wait until <code>time=5</code> to push the button, then when the capsule reaches each disc, the first disc will have ticked forward <code>5+1 = 6</code> times (to position <code>0</code>), and the second disc will have ticked forward <code>5+2 = 7</code> times (also to position <code>0</code>). In this case, the capsule would fall through the discs and come out of the machine.</p>
+<p>However, your situation has more than two discs; you've noted their positions in your puzzle input. What is the <em>first time you can press the button</em> to get a capsule?</p>
+</article>
+<p>Your puzzle answer was <code>148737</code>.</p><article class="day-desc"><h2>--- Part Two ---</h2><p>After getting the first capsule (it contained a star! what great fortune!), the machine detects your success and begins to rearrange itself.</p>
+<p>When it's done, the discs are back in their original configuration as if it were <code>time=0</code> again, but a new disc with <code>11</code> positions and starting at position <code>0</code> has appeared exactly one second below the previously-bottom disc.</p>
+<p>With this new disc, and counting again starting from <code>time=0</code> with the configuration in your puzzle input, what is the <em>first time you can press the button</em> to get another capsule?</p>
+</article>
+<p>Your puzzle answer was <code>2353212</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="15/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+%22Timing+is+Everything%22+%2D+Day+15+%2D+Advent+of+Code+2016&amp;url=http%3A%2F%2Fadventofcode%2Ecom%2F2016%2Fday%2F15&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%2F15" target="_blank">Google+</a>
+  <a href="http://www.reddit.com/submit?url=http%3A%2F%2Fadventofcode%2Ecom%2F2016%2Fday%2F15&amp;title=I%27ve+completed+%22Timing+is+Everything%22+%2D+Day+15+%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