-
Notifications
You must be signed in to change notification settings - Fork 0
Solve Day 15 #25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
manuphatak
wants to merge
9
commits into
main
Choose a base branch
from
day_15
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Solve Day 15 #25
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
63b300b
Setup Day 15
manuphatak 99e0463
Solve part 1
manuphatak 71edc50
Solve part 2
manuphatak 3020dcc
Use explicit imports
manuphatak e681661
update readme to include part 2
manuphatak e794db1
leave todo comments
manuphatak 5deecfe
re-dupe specs, too much abstraction
manuphatak 17bf73d
Merge remote-tracking branch 'origin/main' into day_15
manuphatak 6ec6bf7
Merge remote-tracking branch 'origin/main' into day_15
manuphatak File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| ## Day 15: Rambunctious Recitation | ||
|
|
||
| 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. | ||
|
|
||
| While you wait for your flight, you decide to check in with the Elves back at the North Pole. They're playing a _memory game_ and are ever so excited to explain the rules! | ||
|
|
||
| In this game, the players take turns saying _numbers_ . They begin by taking turns reading from a list of _starting numbers_ (your puzzle input). Then, each turn consists of considering the _most recently spoken number_ : | ||
|
|
||
| - If that was the _first_ time the number has been spoken, the current player says _`0`_ . | ||
| - Otherwise, the number had been spoken before; the current player announces _how many turns apart_ the number is from when it was previously spoken. | ||
|
|
||
| So, after the starting numbers, each turn results in that player speaking aloud either _`0`_ (if the last number is new) or an _age_ (if the last number is a repeat). | ||
|
|
||
| For example, suppose the starting numbers are `0,3,6` : | ||
|
|
||
| - _Turn 1_ : The `1` st number spoken is a starting number, _`0`_ . | ||
| - _Turn 2_ : The `2` nd number spoken is a starting number, _`3`_ . | ||
| - _Turn 3_ : The `3` rd number spoken is a starting number, _`6`_ . | ||
| - _Turn 4_ : Now, consider the last number spoken, `6` . Since that was the first time the number had been spoken, the `4` th number spoken is _`0`_ . | ||
| - _Turn 5_ : Next, again consider the last number spoken, `0` . Since it _had_ been spoken before, the next number to speak is the difference between the turn number when it was last spoken (the previous turn, `4` ) and the turn number of the time it was most recently spoken before then (turn `1` ). Thus, the `5` th number spoken is `4 - 1` , _`3`_ . | ||
| - _Turn 6_ : The last number spoken, `3` had also been spoken before, most recently on turns `5` and `2` . So, the `6` th number spoken is `5 - 2` , _`3`_ . | ||
| - _Turn 7_ : Since `3` was just spoken twice in a row, and the last two turns are `1` turn apart, the `7` th number spoken is _`1`_ . | ||
| - _Turn 8_ : Since `1` is new, the `8` th number spoken is _`0`_ . | ||
| - _Turn 9_ : `0` was last spoken on turns `8` and `4` , so the `9` th number spoken is the difference between them, _`4`_ . | ||
| - _Turn 10_ : `4` is new, so the `10` th number spoken is _`0`_ . | ||
|
|
||
| (The game ends when the Elves get sick of playing or dinner is ready, whichever comes first.) | ||
|
|
||
| Their question for you is: what will be the _`2020` th_ number spoken? In the example above, the `2020` th number spoken will be `436` . | ||
|
|
||
| Here are a few more examples: | ||
|
|
||
| - Given the starting numbers `1,3,2` , the `2020` th number spoken is `1` . | ||
| - Given the starting numbers `2,1,3` , the `2020` th number spoken is `10` . | ||
| - Given the starting numbers `1,2,3` , the `2020` th number spoken is `27` . | ||
| - Given the starting numbers `2,3,1` , the `2020` th number spoken is `78` . | ||
| - Given the starting numbers `3,2,1` , the `2020` th number spoken is `438` . | ||
| - Given the starting numbers `3,1,2` , the `2020` th number spoken is `1836` . | ||
|
|
||
| Given your starting numbers, _what will be the `2020` th number spoken?_ | ||
|
|
||
| ## Part Two | ||
|
|
||
| Impressed, the Elves issue you a challenge: determine the `30000000` th number spoken. For example, given the same starting numbers as above: | ||
|
|
||
| - Given `0,3,6` , the `30000000` th number spoken is `175594` . | ||
| - Given `1,3,2` , the `30000000` th number spoken is `2578` . | ||
| - Given `2,1,3` , the `30000000` th number spoken is `3544142` . | ||
| - Given `1,2,3` , the `30000000` th number spoken is `261214` . | ||
| - Given `2,3,1` , the `30000000` th number spoken is `6895259` . | ||
| - Given `3,2,1` , the `30000000` th number spoken is `18` . | ||
| - Given `3,1,2` , the `30000000` th number spoken is `362` . | ||
|
|
||
| Given your starting numbers, _what will be the `30000000` th number spoken?_ | ||
|
|
||
| ## Link | ||
|
|
||
| [https://adventofcode.com/2020/day/15][1] | ||
|
|
||
| [1]: https://adventofcode.com/2020/day/15 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| module Day15.Solution (memoryGame, part1, part2) where | ||
|
|
||
| import Advent.Utils (fromRightOrShowError, readInt) | ||
| import Control.Monad (liftM3) | ||
| import qualified Data.IntMap.Lazy as IntMap | ||
| import Text.Parsec | ||
| ( ParseError, | ||
| Parsec, | ||
| char, | ||
| digit, | ||
| endOfLine, | ||
| many1, | ||
| parse, | ||
| sepBy, | ||
| ) | ||
|
|
||
| part1 :: String -> String | ||
| part1 = show . memoryGame 2020 . fromRightOrShowError . parseInts | ||
|
|
||
| part2 :: String -> String | ||
| part2 = show . memoryGame 30000000 . fromRightOrShowError . parseInts | ||
|
|
||
| parseInts :: String -> Either ParseError [Int] | ||
| parseInts = parse (intsParser <* endOfLine) "" | ||
| where | ||
| intsParser :: Parsec String () [Int] | ||
| intsParser = (readInt <$> many1 digit) `sepBy` char ',' | ||
|
|
||
| type State = IntMap.IntMap Int | ||
|
|
||
| memoryGame :: Int -> [Int] -> Int | ||
| memoryGame target = liftM3 go length last initialState | ||
| where | ||
| go :: Int -> Int -> State -> Int | ||
| go turn prev state | ||
| | turn == target = prev | ||
| | otherwise = go (succ turn) next nextState | ||
| where | ||
| next = (maybe 0 (turn -) . IntMap.lookup prev) state | ||
| nextState = IntMap.insert prev turn state | ||
|
|
||
| initialState :: [Int] -> State | ||
| initialState = IntMap.fromList . flip zip [1 ..] . init | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| module Day15.SolutionSpec (spec) where | ||
|
|
||
| import Data.Foldable (for_) | ||
| import Day15.Solution (memoryGame, part1, part2) | ||
| import Test.Hspec | ||
|
|
||
| spec :: Spec | ||
| spec = parallel $ do | ||
| it "solves Part 1" $ do | ||
| input <- readFile "./test/Day15/input.txt" | ||
| part1 input `shouldBe` "694" | ||
| -- TODO: this runs in ~40 seconds with production optimizations | ||
| xit "solves Part 2" $ do | ||
| input <- readFile "./test/Day15/input.txt" | ||
| part2 input `shouldBe` "21768614" | ||
| describe "memoryGame" $ do | ||
| context "when looking at the 2020th result" $ do | ||
| let n = 2020 | ||
| let cases = | ||
| [ ([0, 3, 6], 436), | ||
| ([1, 3, 2], 1), | ||
| ([2, 1, 3], 10), | ||
| ([1, 2, 3], 27), | ||
| ([2, 3, 1], 78), | ||
| ([3, 2, 1], 438), | ||
| ([3, 1, 2], 1836) | ||
| ] | ||
| let test (input, expected) = it ("is " ++ show expected ++ " for input " ++ show input) $ do | ||
| memoryGame n input `shouldBe` expected | ||
|
|
||
| for_ cases test | ||
|
|
||
| -- TODO: figure out how to make this not take 10 minutes | ||
| xcontext "when looking at the 30000000th result" $ do | ||
| let n = 30000000 | ||
| let cases = | ||
| [ ([0, 3, 6], 175594), | ||
| ([1, 3, 2], 2578), | ||
| ([2, 1, 3], 3544142), | ||
| ([1, 2, 3], 261214), | ||
| ([2, 3, 1], 6895259), | ||
| ([3, 2, 1], 18), | ||
| ([3, 1, 2], 362) | ||
| ] | ||
| let test (input, expected) = it ("is " ++ show expected ++ " for input " ++ show input) $ do | ||
| memoryGame n input `shouldBe` expected | ||
|
|
||
| for_ cases test | ||
|
|
||
| -- 300 | ||
| -- Finished in 0.0017 seconds | ||
| -- Finished in 0.0011 seconds | ||
|
|
||
| -- 3000 | ||
| -- Finished in 0.0061 seconds | ||
| -- Finished in 0.0052 seconds | ||
|
|
||
| -- 30000 | ||
| -- Finished in 0.1399 seconds | ||
| -- Finished in 0.1418 seconds | ||
|
|
||
| -- 300000 | ||
| -- Finished in 1.7987 seconds | ||
| -- Finished in 1.8572 seconds | ||
| -- Finished in 1.7550 seconds | ||
|
|
||
| -- 3000000 | ||
| -- Finished in 30.7137 seconds | ||
| -- Finished in 26.4237 seconds | ||
| -- Finished in 25.2911 seconds | ||
|
|
||
| -- 30000000 | ||
| -- TODO: Need to get here! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| 17,1,3,16,19,0 |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO: This runs too slowly to check.