Commit de640d46 authored by Neil Smith's avatar Neil Smith
Browse files

Now with use of monad loops

parent 4ecf3b3b
......@@ -56,7 +56,6 @@ executables:
source-dirs: src
dependencies:
- base >= 2 && < 6
- text
- vector
advent15slow:
......@@ -64,6 +63,12 @@ executables:
source-dirs: src
dependencies:
- base >= 2 && < 6
- text
- containers
advent15loop:
main: advent15loop.hs
source-dirs: src
dependencies:
- base >= 2 && < 6
- vector
- monad-loops
......@@ -7,6 +7,9 @@ import Data.STRef
import qualified Data.Vector.Unboxed.Mutable as V
type STInt s = STRef s Int
type VInt s = V.MVector s Int
main :: IO ()
main =
do let seed = [20, 0, 1, 11, 6, 3]
......@@ -18,24 +21,25 @@ main =
part1 seed = runGame seed 2020
part2 seed = runGame seed 30000000
zeroInt :: Int
zeroInt = 0
runGame :: [Int] -> Int -> Int
runGame seed roundsNeeded =
runST $
do (round, word, history) <- seedGame seed roundsNeeded
gameSteps roundsNeeded round word history
readSTRef word
seedGame :: [Int] -> Int -> ST s (STInt s, STInt s, VInt s)
seedGame seed historySize =
do round <- newSTRef $ length seed
word <- newSTRef $ last seed
history <- V.replicate historySize zeroInt
history <- V.replicate historySize 0
forM_ (zip (init seed) [1..]) $ \(t, s) -> V.write history t s
return (round, word, history)
runGame seed roundsNeeded =
runST $
do (round, word, history) <- seedGame seed roundsNeeded
gameStep roundsNeeded round word history
readSTRef word
gameStep :: Int -> STRef s Int -> STRef s Int -> V.MVector s Int -> ST s ()
gameStep targetRound round word history =
-- gameSteps :: Int -> STRef s Int -> STRef s Int -> V.MVector s Int -> ST s ()
gameSteps :: Int -> STInt s -> STInt s -> VInt s -> ST s ()
gameSteps targetRound round word history =
do roundVal <- readSTRef round
if roundVal == targetRound
then return ()
......@@ -46,7 +50,7 @@ gameStep targetRound round word history =
V.write history wordVal roundVal
modifySTRef round (+1)
writeSTRef word word'
gameStep targetRound round word history
gameSteps targetRound round word history
speakWord :: Int -> Int -> Int
......
-- import Debug.Trace
import Prelude hiding (round)
import Control.Monad
import Control.Monad.ST
import Control.Monad.Loops
import Data.STRef
import qualified Data.Vector.Unboxed.Mutable as V
main :: IO ()
main =
do let seed = [20, 0, 1, 11, 6, 3]
-- print seed
print $ part1 seed
print $ part2 seed
part1 seed = runGame seed 2020
part2 seed = runGame seed 30000000
runGame seed roundsNeeded =
runST $
do (round, word, history) <- seedGame seed roundsNeeded
gameLoop roundsNeeded round word history
readSTRef word
-- gameLoop targetRound round word history =
-- do ( gameStep round word history
-- `untilM_` (do r <- readSTRef round
-- return $ r == targetRound)
-- )
-- return ()
-- gameLoop targetRound round word history =
-- do untilM_ (gameStep round word history )
-- (do r <- readSTRef round
-- return $ r == targetRound )
-- return ()
-- gameLoop targetRound round word history =
-- do whileM_ (do r <- readSTRef round
-- return $ r /= targetRound )
-- (gameStep round word history )
-- return ()
gameLoop targetRound round word history =
do whileM_ (do r <- readSTRef round
return $ r /= targetRound )
$ gameStep round word history
return ()
seedGame seed historySize =
do round <- newSTRef $ length seed
word <- newSTRef $ last seed
history <- V.replicate historySize 0
forM_ (zip (init seed) [1..]) $ \(t, s) -> V.write history t s
return (round, word, history)
gameStep :: STRef s Int -> STRef s Int -> V.MVector s Int -> ST s ()
gameStep round word history =
do roundVal <- readSTRef round
wordVal <- readSTRef word
wordH <- V.read history wordVal
let word' = speakWord wordH roundVal
V.write history wordVal roundVal
modifySTRef round (+1)
writeSTRef word word'
return ()
speakWord :: Int -> Int -> Int
speakWord 0 _ = 0
speakWord prev now = now - prev
......@@ -3,7 +3,6 @@
import Prelude hiding (round)
import qualified Data.IntMap.Strict as M
data Game = Game { round :: Int
, word :: Int
, history :: M.IntMap Int
......
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="utf-8"/>
<title>Day 15 - Advent of Code 2020</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?25"/>
<link rel="stylesheet alternate" type="text/css" href="/static/highcontrast.css?0" title="High Contrast"/>
<link rel="shortcut icon" href="/favicon.png"/>
</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 a massive company, 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, social media), I
built the whole thing myself, including the design, animations, prose, and all
of the puzzles.
The puzzles are most of the work; preparing a new calendar and a new set of
puzzles each year takes all of my free time for 4-5 months. 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="/2020/about">[About]</a></li><li><a href="/2020/events">[Events]</a></li><li><a href="https://teespring.com/stores/advent-of-code" target="_blank">[Shop]</a></li><li><a href="/2020/settings">[Settings]</a></li><li><a href="/2020/auth/logout">[Log Out]</a></li></ul></nav><div class="user">Neil Smith <a href="/2020/support" class="supporter-badge" title="Advent of Code Supporter">(AoC++)</a> <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="/2020">2020</a><span class="title-event-wrap">;</span></h1><nav><ul><li><a href="/2020">[Calendar]</a></li><li><a href="/2020/support">[AoC++]</a></li><li><a href="/2020/sponsors">[Sponsors]</a></li><li><a href="/2020/leaderboard">[Leaderboard]</a></li><li><a href="/2020/stats">[Stats]</a></li></ul></nav></div></header>
<div id="sidebar">
<div id="sponsor"><div class="quiet">Our <a href="/2020/sponsors">sponsors</a> help make Advent of Code possible:</div><div class="sponsor"><a href="https://careers.bolt.eu/positions?team=engineering&amp;utm_source=adventofcode&amp;utm_medium=banner&amp;utm_campaign=adventofcode_traffic" target="_blank" onclick="if(ga)ga('send','event','sponsor','sidebar',this.href);" rel="noopener">Bolt</a> - Fastest growing mobility startup in Europe: distributed systems, microservices, ML, complex algorithms for demand prediction, and much more!</div></div>
</div><!--/sidebar-->
<main>
<script>window.addEventListener('click', function(e,s,r){if(e.target.nodeName==='CODE'&&e.detail===3){s=window.getSelection();s.removeAllRanges();r=document.createRange();r.selectNodeContents(e.target);s.addRange(r);}});</script>
<article class="day-desc"><h2>--- Day 15: Rambunctious Recitation ---</h2><p>You catch the airport shuttle and try to book a new flight to your vacation island. Due to the storm, all direct flights have been cancelled, but a route is available to get around the storm. You take it.</p>
<p>While you wait for your flight, you decide to check in with the Elves back at the North Pole. They're playing a <em>memory game</em> and are <span title="Of course they are.">ever so excited</span> to explain the rules!</p>
<p>In this game, the players take turns saying <em>numbers</em>. They begin by taking turns reading from a list of <em>starting numbers</em> (your puzzle input). Then, each turn consists of considering the <em>most recently spoken number</em>:</p>
<ul>
<li>If that was the <em>first</em> time the number has been spoken, the current player says <em><code>0</code></em>.</li>
<li>Otherwise, the number had been spoken before; the current player announces <em>how many turns apart</em> the number is from when it was previously spoken.</li>
</ul>
<p>So, after the starting numbers, each turn results in that player speaking aloud either <em><code>0</code></em> (if the last number is new) or an <em>age</em> (if the last number is a repeat).</p>
<p>For example, suppose the starting numbers are <code>0,3,6</code>:</p>
<ul>
<li><em>Turn 1</em>: The <code>1</code>st number spoken is a starting number, <em><code>0</code></em>.</li>
<li><em>Turn 2</em>: The <code>2</code>nd number spoken is a starting number, <em><code>3</code></em>.</li>
<li><em>Turn 3</em>: The <code>3</code>rd number spoken is a starting number, <em><code>6</code></em>.</li>
<li><em>Turn 4</em>: Now, consider the last number spoken, <code>6</code>. Since that was the first time the number had been spoken, the <code>4</code>th number spoken is <em><code>0</code></em>.</li>
<li><em>Turn 5</em>: Next, again consider the last number spoken, <code>0</code>. Since it <em>had</em> been spoken before, the next number to speak is the difference between the turn number when it was last spoken (the previous turn, <code>4</code>) and the turn number of the time it was most recently spoken before then (turn <code>1</code>). Thus, the <code>5</code>th number spoken is <code>4 - 1</code>, <em><code>3</code></em>.</li>
<li><em>Turn 6</em>: The last number spoken, <code>3</code> had also been spoken before, most recently on turns <code>5</code> and <code>2</code>. So, the <code>6</code>th number spoken is <code>5 - 2</code>, <em><code>3</code></em>.</li>
<li><em>Turn 7</em>: Since <code>3</code> was just spoken twice in a row, and the last two turns are <code>1</code> turn apart, the <code>7</code>th number spoken is <em><code>1</code></em>.</li>
<li><em>Turn 8</em>: Since <code>1</code> is new, the <code>8</code>th number spoken is <em><code>0</code></em>.</li>
<li><em>Turn 9</em>: <code>0</code> was last spoken on turns <code>8</code> and <code>4</code>, so the <code>9</code>th number spoken is the difference between them, <em><code>4</code></em>.</li>
<li><em>Turn 10</em>: <code>4</code> is new, so the <code>10</code>th number spoken is <em><code>0</code></em>.</li>
</ul>
<p>(The game ends when the Elves get sick of playing or dinner is ready, whichever comes first.)</p>
<p>Their question for you is: what will be the <em><code>2020</code>th</em> number spoken? In the example above, the <code>2020</code>th number spoken will be <code>436</code>.</p>
<p>Here are a few more examples:</p>
<ul>
<li>Given the starting numbers <code>1,3,2</code>, the <code>2020</code>th number spoken is <code>1</code>.</li>
<li>Given the starting numbers <code>2,1,3</code>, the <code>2020</code>th number spoken is <code>10</code>.</li>
<li>Given the starting numbers <code>1,2,3</code>, the <code>2020</code>th number spoken is <code>27</code>.</li>
<li>Given the starting numbers <code>2,3,1</code>, the <code>2020</code>th number spoken is <code>78</code>.</li>
<li>Given the starting numbers <code>3,2,1</code>, the <code>2020</code>th number spoken is <code>438</code>.</li>
<li>Given the starting numbers <code>3,1,2</code>, the <code>2020</code>th number spoken is <code>1836</code>.</li>
</ul>
<p>Given your starting numbers, <em>what will be the <code>2020</code>th number spoken?</em></p>
</article>
<p>Your puzzle answer was <code>421</code>.</p><article class="day-desc"><h2 id="part2">--- Part Two ---</h2><p>Impressed, the Elves issue you a challenge: determine the <code>30000000</code>th number spoken. For example, given the same starting numbers as above:</p>
<ul>
<li>Given <code>0,3,6</code>, the <code>30000000</code>th number spoken is <code>175594</code>.</li>
<li>Given <code>1,3,2</code>, the <code>30000000</code>th number spoken is <code>2578</code>.</li>
<li>Given <code>2,1,3</code>, the <code>30000000</code>th number spoken is <code>3544142</code>.</li>
<li>Given <code>1,2,3</code>, the <code>30000000</code>th number spoken is <code>261214</code>.</li>
<li>Given <code>2,3,1</code>, the <code>30000000</code>th number spoken is <code>6895259</code>.</li>
<li>Given <code>3,2,1</code>, the <code>30000000</code>th number spoken is <code>18</code>.</li>
<li>Given <code>3,1,2</code>, the <code>30000000</code>th number spoken is <code>362</code>.</li>
</ul>
<p>Given your starting numbers, <em>what will be the <code>30000000</code>th number spoken?</em></p>
</article>
<p>Your puzzle answer was <code>436</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="/2020">return to your Advent calendar</a> and try another puzzle.</p>
<p>Your puzzle input was <code class="puzzle-input">20,0,1,11,6,3</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+%22Rambunctious+Recitation%22+%2D+Day+15+%2D+Advent+of+Code+2020&amp;url=https%3A%2F%2Fadventofcode%2Ecom%2F2020%2Fday%2F15&amp;related=ericwastl&amp;hashtags=AdventOfCode" target="_blank">Twitter</a>
<a href="javascript:void(0);" onclick="var mastodon_instance=prompt('Mastodon Instance / Server Name?'); if(typeof mastodon_instance==='string' && mastodon_instance.length){this.href='https://'+mastodon_instance+'/share?text=I%27ve+completed+%22Rambunctious+Recitation%22+%2D+Day+15+%2D+Advent+of+Code+2020+%23AdventOfCode+https%3A%2F%2Fadventofcode%2Ecom%2F2020%2Fday%2F15'}else{return false;}" target="_blank">Mastodon</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('set', 'anonymizeIp', true);
ga('send', 'pageview');
</script>
<!-- /ga -->
</body>
</html>
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment