Done day 22
authorNeil Smith <neil.git@njae.me.uk>
Thu, 9 Jan 2020 11:20:50 +0000 (11:20 +0000)
committerNeil Smith <neil.git@njae.me.uk>
Thu, 9 Jan 2020 11:20:50 +0000 (11:20 +0000)
advent22/package.yaml [new file with mode: 0644]
advent22/src/advent22.hs [new file with mode: 0644]
data/advent22.txt [new file with mode: 0644]
data/advent22c.txt [new file with mode: 0644]
problems/day22.html [new file with mode: 0644]
stack.yaml

diff --git a/advent22/package.yaml b/advent22/package.yaml
new file mode 100644 (file)
index 0000000..e56e7ad
--- /dev/null
@@ -0,0 +1,61 @@
+# This YAML file describes your package. Stack will automatically generate a
+# Cabal file when you run `stack build`. See the hpack website for help with
+# this file: <https://github.com/sol/hpack>.
+
+name: advent22
+synopsis: Advent of Code
+version: '0.0.1'
+
+default-extensions:
+- AllowAmbiguousTypes
+- ApplicativeDo
+- BangPatterns
+- BlockArguments
+- DataKinds
+- DeriveFoldable
+- DeriveFunctor
+- DeriveGeneric
+- DeriveTraversable
+- EmptyCase
+- FlexibleContexts
+- FlexibleInstances
+- FunctionalDependencies
+- GADTs
+- GeneralizedNewtypeDeriving
+- ImplicitParams
+- KindSignatures
+- LambdaCase
+- MonadComprehensions
+- MonoLocalBinds
+- MultiParamTypeClasses
+- MultiWayIf
+- NegativeLiterals
+- NumDecimals
+# - OverloadedLists
+- OverloadedStrings
+- PartialTypeSignatures
+- PatternGuards
+- PatternSynonyms
+- PolyKinds
+- RankNTypes
+- RecordWildCards
+- ScopedTypeVariables
+- TemplateHaskell
+- TransformListComp
+- TupleSections
+- TypeApplications
+- TypeInType
+- TypeOperators
+- ViewPatterns
+
+
+executables:
+  advent22:
+    main: advent22.hs
+    source-dirs: src
+    dependencies:
+    - base >= 2 && < 6
+    - text
+    - megaparsec
+    - finite-typelits
+    - groups
diff --git a/advent22/src/advent22.hs b/advent22/src/advent22.hs
new file mode 100644 (file)
index 0000000..d0d616a
--- /dev/null
@@ -0,0 +1,104 @@
+-- import Debug.Trace
+
+import Data.Text (Text)
+import qualified Data.Text.IO as TIO
+
+import Data.Void (Void)
+
+import Text.Megaparsec hiding (State)
+import Text.Megaparsec.Char
+import qualified Text.Megaparsec.Char.Lexer as L
+import qualified Control.Applicative as CA
+
+
+import Data.Finite (Finite, modulo, getFinite)
+import Data.Group (Group(..), pow)
+import GHC.TypeNats (KnownNat)
+
+import Data.Foldable (fold)
+
+
+data ShuffleOp = Cut Integer
+               | Increment Integer
+               | Stack 
+               deriving (Eq, Ord, Show)
+
+type Shuffle = [ShuffleOp]
+
+data Affine n = Affine { affA :: !(Finite n)
+                       , affB :: !(Finite n)
+                       } deriving (Eq, Ord, Show)
+
+
+instance KnownNat n => Semigroup (Affine n) where
+    Affine a2 b2 <> Affine a1 b1 = Affine (a2 * a1) (a2 * b1 + b2)
+
+instance KnownNat n => Monoid (Affine n) where
+    mempty = Affine 1 0
+
+instance KnownNat n => Group (Affine n) where
+    invert (Affine a b) = Affine a' b'
+        where
+        a' = a ^ (maxBound @(Finite n) - 1)
+        b' = negate (a' * b)
+
+
+main :: IO ()
+main = do 
+        text <- TIO.readFile "data/advent22.txt"
+        let shuffle = successfulParse text 
+        print $ part1 shuffle
+        print $ part2 shuffle
+
+
+part1 shuffle = getFinite $ trans @$ 2019
+    where trans = mergeOps $ map affOfOp shuffle :: Affine 10007
+
+part2 shuffle = getFinite $ invert bigTrans @$ 2020
+    where trans = mergeOps $ map affOfOp shuffle :: Affine 119315717514047
+          bigTrans = trans `pow` 101741582076661
+
+
+
+affOfOp :: KnownNat n => ShuffleOp -> Affine n
+affOfOp (Cut c) = Affine 1 (negate (modulo c))
+affOfOp (Increment i) = Affine (modulo i) 0
+affOfOp Stack = Affine (modulo -1) (modulo -1)
+
+mergeOps :: KnownNat n => [Affine n] -> Affine n
+mergeOps = fold . reverse 
+
+-- given a transformation, where does the item at x end up?
+(@$) :: KnownNat n => Affine n -> Finite n -> Finite n
+Affine a b @$ x = a * x + b
+
+
+-- Parse the input file
+type Parser = Parsec Void Text
+
+sc :: Parser ()
+sc = L.space (skipSome spaceChar) CA.empty CA.empty
+-- sc = L.space (skipSome (char ' ')) CA.empty CA.empty
+
+lexeme  = L.lexeme sc
+integer = lexeme L.decimal
+signedInteger = L.signed sc integer
+symb = L.symbol sc
+cutSP = symb "cut"
+dealIncrementP = symb "deal with increment"
+dealIntoP = symb "deal into new stack"
+
+cutP = Cut <$> (cutSP *> signedInteger)
+incrementP = Increment <$> (dealIncrementP *> signedInteger)
+stackP = Stack <$ dealIntoP
+
+shuffleOpP = cutP <|> incrementP <|> stackP
+
+shuffleP = many shuffleOpP
+
+-- successfulParse :: Text -> [Vec]
+successfulParse :: Text -> Shuffle
+successfulParse input = 
+        case parse shuffleP "input" input of
+                Left  _err -> [] -- TIO.putStr $ T.pack $ parseErrorPretty err
+                Right shuffle -> shuffle
diff --git a/data/advent22.txt b/data/advent22.txt
new file mode 100644 (file)
index 0000000..97760b6
--- /dev/null
@@ -0,0 +1,100 @@
+cut -45
+deal with increment 28
+cut -9687
+deal with increment 47
+cut 7237
+deal with increment 12
+cut -9336
+deal with increment 72
+cut -9471
+deal into new stack
+cut -3034
+deal with increment 5
+cut -5333
+deal with increment 69
+cut -3998
+deal with increment 20
+cut 1217
+deal with increment 40
+cut -421
+deal into new stack
+cut 6883
+deal with increment 7
+cut 1897
+deal with increment 57
+cut -3069
+deal with increment 10
+cut -5522
+deal with increment 64
+cut 1422
+deal with increment 55
+cut 973
+deal with increment 57
+cut 1061
+deal with increment 60
+cut -5652
+deal with increment 9
+cut 2037
+deal with increment 73
+deal into new stack
+cut -8727
+deal with increment 59
+cut -2227
+deal into new stack
+cut 467
+deal with increment 39
+deal into new stack
+deal with increment 67
+cut -3708
+deal into new stack
+cut 1394
+deal with increment 42
+cut -6618
+deal with increment 21
+deal into new stack
+cut 9107
+deal with increment 33
+cut 892
+deal with increment 32
+deal into new stack
+cut -7566
+deal with increment 45
+cut 5149
+deal with increment 53
+deal into new stack
+deal with increment 71
+cut -1564
+deal with increment 68
+cut 6372
+deal with increment 2
+cut -3799
+deal with increment 39
+cut -2830
+deal with increment 63
+cut -4758
+deal with increment 38
+cut -6179
+deal with increment 16
+cut -1023
+deal into new stack
+deal with increment 34
+cut -8829
+deal with increment 70
+cut 9112
+deal with increment 72
+cut -4044
+deal with increment 29
+cut 3010
+deal with increment 48
+cut -9025
+deal with increment 72
+cut -8418
+deal with increment 45
+cut -4991
+deal with increment 19
+cut -6999
+deal with increment 11
+cut 1852
+deal with increment 56
+deal into new stack
+deal with increment 39
diff --git a/data/advent22c.txt b/data/advent22c.txt
new file mode 100644 (file)
index 0000000..480cbce
--- /dev/null
@@ -0,0 +1,10 @@
+deal into new stack
+cut -2
+deal with increment 7
+cut 8
+cut -4
+deal with increment 7
+cut 3
+deal with increment 9
+deal with increment 3
+cut -1
diff --git a/problems/day22.html b/problems/day22.html
new file mode 100644 (file)
index 0000000..403b6ad
--- /dev/null
@@ -0,0 +1,256 @@
+<!DOCTYPE html>
+<html lang="en-us">
+<head>
+<meta charset="utf-8"/>
+<title>Day 22 - Advent of Code 2019</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?24"/>
+<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, ads, 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="/2019/about">[About]</a></li><li><a href="/2019/events">[Events]</a></li><li><a href="https://teespring.com/adventofcode-2019" target="_blank">[Shop]</a></li><li><a href="/2019/settings">[Settings]</a></li><li><a href="/2019/auth/logout">[Log Out]</a></li></ul></nav><div class="user">Neil Smith <a href="/2019/support" class="supporter-badge" title="Advent of Code Supporter">(AoC++)</a> <span class="star-count">44*</span></div></div><div><h1 class="title-event">&nbsp;&nbsp;&nbsp;<span class="title-event-wrap">&lt;y&gt;</span><a href="/2019">2019</a><span class="title-event-wrap">&lt;/y&gt;</span></h1><nav><ul><li><a href="/2019">[Calendar]</a></li><li><a href="/2019/support">[AoC++]</a></li><li><a href="/2019/sponsors">[Sponsors]</a></li><li><a href="/2019/leaderboard">[Leaderboard]</a></li><li><a href="/2019/stats">[Stats]</a></li></ul></nav></div></header>
+
+<div id="sidebar">
+<div id="sponsor"><div class="quiet">Our <a href="/2019/sponsors">sponsors</a> help make Advent of Code possible:</div><div class="sponsor"><a href="https://xebia.com/community/advent-of-code" target="_blank" onclick="if(ga)ga('send','event','sponsor','sidebar',this.href);" rel="noopener">Xebia</a> - an international network of passionate technologists and craftspeople, dedicated to exploring and creating new frontiers in IT</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 22: Slam Shuffle ---</h2><p>There isn't much to do while you wait for the droids to repair your ship.  At least you're drifting in the right direction.  You decide to practice a new <a href="https://en.wikipedia.org/wiki/Shuffling">card shuffle</a> you've been working on.</p>
+<p>Digging through the ship's storage, you find a deck of <em>space cards</em>! Just like <span title="What do you mean, you've never heard of space cards? They're all the rage in Zozo.">any deck of space cards</span>, there are 10007 cards in the deck numbered <code>0</code> through <code>10006</code>. The deck must be new - they're still in <em>factory order</em>, with <code>0</code> on the top, then <code>1</code>, then <code>2</code>, and so on, all the way through to <code>10006</code> on the bottom.</p>
+<p>You've been practicing three different <em>techniques</em> that you use while shuffling. Suppose you have a deck of only 10 cards (numbered <code>0</code> through <code>9</code>):</p>
+<p><em>To <code>deal into new stack</code></em>, create a new stack of cards by dealing the top card of the deck onto the top of the new stack repeatedly until you run out of cards:</p>
+<pre><code>Top          Bottom
+0 1 2 3 4 5 6 7 8 9   Your deck
+                      New stack
+
+  1 2 3 4 5 6 7 8 9   Your deck
+                  0   New stack
+
+    2 3 4 5 6 7 8 9   Your deck
+                1 0   New stack
+
+      3 4 5 6 7 8 9   Your deck
+              2 1 0   New stack
+
+Several steps later...
+
+                  9   Your deck
+  8 7 6 5 4 3 2 1 0   New stack
+
+                      Your deck
+9 8 7 6 5 4 3 2 1 0   New stack
+</code></pre>
+<p>Finally, pick up the new stack you've just created and use it as the deck for the next technique.</p>
+<p><em>To <code>cut N</code> cards</em>, take the top <code>N</code> cards off the top of the deck and move them as a single unit to the bottom of the deck, retaining their order. For example, to <code>cut 3</code>:</p>
+<pre><code>Top          Bottom
+0 1 2 3 4 5 6 7 8 9   Your deck
+
+      3 4 5 6 7 8 9   Your deck
+0 1 2                 Cut cards
+
+3 4 5 6 7 8 9         Your deck
+              0 1 2   Cut cards
+
+3 4 5 6 7 8 9 0 1 2   Your deck
+</code></pre>
+<p>You've also been getting pretty good at a version of this technique where <code>N</code> is negative! In that case, cut (the absolute value of) <code>N</code> cards from the bottom of the deck onto the top.  For example, to <code>cut -4</code>:</p>
+<pre><code>Top          Bottom
+0 1 2 3 4 5 6 7 8 9   Your deck
+
+0 1 2 3 4 5           Your deck
+            6 7 8 9   Cut cards
+
+        0 1 2 3 4 5   Your deck
+6 7 8 9               Cut cards
+
+6 7 8 9 0 1 2 3 4 5   Your deck
+</code></pre>
+<p><em>To <code>deal with increment N</code></em>, start by clearing enough space on your table to lay out all of the cards individually in a long line.  Deal the top card into the leftmost position. Then, move <code>N</code> positions to the right and deal the next card there. If you would move into a position past the end of the space on your table, wrap around and keep counting from the leftmost card again.  Continue this process until you run out of cards.</p>
+<p>For example, to <code>deal with increment 3</code>:</p>
+<pre><code>
+0 1 2 3 4 5 6 7 8 9   Your deck
+. . . . . . . . . .   Space on table
+^                     Current position
+
+Deal the top card to the current position:
+
+  1 2 3 4 5 6 7 8 9   Your deck
+0 . . . . . . . . .   Space on table
+^                     Current position
+
+Move the current position right 3:
+
+  1 2 3 4 5 6 7 8 9   Your deck
+0 . . . . . . . . .   Space on table
+      ^               Current position
+
+Deal the top card:
+
+    2 3 4 5 6 7 8 9   Your deck
+0 . . 1 . . . . . .   Space on table
+      ^               Current position
+
+Move right 3 and deal:
+
+      3 4 5 6 7 8 9   Your deck
+0 . . 1 . . 2 . . .   Space on table
+            ^         Current position
+
+Move right 3 and deal:
+
+        4 5 6 7 8 9   Your deck
+0 . . 1 . . 2 . . 3   Space on table
+                  ^   Current position
+
+Move right 3, wrapping around, and deal:
+
+          5 6 7 8 9   Your deck
+0 . 4 1 . . 2 . . 3   Space on table
+    ^                 Current position
+
+And so on:
+
+0 7 4 1 8 5 2 9 6 3   Space on table
+</code></pre>
+<p>Positions on the table which already contain cards are still counted; they're not skipped.  Of course, this technique is carefully designed so it will never put two cards in the same position or leave a position empty.</p>
+<p>Finally, collect the cards on the table so that the leftmost card ends up at the top of your deck, the card to its right ends up just below the top card, and so on, until the rightmost card ends up at the bottom of the deck.</p>
+<p>The complete shuffle process (your puzzle input) consists of applying many of these techniques.  Here are some examples that combine techniques; they all start with a <em>factory order</em> deck of 10 cards:</p>
+<pre><code>deal with increment 7
+deal into new stack
+deal into new stack
+Result: 0 3 6 9 2 5 8 1 4 7
+</code></pre>
+<pre><code>cut 6
+deal with increment 7
+deal into new stack
+Result: 3 0 7 4 1 8 5 2 9 6
+</code></pre>
+<pre><code>deal with increment 7
+deal with increment 9
+cut -2
+Result: 6 3 0 7 4 1 8 5 2 9
+</code></pre>
+<pre><code>deal into new stack
+cut -2
+deal with increment 7
+cut 8
+cut -4
+deal with increment 7
+cut 3
+deal with increment 9
+deal with increment 3
+cut -1
+Result: 9 2 5 8 1 4 7 0 3 6
+</code></pre>
+<p>Positions within the deck count from <code>0</code> at the top, then <code>1</code> for the card immediately below the top card, and so on to the bottom.  (That is, cards start in the position matching their number.)</p>
+<p>After shuffling your <em>factory order</em> deck of 10007 cards, <em>what is the position of card <code>2019</code>?</em></p>
+</article>
+<p>Your puzzle answer was <code>2480</code>.</p><article class="day-desc"><h2 id="part2">--- Part Two ---</h2><p>After a while, you realize your shuffling skill won't improve much more with merely a single deck of cards.  You ask every 3D printer on the ship to make you some more cards while you check on the ship repairs.  While reviewing the work the droids have finished so far, you think you see <a href="https://en.wikipedia.org/wiki/Halley%27s_Comet">Halley's Comet</a> fly past!</p>
+<p>When you get back, you discover that the 3D printers have combined their power to create for you a single, giant, brand new, <em>factory order</em> deck of <em><code>119315717514047</code> space cards</em>.</p>
+<p>Finally, a deck of cards worthy of shuffling!</p>
+<p>You decide to apply your complete shuffle process (your puzzle input) to the deck <em><code>101741582076661</code> times in a row</em>.</p>
+<p>You'll need to be careful, though - one wrong move with this many cards and you might <em>overflow</em> your entire ship!</p>
+<p>After shuffling your new, giant, <em>factory order</em> deck that many times, <em>what number is on the card that ends up in position <code>2020</code>?</em></p>
+</article>
+<p>Your puzzle answer was <code>62416301438548</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="/2019">return to your Advent calendar</a> and try another puzzle.</p>
+<p>If you still want to see it, you can <a href="22/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+%22Slam+Shuffle%22+%2D+Day+22+%2D+Advent+of+Code+2019&amp;url=https%3A%2F%2Fadventofcode%2Ecom%2F2019%2Fday%2F22&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+%22Slam+Shuffle%22+%2D+Day+22+%2D+Advent+of+Code+2019+%23AdventOfCode+https%3A%2F%2Fadventofcode%2Ecom%2F2019%2Fday%2F22'}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
index a73acc666f1559d229ca3d23afcb9bbe23bc5b7c..fb6add80f6a48c9cb7a96199ebcb421e2f92ab1a 100644 (file)
@@ -59,6 +59,7 @@ packages:
 - advent19
 - advent20
 - advent21
+- advent22
 
 
 # Dependency packages to be pulled from upstream that are not in the resolver.