Added Solution for 2020 day 23
This commit is contained in:
parent
cb37bd7552
commit
dd5044e7ae
5 changed files with 200 additions and 0 deletions
8
2020/day23_crab_cups/Cargo.toml
Normal file
8
2020/day23_crab_cups/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "day23_crab_cups"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
101
2020/day23_crab_cups/challenge.txt
Normal file
101
2020/day23_crab_cups/challenge.txt
Normal file
|
@ -0,0 +1,101 @@
|
|||
The small crab challenges *you* to a game! The crab is going to mix up some cups, and you have to predict where they'll end up.
|
||||
|
||||
The cups will be arranged in a circle and labeled *clockwise* (your puzzle input). For example, if your labeling were `32415`, there would be five cups in the circle; going clockwise around the circle from the first cup, the cups would be labeled `3`, `2`, `4`, `1`, `5`, and then back to `3` again.
|
||||
|
||||
Before the crab starts, it will designate the first cup in your list as the *current cup*. The crab is then going to do *100 moves*.
|
||||
|
||||
Each *move*, the crab does the following actions:
|
||||
|
||||
* The crab picks up the *three cups* that are immediately *clockwise* of the *current cup*. They are removed from the circle; cup spacing is adjusted as necessary to maintain the circle.
|
||||
* The crab selects a *destination cup*: the cup with a *label* equal to the *current cup's* label minus one. If this would select one of the cups that was just picked up, the crab will keep subtracting one until it finds a cup that wasn't just picked up. If at any point in this process the value goes below the lowest value on any cup's label, it *wraps around* to the highest value on any cup's label instead.
|
||||
* The crab places the cups it just picked up so that they are *immediately clockwise* of the destination cup. They keep the same order as when they were picked up.
|
||||
* The crab selects a new *current cup*: the cup which is immediately clockwise of the current cup.
|
||||
|
||||
For example, suppose your cup labeling were `389125467`. If the crab were to do merely 10 moves, the following changes would occur:
|
||||
|
||||
```
|
||||
-- move 1 --
|
||||
cups: (3) 8 9 1 2 5 4 6 7
|
||||
pick up: 8, 9, 1
|
||||
destination: 2
|
||||
|
||||
-- move 2 --
|
||||
cups: 3 (2) 8 9 1 5 4 6 7
|
||||
pick up: 8, 9, 1
|
||||
destination: 7
|
||||
|
||||
-- move 3 --
|
||||
cups: 3 2 (5) 4 6 7 8 9 1
|
||||
pick up: 4, 6, 7
|
||||
destination: 3
|
||||
|
||||
-- move 4 --
|
||||
cups: 7 2 5 (8) 9 1 3 4 6
|
||||
pick up: 9, 1, 3
|
||||
destination: 7
|
||||
|
||||
-- move 5 --
|
||||
cups: 3 2 5 8 (4) 6 7 9 1
|
||||
pick up: 6, 7, 9
|
||||
destination: 3
|
||||
|
||||
-- move 6 --
|
||||
cups: 9 2 5 8 4 (1) 3 6 7
|
||||
pick up: 3, 6, 7
|
||||
destination: 9
|
||||
|
||||
-- move 7 --
|
||||
cups: 7 2 5 8 4 1 (9) 3 6
|
||||
pick up: 3, 6, 7
|
||||
destination: 8
|
||||
|
||||
-- move 8 --
|
||||
cups: 8 3 6 7 4 1 9 (2) 5
|
||||
pick up: 5, 8, 3
|
||||
destination: 1
|
||||
|
||||
-- move 9 --
|
||||
cups: 7 4 1 5 8 3 9 2 (6)
|
||||
pick up: 7, 4, 1
|
||||
destination: 5
|
||||
|
||||
-- move 10 --
|
||||
cups: (5) 7 4 1 8 3 9 2 6
|
||||
pick up: 7, 4, 1
|
||||
destination: 3
|
||||
|
||||
-- final --
|
||||
cups: 5 (8) 3 7 4 1 9 2 6
|
||||
|
||||
```
|
||||
|
||||
In the above example, the cups' values are the labels as they appear moving clockwise around the circle; the *current cup* is marked with `( )`.
|
||||
|
||||
After the crab is done, what order will the cups be in? Starting *after the cup labeled `1`*, collect the other cups' labels clockwise into a single string with no extra characters; each number except `1` should appear exactly once. In the above example, after 10 moves, the cups clockwise from `1` are labeled `9`, `2`, `6`, `5`, and so on, producing *`92658374`*. If the crab were to complete all 100 moves, the order after cup `1` would be *`67384529`*.
|
||||
|
||||
Using your labeling, simulate 100 moves. *What are the labels on the cups after cup `1`?*
|
||||
|
||||
Your puzzle answer was `82934675`.
|
||||
|
||||
\--- Part Two ---
|
||||
----------
|
||||
|
||||
Due to what you can only assume is a mistranslation (you're not exactly fluent in Crab), you are quite surprised when the crab starts arranging *many* cups in a circle on your raft - *one million* (`1000000`) in total.
|
||||
|
||||
Your labeling is still correct for the first few cups; after that, the remaining cups are just numbered in an increasing fashion starting from the number after the highest number in your list and proceeding one by one until one million is reached. (For example, if your labeling were `54321`, the cups would be numbered `5`, `4`, `3`, `2`, `1`, and then start counting up from `6` until one million is reached.) In this way, every number from one through one million is used exactly once.
|
||||
|
||||
After discovering where you made the mistake in translating Crab Numbers, you realize the small crab isn't going to do merely 100 moves; the crab is going to do *ten million* (`10000000`) moves!
|
||||
|
||||
The crab is going to hide your *stars* - one each - under the *two cups that will end up immediately clockwise of cup `1`*. You can have them if you predict what the labels on those cups will be when the crab is finished.
|
||||
|
||||
In the above example (`389125467`), this would be `934001` and then `159792`; multiplying these together produces *`149245887792`*.
|
||||
|
||||
Determine which two cups will end up immediately clockwise of cup `1`. *What do you get if you multiply their labels together?*
|
||||
|
||||
Your puzzle answer was `474600314018`.
|
||||
|
||||
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 `327465189`.
|
89
2020/day23_crab_cups/src/lib.rs
Normal file
89
2020/day23_crab_cups/src/lib.rs
Normal file
|
@ -0,0 +1,89 @@
|
|||
use core::fmt::Display;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum ParseError {
|
||||
ParseIntError(char),
|
||||
}
|
||||
|
||||
impl Display for ParseError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::ParseIntError(e) => write!(f, "Unable to parse into integer: {e}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run(input: &str) -> Result<(usize, usize), ParseError> {
|
||||
let arrangement: Vec<_> = input.chars().map(|c| c.to_digit(10).ok_or(ParseError::ParseIntError(c)).map(|i| i as usize)).collect::<Result<Vec<_>, _>>()?;
|
||||
let mut cups = (1..=9).map(|i| arrangement[(arrangement.iter().position(|cup| *cup == i).unwrap()+1) % arrangement.len()]).collect::<Vec<_>>();
|
||||
let mut next = arrangement[0];
|
||||
let mut cups_2 = cups.clone();
|
||||
cups_2[arrangement[arrangement.len()-1]-1] = cups.len()+1;
|
||||
cups_2.append(&mut (cups.len()+2..=1_000_000).collect());
|
||||
cups_2.push(next);
|
||||
|
||||
for _ in 0..100 {
|
||||
play(&mut cups, &mut next);
|
||||
}
|
||||
|
||||
let mut first = 0;
|
||||
let mut next_digit = cups[0];
|
||||
while next_digit != 1 {
|
||||
first *= 10;
|
||||
first += next_digit;
|
||||
next_digit = cups[next_digit-1];
|
||||
}
|
||||
|
||||
next = arrangement[0];
|
||||
for _ in 0..10_000_000 {
|
||||
play(&mut cups_2, &mut next);
|
||||
}
|
||||
|
||||
let second = cups_2[0] * cups_2[cups_2[0]-1];
|
||||
Ok((first, second))
|
||||
}
|
||||
|
||||
fn play(cups: &mut Vec<usize>, current: &mut usize) {
|
||||
let moved = [
|
||||
cups[*current-1],
|
||||
cups[cups[*current-1]-1],
|
||||
cups[cups[cups[*current-1]-1]-1]
|
||||
];
|
||||
let mut target = *current - 1;
|
||||
loop {
|
||||
if target < 1 {
|
||||
target = cups.len();
|
||||
} else if moved.contains(&target) {
|
||||
target -= 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
cups[*current-1] = cups[moved[2]-1];
|
||||
cups[moved[2]-1] = cups[target-1];
|
||||
cups[target-1] = moved[0];
|
||||
|
||||
*current = cups[*current-1];
|
||||
}
|
||||
|
||||
#[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((67384529, 149245887792)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_challenge() {
|
||||
let challenge_input = read_file("tests/challenge_input");
|
||||
assert_eq!(run(&challenge_input), Ok((82934675, 474600314018)));
|
||||
}
|
||||
}
|
1
2020/day23_crab_cups/tests/challenge_input
Normal file
1
2020/day23_crab_cups/tests/challenge_input
Normal file
|
@ -0,0 +1 @@
|
|||
327465189
|
1
2020/day23_crab_cups/tests/sample_input
Normal file
1
2020/day23_crab_cups/tests/sample_input
Normal file
|
@ -0,0 +1 @@
|
|||
389125467
|
Loading…
Add table
Add a link
Reference in a new issue