Added Solution for 2020 day 15
This commit is contained in:
parent
5594482117
commit
5728d1c5d3
5 changed files with 125 additions and 0 deletions
8
2020/day15_rambunctious_recitation/Cargo.toml
Normal file
8
2020/day15_rambunctious_recitation/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "day15_rambunctious_recitation"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
63
2020/day15_rambunctious_recitation/challenge.txt
Normal file
63
2020/day15_rambunctious_recitation/challenge.txt
Normal file
|
@ -0,0 +1,63 @@
|
|||
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?*
|
||||
|
||||
Your puzzle answer was `959`.
|
||||
|
||||
\--- 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?*
|
||||
|
||||
Your puzzle answer was `116590`.
|
||||
|
||||
Both parts of this puzzle are complete! They provide two gold stars: \*\*
|
||||
|
||||
At this point, you should [return to your Advent calendar](/2020) and try another puzzle.
|
||||
|
||||
Your puzzle input was `18,11,9,0,5,1`.
|
52
2020/day15_rambunctious_recitation/src/lib.rs
Normal file
52
2020/day15_rambunctious_recitation/src/lib.rs
Normal file
|
@ -0,0 +1,52 @@
|
|||
use std::num::ParseIntError;
|
||||
|
||||
pub fn run(input: &str) -> Result<(usize, usize), ParseIntError> {
|
||||
let initial: Vec<_> = input.split(',').map(|n| n.parse::<usize>()).collect::<Result<Vec<_>, _>>()?;
|
||||
let mut said_last = vec![0; 30_000_000];
|
||||
initial.iter().enumerate().for_each(|(idx, i)| {said_last[*i] = idx+1});
|
||||
let mut last_number = initial[initial.len()-1];
|
||||
let mut next_number = initial.iter().rev().skip(1).position(|n| *n == last_number).map(|n| n+1).unwrap_or(0);
|
||||
(initial.len()+1..=2020).for_each(|turn| {
|
||||
last_number = next_number;
|
||||
if said_last[last_number] == 0 {
|
||||
next_number = 0;
|
||||
} else {
|
||||
next_number = turn - said_last[last_number];
|
||||
}
|
||||
said_last[last_number] = turn;
|
||||
});
|
||||
let first = last_number;
|
||||
(2021..=30_000_000).for_each(|turn| {
|
||||
last_number = next_number;
|
||||
if said_last[last_number] == 0 {
|
||||
next_number = 0;
|
||||
} else {
|
||||
next_number = turn - said_last[last_number];
|
||||
}
|
||||
said_last[last_number] = turn;
|
||||
});
|
||||
let second = last_number;
|
||||
Ok((first, second))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::fs::read_to_string;
|
||||
|
||||
fn read_file(name: &str) -> String {
|
||||
read_to_string(name).expect(&format!("Unable to read file: {name}")[..]).trim().to_string()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sample() {
|
||||
let sample_input = read_file("tests/sample_input");
|
||||
assert_eq!(run(&sample_input), Ok((436, 175594)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_challenge() {
|
||||
let challenge_input = read_file("tests/challenge_input");
|
||||
assert_eq!(run(&challenge_input), Ok((959, 116590)));
|
||||
}
|
||||
}
|
1
2020/day15_rambunctious_recitation/tests/challenge_input
Normal file
1
2020/day15_rambunctious_recitation/tests/challenge_input
Normal file
|
@ -0,0 +1 @@
|
|||
18,11,9,0,5,1
|
1
2020/day15_rambunctious_recitation/tests/sample_input
Normal file
1
2020/day15_rambunctious_recitation/tests/sample_input
Normal file
|
@ -0,0 +1 @@
|
|||
0,3,6
|
Loading…
Add table
Add a link
Reference in a new issue