Day 15
authorNeil Smith <neil.git@njae.me.uk>
Fri, 15 Dec 2017 08:58:13 +0000 (08:58 +0000)
committerNeil Smith <neil.git@njae.me.uk>
Fri, 15 Dec 2017 08:58:13 +0000 (08:58 +0000)
advent-of-code.cabal
problems/day15.html [new file with mode: 0644]
src/advent14/advent14.hs
src/advent15/advent15.hs [new file with mode: 0644]
src/advent15/advent15.ipynb [new file with mode: 0644]

index e133aae9550c5453b16cb4e855695bbeae1af161..4bd4b0d8f18addd54c3c531743093599cf29618f 100644 (file)
@@ -143,3 +143,8 @@ executable advent14serial
                      , split
                      , containers
 
+executable advent15
+  hs-source-dirs:      src/advent15
+  main-is:             advent15.hs
+  default-language:    Haskell2010
+  build-depends:       base >= 4.7 && < 5
diff --git a/problems/day15.html b/problems/day15.html
new file mode 100644 (file)
index 0000000..2e3ba68
--- /dev/null
@@ -0,0 +1,203 @@
+<!DOCTYPE html>
+<html lang="en-us">
+<head>
+<meta charset="utf-8"/>
+<title>Day 15 - Advent of Code 2017</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?12"/>
+<link rel="stylesheet alternate" type="text/css" href="/static/highcontrast.css?0" title="High Contrast"/>
+<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 took an hour or two
+each, but the harder ones took 4-5 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="/2017/about">[About]</a></li><li><a href="/2017/support">[AoC++]</a></li><li><a href="/2017/events">[Events]</a></li><li><a href="/2017/settings">[Settings]</a></li><li><a href="/2017/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">0xffff&amp;</span><a href="/2017">2017</a><span class="title-event-wrap"></span></h1><nav><ul><li><a href="/2017">[Calendar]</a></li><li><a href="/2017/leaderboard">[Leaderboard]</a></li><li><a href="/2017/stats">[Stats]</a></li><li><a href="/2017/sponsors">[Sponsors]</a></li></ul></nav></div></header>
+
+<div id="sidebar">
+<div id="sponsor"><div class="quiet">Our <a href="/2017/sponsors">sponsors</a> help make Advent of Code possible:</div><p><a href="https://formlabs.com/" target="_blank" onclick="if(ga)ga('send','event','sponsor','click',this.href);" rel="noopener">Formlabs</a> - We make powerful, affordable 3D printers for professionals.</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: Dueling Generators ---</h2><p>Here, you encounter a pair of dueling <span title="I guess they *are* a little banjo-shaped. Why do you ask?">generators</span>. The generators, called <em>generator A</em> and <em>generator B</em>, are trying to agree on a sequence of numbers. However, one of them is malfunctioning, and so the sequences don't always match.</p>
+<p>As they do this, a <em>judge</em> waits for each of them to generate its next value, compares the lowest 16 bits of both values, and keeps track of the number of times those parts of the values match.</p>
+<p>The generators both work on the same principle. To create its next value, a generator will take the previous value it produced, multiply it by a <em>factor</em> (generator A uses <code>16807</code>; generator B uses <code>48271</code>), and then keep the remainder of dividing that resulting product by <code>2147483647</code>. That final remainder is the value it produces next.</p>
+<p>To calculate each generator's first value, it instead uses a specific starting value as its "previous value" (as listed in your puzzle input).</p>
+<p>For example, suppose that for starting values, generator A uses <code>65</code>, while generator B uses <code>8921</code>. Then, the first five pairs of generated values are:</p>
+<pre><code>--Gen. A--  --Gen. B--
+   1092455   430625591
+1181022009  1233683848
+ 245556042  1431495498
+1744312007   137874439
+1352636452   285222916
+</code></pre>
+<p>In binary, these pairs are (with generator A's value first in each pair):</p>
+<pre><code>00000000000100001010101101100111
+00011001101010101101001100110111
+
+01000110011001001111011100111001
+01001001100010001000010110001000
+
+00001110101000101110001101001010
+01010101010100101110001101001010
+
+01100111111110000001011011000111
+00001000001101111100110000000111
+
+01010000100111111001100000100100
+00010001000000000010100000000100
+</code></pre>
+<p>Here, you can see that the lowest (here, rightmost) 16 bits of the third value match: <code>1110001101001010</code>. Because of this one match, after processing these five pairs, the judge would have added only <code>1</code> to its total.</p>
+<p>To get a significant sample, the judge would like to consider <em>40 million</em> pairs. (In the example above, the judge would eventually find a total of <code>588</code> pairs that match in their lowest 16 bits.)</p>
+<p>After 40 million pairs, <em>what is the judge's final count</em>?</p>
+</article>
+<p>Your puzzle answer was <code>631</code>.</p><article class="day-desc"><h2>--- Part Two ---</h2><p>In the interest of trying to align a little better, the generators get more picky about the numbers they actually give to the judge.</p>
+<p>They still generate values in the same way, but now they only hand a value to the judge when it meets their <em>criteria</em>:</p>
+<ul>
+<li>Generator A looks for values that are multiples of <code><em>4</em></code>.</li>
+<li>Generator B looks for values that are multiples of <code><em>8</em></code>.</li>
+</ul>
+<p>Each generator functions completely <em>independently</em>: they both go through values entirely on their own, only occasionally handing an acceptable value to the judge, and otherwise working through the same sequence of values as before until they find one.</p>
+<p>The judge still waits for each generator to provide it with a value before comparing them (using the same comparison method as before). It keeps track of the order it receives values; the first values from each generator are compared, then the second values from each generator, then the third values, and so on.</p>
+<p>Using the example starting values given above, the generators now produce the following first five values each:</p>
+<pre><code>--Gen. A--  --Gen. B--
+1352636452  1233683848
+1992081072   862516352
+ 530830436  1159784568
+1980017072  1616057672
+ 740335192   412269392
+</code></pre>
+<p>These values have the following corresponding binary values:</p>
+<pre><code>01010000100111111001100000100100
+01001001100010001000010110001000
+
+01110110101111001011111010110000
+00110011011010001111010010000000
+
+00011111101000111101010001100100
+01000101001000001110100001111000
+
+01110110000001001010100110110000
+01100000010100110001010101001000
+
+00101100001000001001111001011000
+00011000100100101011101101010000
+</code></pre>
+<p>Unfortunately, even though this change makes more bits similar on average, none of these values' lowest 16 bits match. Now, it's not until the 1056th pair that the judge finds the first match:</p>
+<pre><code>--Gen. A--  --Gen. B--
+1023762912   896885216
+
+00111101000001010110000111100000
+00110101011101010110000111100000
+</code></pre>
+<p>This change makes the generators much slower, and the judge is getting impatient; it is now only willing to consider <em>5 million</em> pairs. (Using the values from the example above, after five million pairs, the judge would eventually find a total of <code>309</code> pairs that match in their lowest 16 bits.)</p>
+<p>After 5 million pairs, but using this new generator logic, <em>what is the judge's final count</em>?</p>
+</article>
+<p>Your puzzle answer was <code>279</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="/2017">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+%22Dueling+Generators%22+%2D+Day+15+%2D+Advent+of+Code+2017&amp;url=http%3A%2F%2Fadventofcode%2Ecom%2F2017%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%2F2017%2Fday%2F15" target="_blank">Google+</a>
+  <a href="http://www.reddit.com/submit?url=http%3A%2F%2Fadventofcode%2Ecom%2F2017%2Fday%2F15&amp;title=I%27ve+completed+%22Dueling+Generators%22+%2D+Day+15+%2D+Advent+of+Code+2017" 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
index 8c492530d19eb53222c7dbb6baecbf59e5df70ea..698853c7bcd2c60b0a891598e0ee9b0bbcc9f41f 100644 (file)
@@ -2,12 +2,10 @@ import Data.List.Split (chunksOf)
 import Data.Char (ord)
 import Text.Printf (printf)
 import Data.Bits (xor)
--- import qualified Data.Map.Strict as M
 import qualified Data.Set as S
 import qualified Data.Graph as G
 import Control.Parallel.Strategies (parMap, rpar)
 
-
 type CellSet = S.Set (Int, Int)
 
 puzzleKey = "xlqgujun"
diff --git a/src/advent15/advent15.hs b/src/advent15/advent15.hs
new file mode 100644 (file)
index 0000000..7cec0d0
--- /dev/null
@@ -0,0 +1,37 @@
+import Data.Word
+import Data.Bits
+
+generatorAStart = 873
+generatorBStart = 583
+
+main :: IO ()
+main = do
+    print $ part1 
+    print $ part2 
+
+part1 = length $ filter (uncurry (==)) $ take 40000000 $ zip streamA streamB
+
+
+part2 = length $ filter (uncurry (==)) $ take 5000000 $ zip fsA fsB
+    where fsA = filteredStream 3 streamA
+          fsB = filteredStream 7 streamB
+
+
+generatorA = generator 2147483647 16807
+generatorB = generator 2147483647 48271
+
+streamA = stream generatorA generatorAStart
+streamB = stream generatorB generatorBStart
+
+generator :: Word64 -> Word64 -> Word64 -> Word64
+generator divisor factor n = fromIntegral $ fromIntegral n * factor `rem` divisor
+
+toWord16 :: Word64 -> Word16
+toWord16 = fromIntegral
+
+stream :: (Word64 -> Word64) -> Word64 -> [Word16]
+stream gen n0 = map toWord16 $ drop 1 $ iterate gen n0
+
+filteredStream :: Word16 -> [Word16] -> [Word16]
+filteredStream f str = filter (\n -> n .&. f == 0) str
+
diff --git a/src/advent15/advent15.ipynb b/src/advent15/advent15.ipynb
new file mode 100644 (file)
index 0000000..d89f1da
--- /dev/null
@@ -0,0 +1,462 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import Data.Word\n",
+    "import Data.Bits"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "a :: Word8\n",
+    "a=156"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "b :: Word16\n",
+    "b = 202"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "<style>/* Styles used for the Hoogle display in the pager */\n",
+       ".hoogle-doc {\n",
+       "display: block;\n",
+       "padding-bottom: 1.3em;\n",
+       "padding-left: 0.4em;\n",
+       "}\n",
+       ".hoogle-code {\n",
+       "display: block;\n",
+       "font-family: monospace;\n",
+       "white-space: pre;\n",
+       "}\n",
+       ".hoogle-text {\n",
+       "display: block;\n",
+       "}\n",
+       ".hoogle-name {\n",
+       "color: green;\n",
+       "font-weight: bold;\n",
+       "}\n",
+       ".hoogle-head {\n",
+       "font-weight: bold;\n",
+       "}\n",
+       ".hoogle-sub {\n",
+       "display: block;\n",
+       "margin-left: 0.4em;\n",
+       "}\n",
+       ".hoogle-package {\n",
+       "font-weight: bold;\n",
+       "font-style: italic;\n",
+       "}\n",
+       ".hoogle-module {\n",
+       "font-weight: bold;\n",
+       "}\n",
+       ".hoogle-class {\n",
+       "font-weight: bold;\n",
+       "}\n",
+       ".get-type {\n",
+       "color: green;\n",
+       "font-weight: bold;\n",
+       "font-family: monospace;\n",
+       "display: block;\n",
+       "white-space: pre-wrap;\n",
+       "}\n",
+       ".show-type {\n",
+       "color: green;\n",
+       "font-weight: bold;\n",
+       "font-family: monospace;\n",
+       "margin-left: 1em;\n",
+       "}\n",
+       ".mono {\n",
+       "font-family: monospace;\n",
+       "display: block;\n",
+       "}\n",
+       ".err-msg {\n",
+       "color: red;\n",
+       "font-style: italic;\n",
+       "font-family: monospace;\n",
+       "white-space: pre;\n",
+       "display: block;\n",
+       "}\n",
+       "#unshowable {\n",
+       "color: red;\n",
+       "font-weight: bold;\n",
+       "}\n",
+       ".err-msg.in.collapse {\n",
+       "padding-top: 0.7em;\n",
+       "}\n",
+       ".highlight-code {\n",
+       "white-space: pre;\n",
+       "font-family: monospace;\n",
+       "}\n",
+       ".suggestion-warning { \n",
+       "font-weight: bold;\n",
+       "color: rgb(200, 130, 0);\n",
+       "}\n",
+       ".suggestion-error { \n",
+       "font-weight: bold;\n",
+       "color: red;\n",
+       "}\n",
+       ".suggestion-name {\n",
+       "font-weight: bold;\n",
+       "}\n",
+       "</style><div class=\"suggestion-name\" style=\"clear:both;\">Redundant bracket</div><div class=\"suggestion-row\" style=\"float: left;\"><div class=\"suggestion-warning\">Found:</div><div class=\"highlight-code\" id=\"haskell\">(fromIntegral a) * b</div></div><div class=\"suggestion-row\" style=\"float: left;\"><div class=\"suggestion-warning\">Why Not:</div><div class=\"highlight-code\" id=\"haskell\">fromIntegral a * b</div></div>"
+      ],
+      "text/plain": [
+       "Line 1: Redundant bracket\n",
+       "Found:\n",
+       "(fromIntegral a) * b\n",
+       "Why not:\n",
+       "fromIntegral a * b"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/plain": [
+       "31512"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "(fromIntegral a) * b"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "24"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "(156 * 202) `mod` 256"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Generator A starts with 873\n",
+    "\n",
+    "Generator B starts with 583"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "generator :: Word64 -> Word64 -> Word64 -> Word64\n",
+    "generator divisor factor n = fromIntegral $ fromIntegral n * factor `rem` divisor"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "generatorA = generator 2147483647 16807\n",
+    "generatorB = generator 2147483647 48271"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 8,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "toWord16 :: Word64 -> Word16\n",
+    "toWord16 = fromIntegral"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 9,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[43879,63289,58186,5831,38948]"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "map toWord16 $ take 5 $ drop 1 $ iterate generatorA 65"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 10,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[54071,34184,58186,52231,10244]"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "map toWord16 $ take 5 $ drop 1 $ iterate generatorB 8921"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 11,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "stream :: (Word64 -> Word64) -> Word64 -> [Word16]\n",
+    "stream gen n0 = map toWord16 $ drop 1 $ iterate gen n0"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 12,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "588"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "length $ filter (uncurry (==)) $ take 40000000 $ zip (stream generatorA 65) (stream generatorB 8921)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 13,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "631"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "length $ filter (uncurry (==)) $ take 40000000 $ zip (stream generatorA 873) (stream generatorB 583)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 14,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "filteredStream :: Word16 -> [Word16] -> [Word16]\n",
+    "filteredStream f stream = filter (\\n -> n .&. f == 0) stream"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 15,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[38948,48816,54372,43440,40536]"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "take 5 $ filteredStream 3 $ stream generatorA 65"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 16,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "38948"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "toWord16 1352636452"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 17,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[1352636452,1992081072,530830436,1980017072,740335192]"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "take 5 $ filter (\\n -> n .&. 3 == 0) $ iterate generatorA 65"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 29,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[1233683848,862516352,1159784568,1616057672,412269392]"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "take 5 $ filter (\\n -> n .&. 7 == 0) $ iterate generatorB 8921"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 34,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "solE = length $ filter (uncurry (==)) $ take 5000000 $ zip fsA fsB\n",
+    "    where fsA = filteredStream 3 $ stream generatorA 65\n",
+    "          fsB = filteredStream 7 $ stream generatorB 8921"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 35,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "309"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "solE"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 32,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "sol = length $ filter (uncurry (==)) $ take 5000000 $ zip fsA fsB\n",
+    "    where fsA = filteredStream 3 $ stream generatorA 873\n",
+    "          fsB = filteredStream 7 $ stream generatorB 583"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 33,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "279"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "sol"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Haskell",
+   "language": "haskell",
+   "name": "haskell"
+  },
+  "language_info": {
+   "codemirror_mode": "ihaskell",
+   "file_extension": ".hs",
+   "name": "haskell",
+   "version": "8.0.2"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}