Add 2024 Quest 5
This commit is contained in:
parent
f4153f6135
commit
22d0b8bea7
9 changed files with 539 additions and 0 deletions
6
2024/day05_pseudo-random_clap_dance/Cargo.toml
Normal file
6
2024/day05_pseudo-random_clap_dance/Cargo.toml
Normal file
|
@ -0,0 +1,6 @@
|
|||
[package]
|
||||
name = "day05_pseudo-random_clap_dance"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
232
2024/day05_pseudo-random_clap_dance/challenge.txt
Normal file
232
2024/day05_pseudo-random_clap_dance/challenge.txt
Normal file
|
@ -0,0 +1,232 @@
|
|||
Part I
|
||||
|
||||
No grand tournament is complete without lively music and spirited dancing! As evening falls, crowds gather in the main square to partake in the whimsical Pseudo-Random Clap Dance. Each participant receives a number from the Master of Ceremonies which is then prominently displayed on their chest. Then, they choose their places in one of four columns, standing one behind the other, forming long lines.
|
||||
With everyone in position, the dance begins. It unfolds in rounds, with each round featuring one person designated as the Clapper. In the first round, the Clapper is the first person in the first column. In the second round, it's the first person in the second column, followed by the first person in the third column in the third round, and finally, the first person in the fourth column in the fourth round.
|
||||
The Clapper moves to the beginning of the column to their right, facing its members. If the Clapper is from the fourth column, they move to the start of the first column. All members of that column extend their arms to the sides. The Clapper then dances around the column from the left, high-fiving each extended hand. Upon reaching the end of the column, they switch to the right side and continue in the opposite direction. The crowd counts each clap out loud, starting from one. When the shouted number matches the Clapper's chest number, an absorption occurs.
|
||||
A Clapper can be absorbed into the column in two ways. If they are circling from the left side, they are absorbed in front of the person they are high-fiving. If on the right side, they are absorbed behind that person.
|
||||
After absorption, the first person from each column combines their numbers into a single large number, shouting it out loud before the next round begins.
|
||||
Just before the start, the king delivers a brief speech, concluding with a caution to the knights participating in the tournament to remain vigilant! You decide to practice predicting the flow of the dance, so you note down all columns as seen from above.
|
||||
Example based on the following notes:
|
||||
2 3 4 5
|
||||
3 4 5 2
|
||||
4 5 2 3
|
||||
5 2 3 4
|
||||
The first Clapper is the person marked with 2 on the top left side. After the initial move to the next column, it looks like this:
|
||||
2
|
||||
3 3 4 5
|
||||
4 4 5 2
|
||||
5 5 2 3
|
||||
2 3 4
|
||||
Clapping time! The Clapper's number is 2, so there will be only 2 claps.
|
||||
"ONE!"
|
||||
323 4 5
|
||||
4 4 5 2
|
||||
5 5 2 3
|
||||
2 3 4 "TWO!"
|
||||
3 3 4 5
|
||||
424 5 2
|
||||
5 5 2 3
|
||||
2 3 4
|
||||
The Clapper is on the left side of the target column, so absorption results in them taking the place in front of the last high-fived dancer.
|
||||
3 3 4 5
|
||||
4 2 5 2
|
||||
5 4 2 3
|
||||
5 3 4
|
||||
2
|
||||
The people in the front combine their numbers and shout:
|
||||
"3345!"
|
||||
3 3 4 5
|
||||
4 2 5 2
|
||||
5 4 2 3
|
||||
5 3 4
|
||||
2
|
||||
The result of the first round is 3345.
|
||||
The second round goes like this:
|
||||
|
||||
3 3 4 5
|
||||
4 2 5 2
|
||||
5 4 2 3
|
||||
5 3 4
|
||||
2 3
|
||||
3 2 4 5
|
||||
4 4 5 2
|
||||
5 5 2 3
|
||||
2 3 4
|
||||
"ONE!"
|
||||
3 234 5
|
||||
4 4 5 2
|
||||
5 5 2 3
|
||||
2 3 4
|
||||
"TWO!"
|
||||
3 2 4 5
|
||||
4 435 2
|
||||
5 5 2 3
|
||||
2 3 4
|
||||
"THREE!"
|
||||
3 2 4 5
|
||||
4 4 5 2
|
||||
5 532 3
|
||||
2 3 4
|
||||
|
||||
3 2 4 5
|
||||
4 4 5 2
|
||||
5 5 3 3
|
||||
2 2 4
|
||||
3 "3245!"
|
||||
3 2 4 5
|
||||
4 4 5 2
|
||||
5 5 3 3
|
||||
2 2 4
|
||||
3
|
||||
The third round:
|
||||
|
||||
3 2 4 5
|
||||
4 4 5 2
|
||||
5 5 3 3
|
||||
2 2 4
|
||||
3 4
|
||||
3 2 5 5
|
||||
4 4 3 2
|
||||
5 5 2 3
|
||||
2 3 4
|
||||
"ONE!"
|
||||
3 2 545
|
||||
4 4 3 2
|
||||
5 5 2 3
|
||||
2 3 4
|
||||
"TWO!"
|
||||
3 2 5 5
|
||||
4 4 342
|
||||
5 5 2 3
|
||||
2 3 4
|
||||
"THREE!"
|
||||
3 2 5 5
|
||||
4 4 3 2
|
||||
5 5 243
|
||||
2 3 4
|
||||
"FOUR!"
|
||||
3 2 5 5
|
||||
4 4 3 2
|
||||
5 5 2 3
|
||||
2 344
|
||||
|
||||
3 2 5 5
|
||||
4 4 3 2
|
||||
5 5 2 3
|
||||
2 3 4
|
||||
4 "3255!"
|
||||
3 2 5 5
|
||||
4 4 3 2
|
||||
5 5 2 3
|
||||
2 3 4
|
||||
4
|
||||
The following round:
|
||||
|
||||
3 2 5 5
|
||||
4 4 3 2
|
||||
5 5 2 3
|
||||
2 3 4
|
||||
4 5
|
||||
3 2 5 2
|
||||
4 4 3 3
|
||||
5 5 2 4
|
||||
2 3 4
|
||||
"ONE!"
|
||||
53 2 5 2
|
||||
4 4 3 3
|
||||
5 5 2 4
|
||||
2 3 4
|
||||
"TWO!"
|
||||
3 2 5 2
|
||||
54 4 3 3
|
||||
5 5 2 4
|
||||
2 3 4
|
||||
"THREE!"
|
||||
3 2 5 2
|
||||
4 4 3 3
|
||||
55 5 2 4
|
||||
2 3 4
|
||||
"FOUR!"
|
||||
3 2 5 2
|
||||
4 4 3 3
|
||||
555 2 4
|
||||
2 3 4
|
||||
"FIVE!"
|
||||
3 2 5 2
|
||||
454 3 3
|
||||
5 5 2 4
|
||||
2 3 4
|
||||
|
||||
3 2 5 2
|
||||
4 4 3 3
|
||||
5 5 2 4
|
||||
5 2 3 4
|
||||
"3252!"
|
||||
3 2 5 2
|
||||
4 4 3 3
|
||||
5 5 2 4
|
||||
5 2 3 4
|
||||
|
||||
Note that the Clapper ends on the right side of the column, so the target place in this case is behind the last high-fived person.
|
||||
For this example, the numbers shouted at the end of each round are as follows:
|
||||
Round Number
|
||||
1: 3345
|
||||
2: 3245
|
||||
3: 3255
|
||||
4: 3252
|
||||
5: 4252
|
||||
6: 4452
|
||||
7: 4422
|
||||
8: 4423
|
||||
9: 2423
|
||||
10: 2323
|
||||
What is the number shouted at the end of the 10th round?
|
||||
|
||||
Part II
|
||||
|
||||
The first dance went exactly as you predicted, so you feel ready for the real challenge.
|
||||
For the upcoming dance, the master of ceremonies meticulously assigns numbers and personally positions the participants in columns. The king takes the stage once more:
|
||||
|
||||
As you know, in our traditional dance some of the numbers shouted at the end of each round
|
||||
can eventually repeat. The next dance will conclude in the round where one of the numbers
|
||||
at the end of the round is shouted for the 2024th time! Your task, my dear knights,
|
||||
is to predict this number and the duration of the dance. Multiply the final number
|
||||
by the round in which it was shouted for the 2024th time to get your final answer.
|
||||
|
||||
Good luck!
|
||||
|
||||
Example based on the following notes:
|
||||
2 3 4 5
|
||||
6 7 8 9
|
||||
In this example, the dance unfolds as follows:
|
||||
Round Number Shouts
|
||||
1: 6345 1
|
||||
2: 6245 1
|
||||
3: 6285 1
|
||||
4: 5284 1
|
||||
5: 6584 1
|
||||
6: 6254 1
|
||||
7: 6285 2
|
||||
8: 5284 2
|
||||
9: 6584 2
|
||||
10: 6254 2
|
||||
...
|
||||
8095: 6285 2024
|
||||
After 10 rounds, some numbers were shouted twice already: 6285, 5284, 6584, and 6254. By continuing further, the first number shouted for the 2024th time is 6285, and this happens at the end of round 8095.
|
||||
Multiplying 6285 by 8095 gives the final answer: 50877075.
|
||||
What do you get if you multiply the first number shouted for the 2024th time by the total number of dance rounds?
|
||||
|
||||
Part III
|
||||
|
||||
Time for the final dance! The Master of Ceremonies once again arranges everyone with the utmost care.
|
||||
The king presents another riddle:
|
||||
|
||||
Sadly, every good time must come to an end eventually,
|
||||
but what if our next dance were to go on forever?
|
||||
Can you predict what would be the highest number that could be shouted?
|
||||
|
||||
Example based on the following notes:
|
||||
2 3 4 5
|
||||
6 7 8 9
|
||||
Assuming this dance would never end, the highest number shouted would be: 6584.
|
||||
What is the highest possible number that can appear at the end of a round in the final dance?
|
139
2024/day05_pseudo-random_clap_dance/src/lib.rs
Normal file
139
2024/day05_pseudo-random_clap_dance/src/lib.rs
Normal file
|
@ -0,0 +1,139 @@
|
|||
use core::fmt::{Display, Write};
|
||||
use std::collections::{BTreeMap, HashMap, VecDeque};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum ParseError {
|
||||
GridMalformed(usize, usize, usize),
|
||||
ParseIntError(String),
|
||||
}
|
||||
|
||||
impl Display for ParseError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::GridMalformed(first, idx, len) => write!(f, "Grid is not rectangular: First line has {first} items, but line {idx} has {len}."),
|
||||
Self::ParseIntError(e) => write!(f, "Unable to parse into a number: {e}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Dancers {
|
||||
dancers: Vec<VecDeque<usize>>,
|
||||
columns: usize,
|
||||
round: usize,
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for Dancers {
|
||||
type Error = ParseError;
|
||||
|
||||
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||||
let columns = value.lines().next().unwrap_or_default().split_whitespace().count();
|
||||
let mut dancers = vec![VecDeque::new(); columns];
|
||||
for (y, l) in value.lines().enumerate() {
|
||||
let numbers: Vec<_> = l.split_whitespace().map(|c| c.parse::<usize>().map_err(|_| ParseError::ParseIntError(c.to_string()))).collect::<Result<Vec<_>, _>>()?;
|
||||
if numbers.len() != columns {
|
||||
return Err(Self::Error::GridMalformed(columns, y, numbers.len()));
|
||||
}
|
||||
numbers.iter().enumerate().for_each(|(x, n)| dancers[x].push_back(*n));
|
||||
}
|
||||
Ok(Self { dancers, columns, round: 0 })
|
||||
}
|
||||
}
|
||||
|
||||
impl Dancers {
|
||||
fn dance(&mut self) -> usize {
|
||||
let clapper = self.dancers[self.round % self.columns].pop_front().unwrap();
|
||||
self.round += 1;
|
||||
let column = &mut self.dancers[self.round % self.columns];
|
||||
let direction = (clapper-1) / column.len();
|
||||
let residual = clapper % column.len();
|
||||
if direction & 1 == 0 {
|
||||
// left side
|
||||
if residual == 0 {
|
||||
column.insert(column.len()-1, clapper);
|
||||
} else {
|
||||
column.insert(residual-1, clapper);
|
||||
}
|
||||
} else {
|
||||
//right side
|
||||
if residual == 0 {
|
||||
column.insert(1, clapper)
|
||||
} else {
|
||||
column.insert(column.len()-residual+1, clapper)
|
||||
}
|
||||
}
|
||||
self.dancers.iter().fold(String::new(), |mut output, c| {
|
||||
let _ = write!(output, "{}", c.front().unwrap());
|
||||
output
|
||||
}).parse().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run(input: &str, part: usize) -> Result<usize, ParseError> {
|
||||
let mut dancers = Dancers::try_from(input)?;
|
||||
match part {
|
||||
1 => {
|
||||
for _ in 0..9 { dancers.dance(); }
|
||||
Ok(dancers.dance())
|
||||
},
|
||||
2 => {
|
||||
// There are probably loops in the results to be exploited here, but I don't see how
|
||||
// to spot them algorithmically and saving the entire state after each dance, just
|
||||
// to look for repetitions, seems excessive.
|
||||
let mut numbers = HashMap::new();
|
||||
loop {
|
||||
let this = dancers.dance();
|
||||
let repetitions: usize = *numbers.get(&this).unwrap_or(&0);
|
||||
if repetitions == 2023 {
|
||||
return Ok(this * dancers.round);
|
||||
} else {
|
||||
numbers.insert(this, repetitions+1);
|
||||
}
|
||||
}
|
||||
},
|
||||
3 => {
|
||||
// Admittedly, there is no proof that no more higher numbers will appear later.
|
||||
// But I simply hope that at the point at which a number repeats itself for the
|
||||
// 10th time, no more new ones will appear.
|
||||
let mut numbers = BTreeMap::new();
|
||||
loop {
|
||||
let this = dancers.dance();
|
||||
let repetitions: usize = *numbers.get(&this).unwrap_or(&0);
|
||||
if repetitions == 9 {
|
||||
return Ok(numbers.pop_last().unwrap().0);
|
||||
} else {
|
||||
numbers.insert(this, repetitions+1);
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
_ => panic!("Illegal part number"),
|
||||
}
|
||||
}
|
||||
|
||||
#[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 expected = [2323, 50877075, 6584];
|
||||
for part in 1..=3 {
|
||||
let sample_input = read_file(&format!("tests/sample{part}"));
|
||||
assert_eq!(run(&sample_input, part), Ok(expected[part-1]));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_challenge() {
|
||||
let expected = [2232, 14029502980017, 8265100210021008];
|
||||
for part in 1..=3 {
|
||||
let challenge_input = read_file(&format!("tests/challenge{part}"));
|
||||
assert_eq!(run(&challenge_input, part), Ok(expected[part-1]));
|
||||
}
|
||||
}
|
||||
}
|
5
2024/day05_pseudo-random_clap_dance/tests/challenge1
Normal file
5
2024/day05_pseudo-random_clap_dance/tests/challenge1
Normal file
|
@ -0,0 +1,5 @@
|
|||
5 2 3 2
|
||||
3 4 3 5
|
||||
2 2 4 3
|
||||
5 5 4 4
|
||||
4 2 3 5
|
99
2024/day05_pseudo-random_clap_dance/tests/challenge2
Normal file
99
2024/day05_pseudo-random_clap_dance/tests/challenge2
Normal file
|
@ -0,0 +1,99 @@
|
|||
72 36 76 28
|
||||
73 14 38 86
|
||||
30 89 31 61
|
||||
12 26 35 75
|
||||
63 93 54 64
|
||||
76 65 79 50
|
||||
17 95 61 94
|
||||
71 29 75 47
|
||||
64 66 31 80
|
||||
48 22 20 12
|
||||
72 46 81 11
|
||||
33 73 25 42
|
||||
53 79 45 80
|
||||
83 11 26 74
|
||||
41 98 92 69
|
||||
98 94 89 84
|
||||
15 59 35 87
|
||||
53 45 14 26
|
||||
69 35 78 62
|
||||
96 82 39 67
|
||||
69 51 67 46
|
||||
62 44 70 90
|
||||
81 48 65 76
|
||||
78 97 29 92
|
||||
92 82 20 68
|
||||
37 45 67 63
|
||||
40 97 94 56
|
||||
19 15 55 91
|
||||
50 40 84 29
|
||||
46 95 59 27
|
||||
31 23 48 42
|
||||
74 13 91 61
|
||||
18 30 28 33
|
||||
72 12 25 38
|
||||
59 34 30 58
|
||||
28 91 37 34
|
||||
48 16 27 10
|
||||
49 83 19 39
|
||||
59 15 87 69
|
||||
88 30 86 37
|
||||
96 82 11 16
|
||||
32 13 73 49
|
||||
89 53 75 10
|
||||
84 42 70 52
|
||||
17 98 77 17
|
||||
14 11 93 50
|
||||
21 86 26 63
|
||||
12 81 54 70
|
||||
61 68 55 99
|
||||
28 26 22 43
|
||||
91 94 36 78
|
||||
57 23 31 28
|
||||
81 66 96 58
|
||||
71 56 30 74
|
||||
95 99 52 38
|
||||
21 40 86 93
|
||||
32 96 13 21
|
||||
60 31 99 34
|
||||
20 55 19 95
|
||||
13 85 34 84
|
||||
64 32 85 21
|
||||
76 12 88 47
|
||||
27 13 40 77
|
||||
51 58 90 15
|
||||
22 24 72 67
|
||||
10 60 42 40
|
||||
39 79 89 64
|
||||
60 41 37 80
|
||||
50 45 54 90
|
||||
90 83 68 23
|
||||
57 55 46 82
|
||||
41 52 65 43
|
||||
35 56 62 36
|
||||
79 65 36 33
|
||||
88 46 39 20
|
||||
51 60 73 53
|
||||
75 14 88 83
|
||||
47 10 24 92
|
||||
37 17 44 63
|
||||
77 18 56 20
|
||||
23 16 11 29
|
||||
19 71 52 98
|
||||
22 44 33 47
|
||||
74 41 57 87
|
||||
29 62 35 43
|
||||
43 15 68 39
|
||||
80 27 99 49
|
||||
32 18 32 43
|
||||
24 45 44 54
|
||||
77 18 34 17
|
||||
71 25 16 57
|
||||
27 38 70 66
|
||||
19 16 21 87
|
||||
66 97 49 97
|
||||
58 24 22 33
|
||||
24 78 18 25
|
||||
85 14 36 41
|
||||
51 44 23 38
|
||||
93 25 85 42
|
50
2024/day05_pseudo-random_clap_dance/tests/challenge3
Normal file
50
2024/day05_pseudo-random_clap_dance/tests/challenge3
Normal file
|
@ -0,0 +1,50 @@
|
|||
1003 1009 1000 3274
|
||||
1008 1002 1000 1008
|
||||
1005 1002 1008 1006
|
||||
1002 1002 1005 1002
|
||||
1001 1003 1009 8363
|
||||
8265 1003 1005 1000
|
||||
1008 1005 7661 1009
|
||||
1001 1003 9870 1004
|
||||
1009 1000 3352 1001
|
||||
1009 1003 1007 1003
|
||||
1007 6665 1008 1005
|
||||
1000 1005 1009 1005
|
||||
1009 8236 1003 1002
|
||||
1002 8094 1000 1004
|
||||
7033 1005 1004 1004
|
||||
1001 5397 1003 1000
|
||||
1006 1001 1003 1003
|
||||
1008 1009 1008 1004
|
||||
1000 1005 1006 1007
|
||||
1003 1003 5343 1003
|
||||
1003 1009 1008 1009
|
||||
1002 1002 1001 1006
|
||||
1000 1000 1004 1009
|
||||
1002 1009 1003 1004
|
||||
1002 1008 8579 1006
|
||||
1002 1009 1000 1005
|
||||
1008 1002 1008 1007
|
||||
4614 1003 1003 1006
|
||||
1008 1005 1005 1000
|
||||
1007 1006 1009 1008
|
||||
1006 1008 1003 1005
|
||||
1003 1006 1001 1001
|
||||
1006 1005 3367 1006
|
||||
1001 1009 1002 1006
|
||||
1009 1007 1000 1006
|
||||
1006 1007 1004 7305
|
||||
1000 1004 8332 1004
|
||||
4128 1005 1009 1000
|
||||
1007 1003 1000 1001
|
||||
1008 1002 1001 1002
|
||||
1003 1005 1001 1003
|
||||
1005 1009 1003 1009
|
||||
1001 1002 1006 1003
|
||||
1002 1002 1008 1003
|
||||
1009 1009 1002 1001
|
||||
1008 1007 1000 1009
|
||||
1002 1001 1004 1001
|
||||
2412 1006 1001 1000
|
||||
7178 1001 1000 1003
|
||||
1008 1004 1005 1008
|
4
2024/day05_pseudo-random_clap_dance/tests/sample1
Normal file
4
2024/day05_pseudo-random_clap_dance/tests/sample1
Normal file
|
@ -0,0 +1,4 @@
|
|||
2 3 4 5
|
||||
3 4 5 2
|
||||
4 5 2 3
|
||||
5 2 3 4
|
2
2024/day05_pseudo-random_clap_dance/tests/sample2
Normal file
2
2024/day05_pseudo-random_clap_dance/tests/sample2
Normal file
|
@ -0,0 +1,2 @@
|
|||
2 3 4 5
|
||||
6 7 8 9
|
2
2024/day05_pseudo-random_clap_dance/tests/sample3
Normal file
2
2024/day05_pseudo-random_clap_dance/tests/sample3
Normal file
|
@ -0,0 +1,2 @@
|
|||
2 3 4 5
|
||||
6 7 8 9
|
Loading…
Add table
Add a link
Reference in a new issue