mirror of
https://github.com/theoludwig/advent_of_code.git
synced 2025-05-18 19:27:51 +02:00
chore: simplify structure + multiple years of advent of code possible
This commit is contained in:
3
advent_2023/README.md
Normal file
3
advent_2023/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Advent of Code 2023
|
||||
|
||||
Source: <https://adventofcode.com/2023>
|
7
advent_2023/puzzle_2023_day_1/Cargo.toml
Normal file
7
advent_2023/puzzle_2023_day_1/Cargo.toml
Normal file
@ -0,0 +1,7 @@
|
||||
[package]
|
||||
name = "puzzle_2023_day_1"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
|
||||
[dependencies]
|
50
advent_2023/puzzle_2023_day_1/README.md
Normal file
50
advent_2023/puzzle_2023_day_1/README.md
Normal file
@ -0,0 +1,50 @@
|
||||
# - Day 1 of 2023: Trebuchet?! -
|
||||
|
||||
Source: <https://adventofcode.com/2023/day/1>
|
||||
|
||||
## Instructions - Part 1
|
||||
|
||||
Something is wrong with global snow production, and you've been selected to take a look. The Elves have even given you a map; on it, they've used stars to mark the top fifty locations that are likely to be having problems.
|
||||
|
||||
You've been doing this long enough to know that to restore snow operations, you need to check all **fifty stars** by December 25th.
|
||||
|
||||
Collect stars by solving puzzles. Two puzzles will be made available on each day in the Advent calendar; the second puzzle is unlocked when you complete the first. Each puzzle grants **one star**. Good luck!
|
||||
|
||||
You try to ask why they can't just use a [weather machine](https://adventofcode.com/2015/day/1) ("not powerful enough") and where they're even sending you ("the sky") and why your map looks mostly blank ("you sure ask a lot of questions") and hang on did you just say the sky ("of course, where do you think snow comes from") when you realize that the Elves are already loading you into a [trebuchet](https://en.wikipedia.org/wiki/Trebuchet) ("please hold still, we need to strap you in").
|
||||
|
||||
As they're making the final adjustments, they discover that their calibration document (your puzzle input) has been **amended** by a very young Elf who was apparently just excited to show off her art skills. Consequently, the Elves are having trouble reading the values on the document.
|
||||
|
||||
The newly-improved calibration document consists of lines of text; each line originally contained a specific **calibration value** that the Elves now need to recover. On each line, the calibration value can be found by combining the **first digit** and the **last digit** (in that order) to form a single **two-digit number**.
|
||||
|
||||
For example:
|
||||
|
||||
```txt
|
||||
1abc2
|
||||
pqr3stu8vwx
|
||||
a1b2c3d4e5f
|
||||
treb7uchet
|
||||
```
|
||||
|
||||
In this example, the calibration values of these four lines are `12`, `38`, `15`, and `77`. Adding these together produces `142`.
|
||||
|
||||
Consider your entire calibration document. **What is the sum of all of the calibration values?**
|
||||
|
||||
## Instructions - Part 2
|
||||
|
||||
Your calculation isn't quite right. It looks like some of the digits are actually **spelled out with letters**: `one`, `two`, `three`, `four`, `five`, `six`, `seven`, `eight`, and `nine` **also** count as valid "digits".
|
||||
|
||||
Equipped with this new information, you now need to find the real first and last digit on each line. For example:
|
||||
|
||||
```txt
|
||||
two1nine
|
||||
eightwothree
|
||||
abcone2threexyz
|
||||
xtwone3four
|
||||
4nineeightseven2
|
||||
zoneight234
|
||||
7pqrstsixteen
|
||||
```
|
||||
|
||||
In this example, the calibration values are `29`, `83`, `13`, `24`, `42`, `14`, and `76`. Adding these together produces `281`.
|
||||
|
||||
**What is the sum of all of the calibration values?**
|
1000
advent_2023/puzzle_2023_day_1/input.txt
Normal file
1000
advent_2023/puzzle_2023_day_1/input.txt
Normal file
File diff suppressed because it is too large
Load Diff
4
advent_2023/puzzle_2023_day_1/input_example_1.txt
Normal file
4
advent_2023/puzzle_2023_day_1/input_example_1.txt
Normal file
@ -0,0 +1,4 @@
|
||||
1abc2
|
||||
pqr3stu8vwx
|
||||
a1b2c3d4e5f
|
||||
treb7uchet
|
7
advent_2023/puzzle_2023_day_1/input_example_2.txt
Normal file
7
advent_2023/puzzle_2023_day_1/input_example_2.txt
Normal file
@ -0,0 +1,7 @@
|
||||
two1nine
|
||||
eightwothree
|
||||
abcone2threexyz
|
||||
xtwone3four
|
||||
4nineeightseven2
|
||||
zoneight234
|
||||
7pqrstsixteen
|
89
advent_2023/puzzle_2023_day_1/src/lib.rs
Normal file
89
advent_2023/puzzle_2023_day_1/src/lib.rs
Normal file
@ -0,0 +1,89 @@
|
||||
pub fn part_1(input: &str) -> usize {
|
||||
input
|
||||
.lines()
|
||||
.map(|line| {
|
||||
let characters_digits = line
|
||||
.chars()
|
||||
.filter(|&character| character.is_ascii_digit())
|
||||
.collect::<Vec<char>>();
|
||||
|
||||
let first_digit = characters_digits.first().unwrap_or(&'0').to_owned();
|
||||
let last_digit = characters_digits.last().unwrap_or(&'0').to_owned();
|
||||
let number = format!("{}{}", first_digit, last_digit);
|
||||
let number: usize = number.parse().expect("Should parse as a `usize`.");
|
||||
number
|
||||
})
|
||||
.sum()
|
||||
}
|
||||
|
||||
pub fn part_2(input: &str) -> usize {
|
||||
let numbers_spelled_out_with_letters = [
|
||||
"one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
|
||||
];
|
||||
|
||||
input
|
||||
.lines()
|
||||
.map(|line| {
|
||||
let mut characters_digits: Vec<char> = vec![];
|
||||
let mut temporary = String::from("");
|
||||
for character in line.chars() {
|
||||
temporary += &character.to_string();
|
||||
|
||||
let mut temporary_spelled_number_index = None;
|
||||
for (index, spelled_number) in numbers_spelled_out_with_letters.iter().enumerate() {
|
||||
if temporary.contains(spelled_number) {
|
||||
temporary_spelled_number_index = Some(index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if let Some(temporary_spelled_number_index) = temporary_spelled_number_index {
|
||||
let number = temporary_spelled_number_index + 1;
|
||||
characters_digits.push(
|
||||
number
|
||||
.to_string()
|
||||
.chars()
|
||||
.next()
|
||||
.expect("Number should be single-character digit."),
|
||||
);
|
||||
temporary = character.to_string();
|
||||
}
|
||||
|
||||
if character.is_ascii_digit() {
|
||||
characters_digits.push(character);
|
||||
temporary = String::from("");
|
||||
}
|
||||
}
|
||||
|
||||
let first_digit = characters_digits.first().unwrap_or(&'0').to_owned();
|
||||
let last_digit = characters_digits.last().unwrap_or(&'0').to_owned();
|
||||
let number = format!("{}{}", first_digit, last_digit);
|
||||
let number: usize = number.parse().expect("Should parse as a `usize`.");
|
||||
number
|
||||
})
|
||||
.sum()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod day_1_tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_part_1_example() {
|
||||
assert_eq!(part_1(include_str!("../input_example_1.txt")), 142);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part_2_example() {
|
||||
assert_eq!(part_2(include_str!("../input_example_2.txt")), 281);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part_1() {
|
||||
assert_eq!(part_1(include_str!("../input.txt")), 55130);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part_2() {
|
||||
assert_eq!(part_2(include_str!("../input.txt")), 54985);
|
||||
}
|
||||
}
|
8
advent_2023/puzzle_2023_day_1/src/main.rs
Normal file
8
advent_2023/puzzle_2023_day_1/src/main.rs
Normal file
@ -0,0 +1,8 @@
|
||||
use puzzle_2023_day_1::{part_1, part_2};
|
||||
|
||||
fn main() {
|
||||
let input = include_str!("../input.txt");
|
||||
println!("- Day 1 of 2023: Trebuchet?! -");
|
||||
println!("Answer Part 1: {}", part_1(input));
|
||||
println!("Answer Part 2: {}", part_2(input));
|
||||
}
|
7
advent_2023/puzzle_2023_day_2/Cargo.toml
Normal file
7
advent_2023/puzzle_2023_day_2/Cargo.toml
Normal file
@ -0,0 +1,7 @@
|
||||
[package]
|
||||
name = "puzzle_2023_day_2"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
|
||||
[dependencies]
|
59
advent_2023/puzzle_2023_day_2/README.md
Normal file
59
advent_2023/puzzle_2023_day_2/README.md
Normal file
@ -0,0 +1,59 @@
|
||||
# - Day 2 of 2023: Cube Conundrum -
|
||||
|
||||
Source: <https://adventofcode.com/2023/day/2>
|
||||
|
||||
## Instructions - Part 1
|
||||
|
||||
You're launched high into the atmosphere! The apex of your trajectory just barely reaches the surface of a large island floating in the sky. You gently land in a fluffy pile of leaves. It's quite cold, but you don't see much snow. An Elf runs over to greet you.
|
||||
|
||||
The Elf explains that you've arrived at **Snow Island** and apologizes for the lack of snow. He'll be happy to explain the situation, but it's a bit of a walk, so you have some time. They don't get many visitors up here; would you like to play a game in the meantime?
|
||||
|
||||
As you walk, the Elf shows you a small bag and some cubes which are either red, green, or blue. Each time you play this game, he will hide a secret number of cubes of each color in the bag, and your goal is to figure out information about the number of cubes.
|
||||
|
||||
To get information, once a bag has been loaded with cubes, the Elf will reach into the bag, grab a handful of random cubes, show them to you, and then put them back in the bag. He'll do this a few times per game.
|
||||
|
||||
You play several games and record the information from each game (your puzzle input). Each game is listed with its ID number (like the `11` in `Game 11: ...`) followed by a semicolon-separated list of subsets of cubes that were revealed from the bag (like `3 red, 5 green, 4 blue`).
|
||||
|
||||
For example, the record of a few games might look like this:
|
||||
|
||||
```txt
|
||||
Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
|
||||
Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue
|
||||
Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red
|
||||
Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red
|
||||
Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green
|
||||
```
|
||||
|
||||
In game 1, three sets of cubes are revealed from the bag (and then put back again). The first set is 3 blue cubes and 4 red cubes; the second set is 1 red cube, 2 green cubes, and 6 blue cubes; the third set is only 2 green cubes.
|
||||
|
||||
The Elf would first like to know which games would have been possible if the bag contained **only 12 red cubes, 13 green cubes, and 14 blue cubes**?
|
||||
|
||||
In the example above, games 1, 2, and 5 would have been **possible** if the bag had been loaded with that configuration. However, game 3 would have been **impossible** because at one point the Elf showed you 20 red cubes at once; similarly, game 4 would also have been **impossible** because the Elf showed you 15 blue cubes at once. If you add up the IDs of the games that would have been possible, you get 8.
|
||||
|
||||
Determine which games would have been possible if the bag had been loaded with only 12 red cubes, 13 green cubes, and 14 blue cubes. **What is the sum of the IDs of those games?**
|
||||
|
||||
## Instructions - Part 2
|
||||
|
||||
The Elf says they've stopped producing snow because they aren't getting any **water**! He isn't sure why the water stopped; however, he can show you how to get to the water source to check it out for yourself. It's just up ahead!
|
||||
|
||||
As you continue your walk, the Elf poses a second question: in each game you played, what is the **fewest number of cubes of each color** that could have been in the bag to make the game possible?
|
||||
|
||||
Again consider the example games from earlier:
|
||||
|
||||
```txt
|
||||
Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
|
||||
Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue
|
||||
Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red
|
||||
Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red
|
||||
Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green
|
||||
```
|
||||
|
||||
- In game 1, the game could have been played with as few as 4 red, 2 green, and 6 blue cubes. If any color had even one fewer cube, the game would have been impossible.
|
||||
- Game 2 could have been played with a minimum of 1 red, 3 green, and 4 blue cubes.
|
||||
- Game 3 must have been played with at least 20 red, 13 green, and 6 blue cubes.
|
||||
- Game 4 required at least 14 red, 3 green, and 15 blue cubes.
|
||||
- Game 5 needed no fewer than 6 red, 3 green, and 2 blue cubes in the bag.
|
||||
|
||||
The **power** of a set of cubes is equal to the numbers of red, green, and blue cubes multiplied together. The power of the minimum set of cubes in game 1 is `48`. In games 2-5 it was `12`, `1560`, `630`, and `36`, respectively. Adding up these five powers produces the sum **`2286`**.
|
||||
|
||||
For each game, find the minimum set of cubes that must have been present. **What is the sum of the power of these sets?**
|
100
advent_2023/puzzle_2023_day_2/input.txt
Normal file
100
advent_2023/puzzle_2023_day_2/input.txt
Normal file
@ -0,0 +1,100 @@
|
||||
Game 1: 5 red, 1 green, 2 blue; 2 green, 8 blue, 6 red; 8 red, 3 blue, 2 green; 6 red, 1 green, 19 blue; 1 red, 17 blue
|
||||
Game 2: 4 red, 5 green, 2 blue; 7 red, 14 green, 3 blue; 2 green, 5 blue, 11 red; 10 blue, 3 green; 9 green, 6 blue, 13 red; 7 red, 5 green, 9 blue
|
||||
Game 3: 9 green, 18 blue, 1 red; 6 red, 10 blue, 5 green; 4 blue, 4 red, 15 green
|
||||
Game 4: 1 red, 13 green; 10 green, 2 red; 3 red, 4 green, 2 blue
|
||||
Game 5: 4 red, 2 green, 1 blue; 4 red, 9 blue; 4 green, 1 red, 6 blue; 3 blue, 2 green, 6 red; 5 red, 4 green, 1 blue
|
||||
Game 6: 6 red, 3 green, 6 blue; 3 green, 5 blue, 12 red; 3 green, 9 blue, 3 red; 13 red, 8 blue
|
||||
Game 7: 3 blue, 1 red; 3 blue, 10 green; 4 green, 5 blue
|
||||
Game 8: 11 green, 4 blue; 4 red, 4 blue, 11 green; 4 green, 3 blue; 1 blue, 6 red, 12 green
|
||||
Game 9: 1 blue, 4 green, 1 red; 5 green, 3 blue; 9 green, 4 blue; 3 blue, 1 red, 10 green; 6 green, 2 blue
|
||||
Game 10: 5 green, 6 red, 7 blue; 7 green, 5 blue, 5 red; 8 red, 6 blue, 8 green; 2 blue, 8 green, 6 red; 6 blue, 8 red, 4 green
|
||||
Game 11: 1 blue, 10 red, 10 green; 11 green, 2 blue, 16 red; 4 blue, 7 red, 14 green
|
||||
Game 12: 8 green, 9 red, 12 blue; 2 green, 4 blue, 7 red; 1 red, 9 blue, 7 green; 8 green, 2 red, 10 blue; 1 green, 5 red, 5 blue; 6 green, 5 red, 1 blue
|
||||
Game 13: 3 green, 1 blue, 6 red; 1 green, 10 red; 1 blue, 15 red, 2 green
|
||||
Game 14: 2 green, 6 blue; 1 green, 2 blue, 2 red; 5 blue, 1 green, 2 red; 4 green, 5 blue, 4 red; 4 red, 5 green, 4 blue; 1 red, 5 green, 6 blue
|
||||
Game 15: 12 green, 7 blue; 19 green; 11 blue, 16 green, 1 red; 1 red, 2 green, 3 blue; 8 blue, 1 red, 19 green; 14 blue, 3 green, 1 red
|
||||
Game 16: 2 green, 13 blue, 3 red; 5 red, 12 blue; 6 blue, 8 red; 4 red, 1 green, 4 blue; 1 green, 15 blue; 4 blue, 2 green, 1 red
|
||||
Game 17: 11 blue, 7 green, 2 red; 12 red, 8 green, 8 blue; 2 red, 6 blue, 6 green
|
||||
Game 18: 1 green, 2 blue; 2 green, 1 blue, 4 red; 3 green, 16 red; 2 red, 3 green
|
||||
Game 19: 11 blue, 3 green, 3 red; 11 blue, 5 green; 3 green, 3 red, 8 blue
|
||||
Game 20: 1 green, 6 blue; 4 blue, 6 green; 1 red, 10 green; 12 green; 5 blue, 1 red, 4 green; 1 green, 5 blue
|
||||
Game 21: 7 green, 3 blue; 1 red, 5 blue, 6 green; 1 red, 11 green; 8 blue, 1 red, 10 green; 1 red, 5 blue, 3 green
|
||||
Game 22: 3 red, 1 blue; 3 green, 1 red, 1 blue; 7 green, 2 blue
|
||||
Game 23: 12 green, 1 red, 2 blue; 10 blue, 1 green, 1 red; 9 blue, 8 green
|
||||
Game 24: 5 blue, 6 green, 6 red; 3 blue, 1 red; 8 blue, 2 green, 12 red; 1 green, 2 blue, 14 red; 2 blue, 5 green, 15 red
|
||||
Game 25: 6 red, 13 green; 1 blue, 1 red, 3 green; 1 blue, 12 red, 10 green
|
||||
Game 26: 16 red, 2 blue, 7 green; 1 blue, 7 green, 8 red; 1 blue, 3 red, 9 green
|
||||
Game 27: 4 blue, 15 green; 6 green, 2 blue, 1 red; 9 blue, 10 green, 4 red; 3 red, 3 green, 6 blue; 11 blue, 7 red, 11 green; 6 red, 5 green, 13 blue
|
||||
Game 28: 10 blue, 8 red, 10 green; 4 blue, 11 red, 6 green; 8 red, 9 green, 10 blue; 4 red, 9 green, 2 blue
|
||||
Game 29: 4 red, 9 green, 7 blue; 10 blue, 6 green, 4 red; 1 green, 2 red, 10 blue; 3 green, 9 blue
|
||||
Game 30: 6 blue, 9 green, 10 red; 6 blue, 4 red; 5 green, 2 blue; 5 green, 2 red, 2 blue; 6 blue, 8 green
|
||||
Game 31: 7 blue; 2 green, 6 blue; 1 red, 9 blue, 5 green
|
||||
Game 32: 8 blue, 2 red, 4 green; 6 red, 2 blue, 1 green; 14 blue, 8 green, 8 red
|
||||
Game 33: 1 green, 1 red, 1 blue; 2 blue, 1 green, 12 red; 1 green, 1 red; 1 blue, 2 red, 1 green; 7 red, 2 green, 2 blue
|
||||
Game 34: 3 blue; 2 blue; 10 red, 1 blue, 1 green; 5 red; 1 green, 1 red, 1 blue; 1 green, 2 red
|
||||
Game 35: 10 green, 1 red, 16 blue; 4 red, 10 blue, 9 green; 1 green, 7 blue, 5 red
|
||||
Game 36: 1 blue, 3 red, 16 green; 1 blue, 3 red, 1 green; 9 green, 3 red, 8 blue; 14 green, 6 blue, 3 red; 3 red, 12 green, 4 blue
|
||||
Game 37: 11 red, 3 blue; 15 red, 8 blue, 6 green; 6 green, 19 red, 11 blue; 1 green, 4 blue, 14 red; 12 blue, 5 red, 8 green; 4 blue, 9 red
|
||||
Game 38: 4 green, 10 blue, 3 red; 1 green, 1 red, 11 blue; 2 red, 12 blue
|
||||
Game 39: 3 green, 1 red, 4 blue; 9 green, 1 red, 18 blue; 4 red, 4 green, 17 blue; 4 red, 10 blue, 14 green
|
||||
Game 40: 5 red, 4 green, 8 blue; 1 green, 9 blue; 9 blue, 3 red, 6 green; 8 red, 9 blue, 9 green
|
||||
Game 41: 1 blue, 9 red, 3 green; 9 red, 10 green, 15 blue; 13 red, 8 green, 8 blue; 19 red, 6 blue, 2 green; 7 green, 5 blue, 12 red
|
||||
Game 42: 15 blue; 1 red, 1 green, 9 blue; 6 blue, 1 red; 1 green, 4 blue
|
||||
Game 43: 1 green, 8 blue, 2 red; 1 red, 1 green, 6 blue; 7 blue; 7 blue, 3 red, 1 green; 2 red, 5 blue
|
||||
Game 44: 7 green, 11 blue, 6 red; 9 green, 8 blue; 4 red, 15 green; 12 green, 14 blue, 8 red
|
||||
Game 45: 4 red, 4 green; 14 green; 4 green, 2 blue; 1 blue, 12 red, 5 green; 3 red, 6 green; 11 red, 1 green
|
||||
Game 46: 2 blue, 1 green, 1 red; 1 blue, 6 green, 1 red; 2 blue, 1 red, 1 green; 5 green
|
||||
Game 47: 1 blue, 1 red; 14 red; 3 green, 2 blue, 17 red; 4 green
|
||||
Game 48: 1 red, 11 green, 2 blue; 1 red, 11 green, 6 blue; 13 green, 1 blue, 3 red; 3 green, 4 red, 6 blue; 12 green, 5 blue, 1 red; 2 red, 4 green, 4 blue
|
||||
Game 49: 5 blue, 3 green; 2 green, 8 blue; 5 blue; 4 green, 5 blue, 1 red; 4 green, 7 blue; 1 green, 3 blue
|
||||
Game 50: 3 red, 5 green, 2 blue; 9 green, 7 red, 4 blue; 3 blue, 6 red, 13 green; 6 blue, 8 red, 9 green
|
||||
Game 51: 2 green, 11 red, 7 blue; 5 blue, 13 red; 1 green, 2 blue, 3 red; 6 blue, 8 red; 11 red, 2 green, 4 blue
|
||||
Game 52: 15 blue, 1 green, 4 red; 4 green, 10 blue, 2 red; 6 red, 18 blue, 1 green
|
||||
Game 53: 2 red, 10 green, 6 blue; 4 green, 3 blue, 3 red; 17 blue, 19 green, 5 red; 6 blue, 6 green, 9 red; 5 blue, 17 green, 7 red
|
||||
Game 54: 9 blue, 8 red, 6 green; 6 red, 8 green; 1 green, 6 blue, 1 red; 5 red, 4 green, 9 blue; 5 blue, 2 green, 5 red
|
||||
Game 55: 8 blue, 8 red, 10 green; 3 red, 4 green, 9 blue; 4 red, 3 green, 7 blue
|
||||
Game 56: 3 red, 6 green, 1 blue; 5 green, 1 blue, 1 red; 1 red, 2 green; 10 green
|
||||
Game 57: 1 green, 4 blue, 12 red; 17 red, 7 blue, 10 green; 17 red, 5 blue, 3 green
|
||||
Game 58: 1 red, 5 green, 14 blue; 5 green, 6 red, 7 blue; 4 blue, 8 green; 3 red, 9 green, 7 blue; 8 blue, 8 green, 6 red; 8 green, 7 blue, 5 red
|
||||
Game 59: 3 green, 5 red; 2 red, 13 green, 1 blue; 19 green, 1 red, 1 blue; 19 green, 1 blue; 18 green, 1 blue, 5 red; 6 red, 9 green
|
||||
Game 60: 5 red, 1 green, 6 blue; 8 red, 6 blue, 14 green; 8 green, 8 red, 3 blue; 2 blue, 5 green, 3 red; 4 blue, 1 red, 14 green
|
||||
Game 61: 7 red, 4 blue, 2 green; 2 green, 8 red, 9 blue; 5 blue, 2 green, 8 red; 8 red, 1 green, 8 blue
|
||||
Game 62: 6 red, 3 blue; 1 blue, 2 red, 2 green; 3 red, 1 blue
|
||||
Game 63: 2 red, 1 blue, 2 green; 1 blue, 1 green; 2 green, 4 red; 3 green, 2 red; 2 green
|
||||
Game 64: 5 green, 6 blue, 7 red; 2 red, 5 green, 8 blue; 7 green, 9 blue, 1 red; 4 green, 5 blue; 19 blue, 5 green, 13 red
|
||||
Game 65: 3 red, 1 blue, 4 green; 5 green, 3 blue; 9 green, 1 red, 10 blue
|
||||
Game 66: 6 red, 13 green, 2 blue; 2 blue, 5 red, 9 green; 18 red; 2 green, 1 blue, 1 red; 19 red, 10 green; 1 blue, 15 green, 13 red
|
||||
Game 67: 8 blue, 3 red; 1 red, 12 green, 7 blue; 4 red, 6 blue, 5 green; 11 green, 10 blue, 7 red; 5 red, 9 green, 14 blue
|
||||
Game 68: 1 red, 3 green; 10 blue, 1 red, 3 green; 1 green, 17 blue; 16 blue; 6 blue
|
||||
Game 69: 11 green, 5 blue, 8 red; 2 red, 5 green, 1 blue; 10 green, 2 blue; 11 green, 7 red, 4 blue
|
||||
Game 70: 2 green, 1 blue, 13 red; 16 green, 20 red, 4 blue; 10 red
|
||||
Game 71: 10 blue, 6 green, 7 red; 5 red, 5 green, 2 blue; 7 green, 4 red, 5 blue; 1 red, 8 blue; 5 red, 1 blue, 8 green; 5 blue, 1 red, 5 green
|
||||
Game 72: 2 red, 4 green; 2 green, 2 red, 1 blue; 3 blue, 3 green, 2 red; 2 green
|
||||
Game 73: 5 red, 19 blue; 12 blue, 4 green, 16 red; 14 red, 11 blue, 1 green
|
||||
Game 74: 2 red, 1 green, 9 blue; 5 blue, 1 green, 2 red; 2 green, 1 red, 13 blue; 2 green, 1 red, 3 blue
|
||||
Game 75: 7 blue, 1 red, 18 green; 17 green, 8 red, 13 blue; 15 blue, 4 red
|
||||
Game 76: 1 green, 12 red, 13 blue; 5 green, 11 blue, 12 red; 10 red, 1 green; 10 red, 2 blue; 5 red, 2 green; 2 green, 17 blue, 3 red
|
||||
Game 77: 2 blue, 1 red, 1 green; 7 red; 7 red, 3 blue, 2 green; 10 green, 1 red; 3 red, 7 blue, 6 green
|
||||
Game 78: 10 red, 2 blue, 2 green; 1 blue, 6 red, 4 green; 12 red, 8 green; 6 green, 8 red, 7 blue; 11 green, 5 blue, 6 red
|
||||
Game 79: 7 green, 5 red; 6 blue, 2 green, 15 red; 9 blue, 2 red, 12 green; 1 blue, 4 red, 10 green; 4 blue, 12 green, 11 red; 5 green, 3 red, 5 blue
|
||||
Game 80: 1 green, 13 blue, 2 red; 2 red, 1 green, 13 blue; 7 blue, 8 red
|
||||
Game 81: 1 green, 2 red, 11 blue; 5 red, 3 blue; 1 green, 1 red; 14 red, 1 green
|
||||
Game 82: 12 red, 3 blue, 8 green; 15 red, 9 blue, 8 green; 6 blue, 13 red, 8 green
|
||||
Game 83: 4 blue, 6 green, 3 red; 7 red, 2 blue, 9 green; 6 green, 3 red
|
||||
Game 84: 4 green; 3 red, 3 blue; 4 red, 1 blue, 2 green; 1 red, 5 green, 5 blue; 1 red, 5 blue, 3 green
|
||||
Game 85: 3 red, 4 blue, 15 green; 9 green; 2 red, 4 blue, 6 green; 1 red, 4 green, 7 blue; 3 red, 10 green, 9 blue; 1 red, 13 green, 3 blue
|
||||
Game 86: 8 red, 6 blue; 3 blue, 3 green, 15 red; 12 red, 6 green, 13 blue; 15 red, 6 green, 10 blue
|
||||
Game 87: 4 red, 4 blue; 6 red, 2 blue; 5 blue, 3 green; 4 blue, 2 red
|
||||
Game 88: 4 blue, 7 green; 2 blue, 7 green; 6 green, 4 blue; 1 red, 1 blue, 2 green; 11 green, 3 blue
|
||||
Game 89: 1 blue, 12 green, 11 red; 3 red, 7 blue, 1 green; 7 green, 8 red; 6 blue, 2 green, 3 red; 7 red, 8 green; 11 blue, 5 red, 12 green
|
||||
Game 90: 1 green, 12 red, 17 blue; 14 red, 17 blue, 9 green; 6 green, 9 red, 11 blue
|
||||
Game 91: 3 green, 14 blue; 2 blue, 2 green, 6 red; 1 red, 11 blue, 1 green; 3 green, 4 red, 20 blue; 6 red, 2 green, 3 blue; 10 blue, 12 red
|
||||
Game 92: 6 blue, 7 red; 2 blue, 4 red, 1 green; 4 red, 1 green, 3 blue; 2 red, 5 blue; 8 red, 6 blue; 1 green, 2 blue, 1 red
|
||||
Game 93: 4 blue, 1 green, 4 red; 8 red, 4 green, 4 blue; 2 blue, 9 red; 1 blue, 4 red; 4 blue, 2 green, 11 red
|
||||
Game 94: 5 blue, 1 green, 7 red; 1 green, 11 blue, 1 red; 1 green, 15 blue, 4 red
|
||||
Game 95: 1 red, 3 blue; 1 red, 1 green, 8 blue; 3 red, 1 green, 3 blue; 3 red, 6 blue; 6 blue
|
||||
Game 96: 4 green, 1 blue; 7 green, 3 red; 2 blue, 9 red, 16 green; 3 blue, 4 red, 11 green
|
||||
Game 97: 6 green, 8 blue; 1 blue, 1 green; 3 green, 4 blue; 8 blue, 5 green, 2 red
|
||||
Game 98: 18 blue, 6 green; 11 green, 3 blue, 7 red; 18 blue, 3 red, 7 green; 5 red, 5 green; 8 blue, 2 green, 11 red
|
||||
Game 99: 3 red, 2 green, 3 blue; 1 red, 4 green, 1 blue; 2 green, 18 red; 15 red, 1 blue; 2 blue, 9 red, 2 green; 17 red, 3 blue, 4 green
|
||||
Game 100: 9 blue, 8 red, 16 green; 3 red, 7 green, 8 blue; 1 green, 3 red, 12 blue; 3 green, 14 blue
|
5
advent_2023/puzzle_2023_day_2/input_example_1.txt
Normal file
5
advent_2023/puzzle_2023_day_2/input_example_1.txt
Normal file
@ -0,0 +1,5 @@
|
||||
Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
|
||||
Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue
|
||||
Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red
|
||||
Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red
|
||||
Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green
|
198
advent_2023/puzzle_2023_day_2/src/lib.rs
Normal file
198
advent_2023/puzzle_2023_day_2/src/lib.rs
Normal file
@ -0,0 +1,198 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
const NUMBER_OF_RED_CUBES_IN_THE_BAG: usize = 12;
|
||||
const NUMBER_OF_GREEN_CUBES_IN_THE_BAG: usize = 13;
|
||||
const NUMBER_OF_BLUE_CUBES_IN_THE_BAG: usize = 14;
|
||||
|
||||
#[derive(Debug, Default, PartialEq)]
|
||||
pub struct NumberOfCubesOfEachColor {
|
||||
pub red: usize,
|
||||
pub green: usize,
|
||||
pub blue: usize,
|
||||
}
|
||||
|
||||
impl FromStr for NumberOfCubesOfEachColor {
|
||||
type Err = &'static str;
|
||||
|
||||
/// Parses a string `string` to return a value of [`NumberOfCubesOfEachColor`]
|
||||
///
|
||||
/// If parsing succeeds, return the value inside [`Ok`], otherwise
|
||||
/// when the string is ill-formatted return an error specific to the
|
||||
/// inside [`Err`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::str::FromStr;
|
||||
/// use puzzle_2023_day_2::NumberOfCubesOfEachColor;
|
||||
///
|
||||
/// let string = "3 blue, 4 red";
|
||||
/// let expected_result = NumberOfCubesOfEachColor {
|
||||
/// red: 4,
|
||||
/// green: 0,
|
||||
/// blue: 3,
|
||||
/// };
|
||||
/// let actual_result = NumberOfCubesOfEachColor::from_str(string).unwrap();
|
||||
///
|
||||
/// assert_eq!(actual_result, expected_result);
|
||||
/// ```
|
||||
fn from_str(string: &str) -> Result<Self, Self::Err> {
|
||||
let mut result = NumberOfCubesOfEachColor::default();
|
||||
let subsets = string.split(", ");
|
||||
for subset in subsets {
|
||||
let mut subset_splitted = subset.split_ascii_whitespace();
|
||||
let number: usize = subset_splitted.next().unwrap_or("0").parse().unwrap_or(0);
|
||||
let color = subset_splitted.next();
|
||||
if let Some(color) = color {
|
||||
match color {
|
||||
"red" => result.red = number,
|
||||
"blue" => result.blue = number,
|
||||
"green" => result.green = number,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, PartialEq)]
|
||||
pub struct Game {
|
||||
pub id: usize,
|
||||
pub subsets_of_cubes: Vec<NumberOfCubesOfEachColor>,
|
||||
}
|
||||
|
||||
impl FromStr for Game {
|
||||
type Err = &'static str;
|
||||
|
||||
/// Parses a string `string` to return a value of [`Game`]
|
||||
///
|
||||
/// If parsing succeeds, return the value inside [`Ok`], otherwise
|
||||
/// when the string is ill-formatted return an error specific to the
|
||||
/// inside [`Err`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::str::FromStr;
|
||||
/// use puzzle_2023_day_2::{Game, NumberOfCubesOfEachColor};
|
||||
///
|
||||
/// let string = "Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green";
|
||||
/// let expected_result = Game {
|
||||
/// id: 1,
|
||||
/// subsets_of_cubes: vec![
|
||||
/// NumberOfCubesOfEachColor {
|
||||
/// red: 4,
|
||||
/// green: 0,
|
||||
/// blue: 3,
|
||||
/// },
|
||||
/// NumberOfCubesOfEachColor {
|
||||
/// red: 1,
|
||||
/// green: 2,
|
||||
/// blue: 6,
|
||||
/// },
|
||||
/// NumberOfCubesOfEachColor {
|
||||
/// red: 0,
|
||||
/// green: 2,
|
||||
/// blue: 0,
|
||||
/// },
|
||||
/// ],
|
||||
/// };
|
||||
/// let actual_result = Game::from_str(string).unwrap();
|
||||
///
|
||||
/// assert_eq!(actual_result, expected_result);
|
||||
/// ```
|
||||
fn from_str(string: &str) -> Result<Self, Self::Err> {
|
||||
let mut result = Game::default();
|
||||
let mut parts = string.split(": ");
|
||||
result.id = parts
|
||||
.next()
|
||||
.unwrap_or("Game 1")
|
||||
.strip_prefix("Game ")
|
||||
.unwrap_or("1")
|
||||
.parse()
|
||||
.unwrap_or(1);
|
||||
result.subsets_of_cubes = parts
|
||||
.next()
|
||||
.unwrap_or("0 red, 0 green, 0 blue")
|
||||
.split("; ")
|
||||
.map(|string| {
|
||||
NumberOfCubesOfEachColor::from_str(string)
|
||||
.unwrap_or(NumberOfCubesOfEachColor::default())
|
||||
})
|
||||
.collect::<Vec<NumberOfCubesOfEachColor>>();
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn part_1(input: &str) -> usize {
|
||||
input
|
||||
.lines()
|
||||
.map(|line| Game::from_str(line).unwrap_or_default())
|
||||
.filter(|game| {
|
||||
game.subsets_of_cubes
|
||||
.iter()
|
||||
.all(|number_of_cubes_of_each_color| {
|
||||
number_of_cubes_of_each_color.red <= NUMBER_OF_RED_CUBES_IN_THE_BAG
|
||||
&& number_of_cubes_of_each_color.blue <= NUMBER_OF_BLUE_CUBES_IN_THE_BAG
|
||||
&& number_of_cubes_of_each_color.green <= NUMBER_OF_GREEN_CUBES_IN_THE_BAG
|
||||
})
|
||||
})
|
||||
.map(|game| game.id)
|
||||
.sum::<usize>()
|
||||
}
|
||||
|
||||
pub fn part_2(input: &str) -> usize {
|
||||
input
|
||||
.lines()
|
||||
.map(|line| {
|
||||
let game = Game::from_str(line).unwrap_or_default();
|
||||
let mut maximum_number_of_cubes_of_each_color = NumberOfCubesOfEachColor {
|
||||
red: 1,
|
||||
green: 1,
|
||||
blue: 1,
|
||||
};
|
||||
for number_of_cubes_of_each_color in game.subsets_of_cubes {
|
||||
if number_of_cubes_of_each_color.red > maximum_number_of_cubes_of_each_color.red {
|
||||
maximum_number_of_cubes_of_each_color.red = number_of_cubes_of_each_color.red;
|
||||
}
|
||||
if number_of_cubes_of_each_color.green > maximum_number_of_cubes_of_each_color.green
|
||||
{
|
||||
maximum_number_of_cubes_of_each_color.green =
|
||||
number_of_cubes_of_each_color.green;
|
||||
}
|
||||
if number_of_cubes_of_each_color.blue > maximum_number_of_cubes_of_each_color.blue {
|
||||
maximum_number_of_cubes_of_each_color.blue = number_of_cubes_of_each_color.blue;
|
||||
}
|
||||
}
|
||||
maximum_number_of_cubes_of_each_color.red
|
||||
* maximum_number_of_cubes_of_each_color.green
|
||||
* maximum_number_of_cubes_of_each_color.blue
|
||||
})
|
||||
.sum::<usize>()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod puzzle_2023_day_2_tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_part_1_example() {
|
||||
assert_eq!(part_1(include_str!("../input_example_1.txt")), 8);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part_2_example() {
|
||||
assert_eq!(part_2(include_str!("../input_example_1.txt")), 2286);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part_1() {
|
||||
assert_eq!(part_1(include_str!("../input.txt")), 2617);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part_2() {
|
||||
assert_eq!(part_2(include_str!("../input.txt")), 59795);
|
||||
}
|
||||
}
|
8
advent_2023/puzzle_2023_day_2/src/main.rs
Normal file
8
advent_2023/puzzle_2023_day_2/src/main.rs
Normal file
@ -0,0 +1,8 @@
|
||||
use puzzle_2023_day_2::{part_1, part_2};
|
||||
|
||||
fn main() {
|
||||
let input = include_str!("../input.txt");
|
||||
println!("- Day 2 of 2023: Cube Conundrum -");
|
||||
println!("Answer Part 1: {}", part_1(input));
|
||||
println!("Answer Part 2: {}", part_2(input));
|
||||
}
|
7
advent_2023/puzzle_2023_day_3/Cargo.toml
Normal file
7
advent_2023/puzzle_2023_day_3/Cargo.toml
Normal file
@ -0,0 +1,7 @@
|
||||
[package]
|
||||
name = "puzzle_2023_day_3"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
|
||||
[dependencies]
|
67
advent_2023/puzzle_2023_day_3/README.md
Normal file
67
advent_2023/puzzle_2023_day_3/README.md
Normal file
@ -0,0 +1,67 @@
|
||||
# - Day 3 of 2023: Gear Ratios -
|
||||
|
||||
Source: <https://adventofcode.com/2023/day/3>
|
||||
|
||||
## Instructions - Part 1
|
||||
|
||||
You and the Elf eventually reach a [gondola lift](https://en.wikipedia.org/wiki/Gondola_lift) station; he says the gondola lift will take you up to the **water source**, but this is as far as he can bring you. You go inside.
|
||||
|
||||
It doesn't take long to find the gondolas, but there seems to be a problem: they're not moving.
|
||||
|
||||
"Aaah!"
|
||||
|
||||
You turn around to see a slightly-greasy Elf with a wrench and a look of surprise. "Sorry, I wasn't expecting anyone! The gondola lift isn't working right now; it'll still be a while before I can fix it." You offer to help.
|
||||
|
||||
The engineer explains that an engine part seems to be missing from the engine, but nobody can figure out which one. If you can **add up all the part numbers** in the engine schematic, it should be easy to work out which part is missing.
|
||||
|
||||
The engine schematic (your puzzle input) consists of a visual representation of the engine. There are lots of numbers and symbols you don't really understand, but apparently **any number adjacent to a symbol**, even diagonally, is a "part number" and should be included in your sum. (Periods (`.`) do not count as a symbol.)
|
||||
|
||||
Here is an example engine schematic:
|
||||
|
||||
```txt
|
||||
467..114..
|
||||
...*......
|
||||
..35..633.
|
||||
......#...
|
||||
617*......
|
||||
.....+.58.
|
||||
..592.....
|
||||
......755.
|
||||
...$.*....
|
||||
.664.598..
|
||||
```
|
||||
|
||||
In this schematic, two numbers are **not** part numbers because they are not adjacent to a symbol: `114` (top right) and `58` (middle right). Every other number is adjacent to a symbol and so **is** a part number; their sum is **`4361`**.
|
||||
|
||||
Of course, the actual engine schematic is much larger. **What is the sum of all of the part numbers in the engine schematic?**
|
||||
|
||||
## Instructions - Part 2
|
||||
|
||||
The engineer finds the missing part and installs it in the engine! As the engine springs to life, you jump in the closest gondola, finally ready to ascend to the water source.
|
||||
|
||||
You don't seem to be going very fast, though. Maybe something is still wrong? Fortunately, the gondola has a phone labeled "help", so you pick it up and the engineer answers.
|
||||
|
||||
Before you can explain the situation, she suggests that you look out the window. There stands the engineer, holding a phone in one hand and waving with the other. You're going so slowly that you haven't even left the station. You exit the gondola.
|
||||
|
||||
The missing part wasn't the only issue - one of the gears in the engine is wrong. A **gear** is any `*` symbol that is adjacent to **exactly two part numbers**. Its **gear ratio** is the result of multiplying those two numbers together.
|
||||
|
||||
This time, you need to find the gear ratio of every gear and add them all up so that the engineer can figure out which gear needs to be replaced.
|
||||
|
||||
Consider the same engine schematic again:
|
||||
|
||||
```txt
|
||||
467..114..
|
||||
...*......
|
||||
..35..633.
|
||||
......#...
|
||||
617*......
|
||||
.....+.58.
|
||||
..592.....
|
||||
......755.
|
||||
...$.*....
|
||||
.664.598..
|
||||
```
|
||||
|
||||
In this schematic, there are **two** gears. The first is in the top left; it has part numbers `467` and `35`, so its gear ratio is `16345`. The second gear is in the lower right; its gear ratio is `451490`. (The `*` adjacent to `617` is **not** a gear because it is only adjacent to one part number.) Adding up all of the gear ratios produces **`467835`**.
|
||||
|
||||
**What is the sum of all of the gear ratios in your engine schematic?**
|
140
advent_2023/puzzle_2023_day_3/input.txt
Normal file
140
advent_2023/puzzle_2023_day_3/input.txt
Normal file
@ -0,0 +1,140 @@
|
||||
...........................775.651...............887....79...946...921...493.....942..942.....151....155....................................
|
||||
......240...................*.....-......................$..*...................*.......%.....+....................956.549.*290.......834...
|
||||
.485...+............437......906......%..608.805.725..72.....242....745..61......440................................*..*.........515...*....
|
||||
..........917.......&....146........790.....*......*....*..........*.....*...............207*......................796..116......../...924..
|
||||
722...323.-................./...410.............72..748.442............384.708...............849..%............................470..........
|
||||
.....*..........................*.....271..691....-...............4*...........388.................448......&........*....848&......751.....
|
||||
....370..$....639.748.......*...467....*.....*........921*909.....................*...32.....................165..452.30....................
|
||||
........984....*.....*...782........711.....50.172...............61&..........415.803.*.........524.......................203.......106*643.
|
||||
...............57..433.........390....................&../.............*122...........674.........*.........................................
|
||||
379..................../.........*........908..477...305.876..*..............297.415*......+.......94........../.....@378.......226..56*....
|
||||
...*..-......82.......167...936.17..958...=....*...............196......+......*.......-...380.992.............989.........29......*....301.
|
||||
..124..317.....*....................*..........839.......................191.882......231.........+......976.................+......469.....
|
||||
............643................*........778............541........655..............*............*........./............*.................515
|
||||
.....&............498#...&....726.774..............111....*378..................723.221.......473............752....523.638.......789...*...
|
||||
.....353................518..........-.........../....*...............*88.........................*..@280..=..-....................-..297...
|
||||
...........279...........................*816.....286.975.&319.....614......694.......799.......503.......861...569.............+...........
|
||||
..474........*.228..............308......................................................*............207........................838..408...
|
||||
...........226./....*................82.........................268/......814.........640.............../..489........719..=..........*.....
|
||||
....83............88.544....250.......=...87..............199.........115*....................................*...377.@.....643........658..
|
||||
........-...651.............*................&..............................*379.....411...686.397............202.*....../........217.......
|
||||
.....781.......*897......630................330.....117.961..........61..543.....#...*.....*.......323.............996.603.......*..........
|
||||
.......................................................*........473....*.....739.184.511..........+......43.833.................953...@.....
|
||||
....110......@471...........*464....@.347......779................/.....205.*.......................681.....@.........................694...
|
||||
.........................203......158.-....310./...449...726*982.............437.....+....259...................185......940*702............
|
||||
.....465....*.......747....................*..........*...............................238..&......./..963...755....*........................
|
||||
.....*....687..104..%.........645........959..497..732........988........733.....12...........417.176....$..........176.323....657..........
|
||||
...566........*...........938*......418......*............925....*28..............-.156........*................................*..#........
|
||||
.............933.......................*....988........../............................*........813.................868*674...375...839......
|
||||
.....................804.......464..452...................................47......324.789..........692*288..................................
|
||||
...959...........792....*10.....=......................*455.77...827.99....*.........................................166.......8...586......
|
||||
.....*...607......*..............................12.764......*.......*..905....590.236...#.677...823......972..204............*......*......
|
||||
..661....*........776....938..901.............@.*.........$...216...995...........*....382..*....#....546*.....#...........564........707...
|
||||
......755................*.......*698......315..291.......964................-.......=.....865........................521........150........
|
||||
........................323............./............973.........*35..........318.....204...........546..+667....214%..*..............973...
|
||||
........143......&725...........619....149..............*235..650.........604..........................*..............195..............*....
|
||||
................................*.................................926...................@240......+...433..302..672.........977....149..335.
|
||||
.......880.......&...............301.512.$.....876......331.897...#..............#...............464......+...........938.........*.........
|
||||
......@....942...603....&....879..........117..........*.....*.............562..905....377*862..............*56.........%........352..*165..
|
||||
.726......*..........239....*.....915..............@...661...905..............*...................466....223.................730............
|
||||
....*......97..839.......308.........*....115....512..........................497.392.....563........=...............448...........462*884..
|
||||
....122.........*...471*...........52...&..=...................=..................@.........*...............................531.............
|
||||
.........*..522...&.....274...........116......*572...........907..........................161..670@..@....................=........57*.....
|
||||
.........28.*.....606.......................925...............................908...86...............78..............712.....813*......16...
|
||||
....549.....512....................................825.....797.......224..660*........@.425*656.........=536..256.......*........599........
|
||||
...*.............963..................842..704.............+....425..*..............................102.......$....565.179..774/........576.
|
||||
...................*..........................*..............=...*....922........50...262....%............603......*........................
|
||||
.......636.......349...&...224...$............899.........983..319.............#........&...663....*575..%.......95.....383*................
|
||||
......=...............928........218................84.............964.........953..+...........212.........................857.............
|
||||
............................179.......68......................&....*.................787.............92&.72....455..969...........846..40...
|
||||
.993=..../..........110.407*...........%.............164..#....306.215...................552..............*....=...#.....69.602...#...*.....
|
||||
......322..........#...........561..............968..*....913............%..........@586...=.330...........166.............*........863.....
|
||||
............810...........157.*....557.....30.*.....774...................968.601*...........*....491..........557.....83*..................
|
||||
.......*368.*.......842...*...435.-...........65.-................................680.....913....#.......793....*.........87.262....34.-....
|
||||
....896......875.....*...........................581.957..758............$................................@..981..............#......*.844..
|
||||
..................957...150.......503................@....*......89....59......261..........653....................................372......
|
||||
...731...-129..+........*........-......................718.713....*.......197..*......30......+...476............872.......................
|
||||
....*...........671....917.......................800.&......=....197..763....*...96......#.........*......%......*..........739......290....
|
||||
.....234..............................814*251....../.755.............../...375.....................309.914..816...877..=.......$......$.....
|
||||
.........543.378.....74.%608.25...755..........237..............834..................431..................../..........585..................
|
||||
....408...&...*..............*................*.............214*.....................*.........89.475*.......................@..939..824....
|
||||
...*..........526..........713..&.....132...899..108.75..#..................521....428....97../.......603.....248.........878...&...*.......
|
||||
....383...............873......1....................*....850....862....%......#.=................533.........*.......................863....
|
||||
.............852.........*................578%....................*..492.........905.145.927........*........437.107.....@....29............
|
||||
......604.......#./531.179..&........56.........921..233.......943......................*..........174...........*.......271.*...32.........
|
||||
........*..619.............588......*............*...*..............918*837.....120.128......508...........536...............558...*638.....
|
||||
523....794...-....................451..544....648..365.778.....@.............@.....*............$..%414...*............453#.................
|
||||
..................&......124*...........*...............*...259........696...424...........*...............322..534................*519.....
|
||||
........201*.30...474........567.526..363............%.963......287+......*.........939.964.....994.............*.....-........287.......657
|
||||
........................709*......=.........854...527................50..591...859....%..........*....196.......188..395..157...*...........
|
||||
.281*....878................354.......*221...*............308....309...*.........$..@...72#......577.........................*...734.....481
|
||||
.....9....*.............658........235......767..12..548...=...#.......585..830....609........................603.130.....884...........*...
|
||||
........324........@...*........................*....*........628.............................................*...$...........=......658....
|
||||
..................139.206....$.....768*........986....311..........967...15...174....100-.....7$..............962....=.........561..........
|
||||
......521.....154.............318......622...................-.............%...@.................856.......60.........24..481.......520.772.
|
||||
.825..#.......*.............................180.............228.11.....173.......128......428.........405.+...68...........=..882......*....
|
||||
....*.......657...........27....798*460...................@............-..............31.*.....840...........*................@.............
|
||||
.965...931............974...*...........................798.................455*.........856......*...809...97..934.740$..570...............
|
||||
........*..511.$427....../..652..-297............296........$........552..........884..................*........%........*........128.......
|
||||
..........-..........207............................=....641.........+..........-..*....43..........329................990...........*......
|
||||
.10...................=..11....&............................./.143........875..732....&.......&............................349.....265...858
|
||||
...*......222....495%...*...618..322.......%.........116...833....*........*.........776....288....760.........-............-...............
|
||||
....291......*..........453.........*...811...398..............515........365..445....................*.....961.........433......743...$....
|
||||
.............33..................543.........@..........................=...../.....793*...........266..............668...........#.....804.
|
||||
................701....................17*.................449*741.....961......814..........................*245......*...809*.............
|
||||
.......206......*....668..728$............529..........*93........................-...833.713..............69.......292........157...224*...
|
||||
..........*585...969............810..522............866..............254.....570........*....*.....588..................+113.......-.....752
|
||||
................................/......../......257.............119...-..844...*..979..442....169.....=.259......+.............752..401.....
|
||||
...726...967........&.234.................326.....*....590*636...*............130.../.........................933.....652*439...*...........
|
||||
.....*......*12..332...-...........500#..........944..............747.......$.....................203....513.......................%864.....
|
||||
....389.&....................*...............938.......893....970.........864........538.755&.258..*........#...............717.96......+...
|
||||
.65.....180...&.............864.....169.........*................*...390............*.........*....904.........................*...354...478
|
||||
....620......472.726.931...............*.......150../.......@....960....................*928.812...........................428......*.......
|
||||
...*................*.................463..........323.....478..........964..........175.........324%........=827......66.......193..303....
|
||||
313.......................@...705.214.....174&........................-.....271........................818...............*.........+........
|
||||
........171+..830...328..158...*..%..................17....721.....568......../...........949.............*.............608.....90......570.
|
||||
....327..........*....*.......44......................*..................193-.......67.................970......966.503................#....
|
||||
669*..........386..306....+............105............443...........................*........490..130...........*....$..........$62.........
|
||||
......454...............&..954...38....*..........229....................643......388.671....@.......*...8......506....66*148.........$.....
|
||||
......*................259.........*.................*756.......596.........*........................638..+....................%....854.....
|
||||
...700......895..............................757................*.........847..............630*612..................854..606....38..........
|
||||
...............*.....93.....573......274........*...952..336...................562..................+...637............*.*..................
|
||||
945........../.814..=..........*....*...........38..=............-....&........*..................118......*.........745..855.........367...
|
||||
......676..688..................604..153...............671......513...690....891.%.....101.728..........767......28...................../...
|
||||
.........=.......700..222.443............114.....................................458...../....#...................*.........=...............
|
||||
...........660.%...&.....*.....98.232.......*............308.......650..267/..........$............................417.....806.....502......
|
||||
.......276*....500............@.............63.......621*.....520...-........913.....225.........620.597...709*632.............663*.........
|
||||
...................232...149............65.......................&........................228.....%.....-................467............800.
|
||||
..........118........+....*....@.........-.458...737.....-247.........425................/..................574......424*.........421..*....
|
||||
......158.-....*........564.599......128......*...#..........................419.............764*156.............................*......996.
|
||||
............577.563.....................*...777.......................508..............*827............................*465.....306.........
|
||||
.........................*..............848......996*......688....154...*.......%...780......51...410......357.148..856.....................
|
||||
...648.............835.713....*...609.......................&........*..885....494..........*..........661....*.............................
|
||||
...-.....477./693..*........938.....*./...........642..149......465.502......$............=.523.........#.......892................=824.....
|
||||
....................296...........44...707..........+.....*...................462......476........@...............*..........388............
|
||||
.....58...321..............127................................446...............................965....446........114.........*.............
|
||||
.........*........951...3....*.................623.263.............=.-....122..........................=....519*...........692.......%313...
|
||||
........943.......*......$....990.......795..../......*..135.....815.483....*..937*.............................634..............771........
|
||||
............460....757.....@......511/..*............564..-..............340.......109.206.......%785..148...21....................*....&...
|
||||
.47.........&...............102........265......555..................182......12*.........................*...%.................788..200....
|
||||
.../............=..................#82..........$.......207.............*863.....751.........251.....641.702.......141..640.................
|
||||
..........23..902.......174...............*.............=.....314...........................*..........*.....*667...........*...............
|
||||
.........*...............*.......*766..842.35.......243..........*......@..................57..435....501.285.............964.....*.........
|
||||
..165...100.@512.........292.......................%......79..@...726....341.511*.............*...................573..........602.74.......
|
||||
...*..................................596#...&...............769........................314.397..&31................%..855..................
|
||||
...6.....673....................898..........836.......827.......+.....-..............................133*766..........*..............290...
|
||||
..........*.........799........*.........629.......634........%.188.103.......594......464.799*295.............895...930.........-....$.....
|
||||
.....908..504.......*......603..800..936...*......*.........768..........973...*.......*...............904*16.*................358..........
|
||||
.....@............825..%......&.........*...963.294.74...........%........*....102...967...-343.................#..................94.698...
|
||||
.810...................968..............429...........*....950..313..482..397...................33.........@..297..198...114.......*...*....
|
||||
.....-............................554..................................-.......245.$...............991..282.........-...*....161..894..78...
|
||||
..705.....177.....*..872@.285........*.../813.........235....729..........*287..*...472.788.645........................144..................
|
||||
.............*..984.......*........722............496*..........*990....79......715........*............456...................812..470......
|
||||
............518......@.....950.........712..............981...........................238....579.533........373.466...615/......$.....*907..
|
||||
..716..907.......761..471..............*......../...........823..+............978*......=.....*.....#......&....*...........................
|
||||
....*...............*........990.331...46....871...........*.....447.723...@...............594...............801......................#757..
|
||||
...312...*.........211..........*.................90.860...970.........*...375...........*.....-....*779.........&..........................
|
||||
.......692..............602.............................*.............595.............841...166..327......-444....154.......................
|
||||
..............$....316..=.............+978.843........42....135/.+332.........454.........................................707.../......295..
|
||||
.........$....743..../.......-................+........................*990..................343......#.....*...............*....684........
|
||||
......651.....................644....................887.812........187.................783........749...928.291...........131...........293
|
10
advent_2023/puzzle_2023_day_3/input_example_1.txt
Normal file
10
advent_2023/puzzle_2023_day_3/input_example_1.txt
Normal file
@ -0,0 +1,10 @@
|
||||
467..114..
|
||||
...*......
|
||||
..35..633.
|
||||
......#...
|
||||
617*......
|
||||
.....+.58.
|
||||
..592.....
|
||||
......755.
|
||||
...$.*....
|
||||
.664.598..
|
226
advent_2023/puzzle_2023_day_3/src/lib.rs
Normal file
226
advent_2023/puzzle_2023_day_3/src/lib.rs
Normal file
@ -0,0 +1,226 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Debug, PartialEq, Default, Clone, Copy)]
|
||||
pub struct GearPosition {
|
||||
pub index_line: usize,
|
||||
pub index_character: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Default, Clone, Copy)]
|
||||
pub struct NumberPosition {
|
||||
pub index_start: usize,
|
||||
pub index_end: usize,
|
||||
pub value: usize,
|
||||
pub gear_position: GearPosition,
|
||||
}
|
||||
|
||||
pub fn get_numbers_positions_from_line(line: &str) -> Vec<NumberPosition> {
|
||||
let mut result = vec![];
|
||||
let mut number_string = String::from("");
|
||||
let mut index_start = 0;
|
||||
let mut index_end = 0;
|
||||
for (index_character, character) in line.chars().enumerate() {
|
||||
if character.is_ascii_digit() {
|
||||
if number_string.is_empty() {
|
||||
index_start = index_character;
|
||||
}
|
||||
index_end = index_character;
|
||||
number_string += &character.to_string();
|
||||
} else if !number_string.is_empty() {
|
||||
let value: usize = number_string.parse().expect("Should parse as a `usize`");
|
||||
result.push(NumberPosition {
|
||||
index_start,
|
||||
index_end,
|
||||
value,
|
||||
gear_position: GearPosition::default(),
|
||||
});
|
||||
number_string = String::from("");
|
||||
index_start = 0;
|
||||
index_end = 0;
|
||||
}
|
||||
}
|
||||
if !number_string.is_empty() {
|
||||
let value: usize = number_string.parse().expect("Should parse as a `usize`");
|
||||
result.push(NumberPosition {
|
||||
index_start,
|
||||
index_end,
|
||||
value,
|
||||
gear_position: GearPosition::default(),
|
||||
});
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
pub fn is_symbol(character: char) -> bool {
|
||||
!character.is_ascii_digit() && character != '.'
|
||||
}
|
||||
|
||||
pub fn is_gear_symbol(character: char) -> bool {
|
||||
character == '*'
|
||||
}
|
||||
|
||||
pub fn part_1(input: &str) -> usize {
|
||||
let lines = input.lines().collect::<Vec<&str>>();
|
||||
lines
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index_line, &line)| {
|
||||
get_numbers_positions_from_line(line)
|
||||
.iter()
|
||||
.filter(|&number_position| {
|
||||
let index_start = number_position.index_start.saturating_sub(1);
|
||||
let index_end = if number_position.index_end + 1 >= line.len() {
|
||||
line.len().saturating_sub(1)
|
||||
} else {
|
||||
number_position.index_end + 1
|
||||
};
|
||||
|
||||
let has_symbol_on_the_left =
|
||||
line.chars().nth(index_start).is_some_and(is_symbol);
|
||||
let has_symbol_on_the_right =
|
||||
line.chars().nth(index_end).is_some_and(is_symbol);
|
||||
|
||||
let has_symbol_on_the_top = lines
|
||||
.get(index_line.saturating_sub(1))
|
||||
.is_some_and(|&line| {
|
||||
line.get(index_start..=index_end)
|
||||
.is_some_and(|value| value.chars().any(is_symbol))
|
||||
});
|
||||
|
||||
let has_symbol_on_the_bottom = lines.get(index_line + 1).is_some_and(|&line| {
|
||||
line.get(index_start..=index_end)
|
||||
.is_some_and(|value| value.chars().any(is_symbol))
|
||||
});
|
||||
|
||||
has_symbol_on_the_left
|
||||
|| has_symbol_on_the_right
|
||||
|| has_symbol_on_the_top
|
||||
|| has_symbol_on_the_bottom
|
||||
})
|
||||
.map(|number_position| number_position.value)
|
||||
.sum::<usize>()
|
||||
})
|
||||
.sum()
|
||||
}
|
||||
|
||||
pub fn part_2(input: &str) -> usize {
|
||||
let lines = input.lines().collect::<Vec<&str>>();
|
||||
let mut number_positions = vec![];
|
||||
|
||||
lines.iter().enumerate().for_each(|(index_line, &line)| {
|
||||
get_numbers_positions_from_line(line)
|
||||
.iter()
|
||||
.for_each(|&number_position| {
|
||||
let index_start = number_position.index_start.saturating_sub(1);
|
||||
let index_end = if number_position.index_end + 1 >= line.len() {
|
||||
line.len().saturating_sub(1)
|
||||
} else {
|
||||
number_position.index_end + 1
|
||||
};
|
||||
|
||||
let has_symbol_on_the_left =
|
||||
line.chars().nth(index_start).is_some_and(is_gear_symbol);
|
||||
if has_symbol_on_the_left {
|
||||
let mut number_position = number_position.to_owned();
|
||||
number_position.gear_position.index_line = index_line;
|
||||
number_position.gear_position.index_character = index_start;
|
||||
number_positions.push(number_position);
|
||||
}
|
||||
|
||||
let has_symbol_on_the_right =
|
||||
line.chars().nth(index_end).is_some_and(is_gear_symbol);
|
||||
if has_symbol_on_the_right {
|
||||
let mut number_position = number_position.to_owned();
|
||||
number_position.gear_position.index_line = index_line;
|
||||
number_position.gear_position.index_character = index_end;
|
||||
number_positions.push(number_position);
|
||||
}
|
||||
|
||||
let index_character_top =
|
||||
lines.get(index_line.saturating_sub(1)).and_then(|&line| {
|
||||
line.get(index_start..=index_end)
|
||||
.and_then(|value| value.chars().position(is_gear_symbol))
|
||||
});
|
||||
if let Some(index_character_top) = index_character_top {
|
||||
let mut number_position = number_position.to_owned();
|
||||
number_position.gear_position.index_line = index_line.saturating_sub(1);
|
||||
number_position.gear_position.index_character =
|
||||
index_character_top + index_start;
|
||||
number_positions.push(number_position);
|
||||
}
|
||||
|
||||
let index_character_bottom = lines.get(index_line + 1).and_then(|&line| {
|
||||
line.get(index_start..=index_end)
|
||||
.and_then(|value| value.chars().position(is_gear_symbol))
|
||||
});
|
||||
if let Some(index_character_bottom) = index_character_bottom {
|
||||
let mut number_position = number_position.to_owned();
|
||||
number_position.gear_position.index_line = index_line + 1;
|
||||
number_position.gear_position.index_character =
|
||||
index_character_bottom + index_start;
|
||||
number_positions.push(number_position);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Key: "index_line-index_character"
|
||||
// Value: usize
|
||||
let mut gear_positions: HashMap<String, Vec<usize>> = HashMap::new();
|
||||
|
||||
number_positions.iter().for_each(|&number_position| {
|
||||
let key = format!(
|
||||
"{}-{}",
|
||||
number_position.gear_position.index_line, number_position.gear_position.index_character,
|
||||
);
|
||||
match gear_positions.get_mut(&key) {
|
||||
Some(gear_positions) => {
|
||||
gear_positions.push(number_position.value);
|
||||
}
|
||||
None => {
|
||||
gear_positions.insert(key, vec![number_position.value]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let mut result = 0;
|
||||
|
||||
for (_, value) in gear_positions.iter() {
|
||||
if value.len() != 2 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let first_number = value.first();
|
||||
let second_number = value.last();
|
||||
|
||||
if let (Some(first_number), Some(second_number)) = (first_number, second_number) {
|
||||
result += first_number * second_number;
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod puzzle_2023_day_3_tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_part_1_example() {
|
||||
assert_eq!(part_1(include_str!("../input_example_1.txt")), 4361);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part_2_example() {
|
||||
assert_eq!(part_2(include_str!("../input_example_1.txt")), 467835);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part_1() {
|
||||
assert_eq!(part_1(include_str!("../input.txt")), 553079);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part_2() {
|
||||
assert_eq!(part_2(include_str!("../input.txt")), 84363105);
|
||||
}
|
||||
}
|
8
advent_2023/puzzle_2023_day_3/src/main.rs
Normal file
8
advent_2023/puzzle_2023_day_3/src/main.rs
Normal file
@ -0,0 +1,8 @@
|
||||
use puzzle_2023_day_3::{part_1, part_2};
|
||||
|
||||
fn main() {
|
||||
let input = include_str!("../input.txt");
|
||||
println!("- Day 3 of 2023: Gear Ratios -");
|
||||
println!("Answer Part 1: {}", part_1(input));
|
||||
println!("Answer Part 2: {}", part_2(input));
|
||||
}
|
7
advent_2023/puzzle_2023_day_4/Cargo.toml
Normal file
7
advent_2023/puzzle_2023_day_4/Cargo.toml
Normal file
@ -0,0 +1,7 @@
|
||||
[package]
|
||||
name = "puzzle_2023_day_4"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
|
||||
[dependencies]
|
75
advent_2023/puzzle_2023_day_4/README.md
Normal file
75
advent_2023/puzzle_2023_day_4/README.md
Normal file
@ -0,0 +1,75 @@
|
||||
# - Day 4 of 2023: Scratchcards -
|
||||
|
||||
Source: <https://adventofcode.com/2023/day/4>
|
||||
|
||||
## Instructions - Part 1
|
||||
|
||||
The gondola takes you up. Strangely, though, the ground doesn't seem to be coming with you; you're not climbing a mountain. As the circle of Snow Island recedes below you, an entire new landmass suddenly appears above you! The gondola carries you to the surface of the new island and lurches into the station.
|
||||
|
||||
As you exit the gondola, the first thing you notice is that the air here is much **warmer** than it was on Snow Island. It's also quite **humid**. Is this where the water source is?
|
||||
|
||||
The next thing you notice is an Elf sitting on the floor across the station in what seems to be a pile of colorful square cards.
|
||||
|
||||
"Oh! Hello!" The Elf excitedly runs over to you. "How may I be of service?" You ask about water sources.
|
||||
|
||||
"I'm not sure; I just operate the gondola lift. That does sound like something we'd have, though - this is **Island Island**, after all! I bet the **gardener** would know. He's on a different island, though - er, the small kind surrounded by water, not the floating kind. We really need to come up with a better naming scheme. Tell you what: if you can help me with something quick, I'll let you **borrow my boat** and you can go visit the gardener. I got all these [scratchcards](https://en.wikipedia.org/wiki/Scratchcard) as a gift, but I can't figure out what I've won."
|
||||
|
||||
The Elf leads you over to the pile of colorful cards. There, you discover dozens of scratchcards, all with their opaque covering already scratched off. Picking one up, it looks like each card has two lists of numbers separated by a vertical bar (`|`): a list of **winning numbers** and then a list of **numbers you have**. You organize the information into a table (your puzzle input).
|
||||
|
||||
As far as the Elf has been able to figure out, you have to figure out which of the **numbers you have** appear in the list of **winning numbers**. The first match makes the card worth **one point** and each match after the first **doubles** the point value of that card.
|
||||
|
||||
For example:
|
||||
|
||||
```txt
|
||||
Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53
|
||||
Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19
|
||||
Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1
|
||||
Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83
|
||||
Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
|
||||
Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11
|
||||
```
|
||||
|
||||
In the above example, card 1 has five winning numbers (`41`, `48`, `83`, `86`, and `17`) and eight numbers you have (`83`, `86`, `6`, `31`, `17`, `9`, `48`, and `53`). Of the numbers you have, four of them (`48`, `83`, `17`, and `86`) are winning numbers! That means card 1 is worth **`8`** points (1 for the first match, then doubled three times for each of the three matches after the first).
|
||||
|
||||
- Card 2 has two winning numbers (`32` and `61`), so it is worth **`2`** points.
|
||||
- Card 3 has two winning numbers (`1` and `21`), so it is worth **`2`** points.
|
||||
- Card 4 has one winning number (`84`), so it is worth **`1`** point.
|
||||
- Card 5 has no winning numbers, so it is worth no points.
|
||||
- Card 6 has no winning numbers, so it is worth no points.
|
||||
|
||||
So, in this example, the Elf's pile of scratchcards is worth **`13`** points.
|
||||
|
||||
Take a seat in the large pile of colorful cards. **How many points are they worth in total?**
|
||||
|
||||
## Instructions - Part 2
|
||||
|
||||
Just as you're about to report your findings to the Elf, one of you realizes that the rules have actually been printed on the back of every card this whole time.
|
||||
|
||||
There's no such thing as "points". Instead, scratchcards only cause you to **win more scratchcards** equal to the number of winning numbers you have.
|
||||
|
||||
Specifically, you win **copies** of the scratchcards below the winning card equal to the number of matches. So, if card 10 were to have 5 matching numbers, you would win one copy each of cards 11, 12, 13, 14, and 15.
|
||||
|
||||
Copies of scratchcards are scored like normal scratchcards and have the **same card number** as the card they copied. So, if you win a copy of card 10 and it has 5 matching numbers, it would then win a copy of the same cards that the original card 10 won: cards 11, 12, 13, 14, and 15. This process repeats until none of the copies cause you to win any more cards. (Cards will never make you copy a card past the end of the table.)
|
||||
|
||||
This time, the above example goes differently:
|
||||
|
||||
```txt
|
||||
Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53
|
||||
Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19
|
||||
Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1
|
||||
Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83
|
||||
Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
|
||||
Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11
|
||||
```
|
||||
|
||||
- Card 1 has four matching numbers, so you win one copy each of the next four cards: cards 2, 3, 4, and 5.
|
||||
- Your original card 2 has two matching numbers, so you win one copy each of cards 3 and 4.
|
||||
- Your copy of card 2 also wins one copy each of cards 3 and 4.
|
||||
- Your four instances of card 3 (one original and three copies) have two matching numbers, so you win **four** copies each of cards 4 and 5.
|
||||
- Your eight instances of card 4 (one original and seven copies) have one matching number, so you win **eight** copies of card 5.
|
||||
- Your fourteen instances of card 5 (one original and thirteen copies) have no matching numbers and win no more cards.
|
||||
- Your one instance of card 6 (one original) has no matching numbers and wins no more cards.
|
||||
|
||||
Once all of the originals and copies have been processed, you end up with 1 instance of card 1, **`2`** instances of card 2, **`4`** instances of card 3, **`8`** instances of card 4, **`14`** instances of card 5, and **`1`** instance of card 6. In total, this example pile of scratchcards causes you to ultimately have **`30`** scratchcards!
|
||||
|
||||
Process all of the original and copied scratchcards until no more scratchcards are won. Including the original set of scratchcards, **how many total scratchcards do you end up with**?
|
208
advent_2023/puzzle_2023_day_4/input.txt
Normal file
208
advent_2023/puzzle_2023_day_4/input.txt
Normal file
@ -0,0 +1,208 @@
|
||||
Card 1: 57 76 72 11 8 28 15 38 54 46 | 77 87 71 98 40 7 84 43 61 64 5 50 19 83 79 99 36 47 4 95 30 44 37 55 26
|
||||
Card 2: 44 69 14 83 54 48 21 6 20 26 | 80 26 86 3 9 4 62 34 15 87 60 88 90 29 65 46 92 73 24 12 40 10 99 37 74
|
||||
Card 3: 15 60 63 84 20 93 36 39 17 19 | 68 80 17 91 20 84 69 72 15 39 5 61 74 99 60 85 19 45 24 79 53 36 7 63 93
|
||||
Card 4: 22 74 83 58 88 46 7 52 84 5 | 75 20 95 8 37 56 31 42 73 43 40 48 4 28 99 45 90 63 81 93 68 50 46 30 7
|
||||
Card 5: 4 97 41 50 32 26 68 84 5 11 | 91 70 87 4 88 13 48 51 32 34 38 82 86 11 1 50 40 43 28 5 61 89 84 41 37
|
||||
Card 6: 79 97 39 26 57 69 38 87 60 44 | 22 92 80 38 27 66 54 2 9 62 3 4 71 99 24 97 14 7 93 28 53 50 77 68 73
|
||||
Card 7: 73 91 51 23 90 67 19 81 50 12 | 4 76 97 64 19 85 31 3 74 12 23 60 20 68 52 39 43 65 37 63 40 59 99 80 6
|
||||
Card 8: 23 64 38 82 68 79 49 56 5 76 | 68 25 64 30 40 52 16 53 95 96 85 9 4 7 26 80 62 67 73 35 32 44 90 69 93
|
||||
Card 9: 75 87 69 31 8 11 89 49 95 24 | 35 26 68 69 42 66 37 77 25 45 75 72 38 50 27 24 32 46 11 10 14 95 62 7 86
|
||||
Card 10: 37 25 47 36 57 81 44 6 79 98 | 67 34 86 70 39 97 80 69 27 17 7 50 99 84 45 32 49 53 15 95 19 18 47 37 41
|
||||
Card 11: 87 98 16 76 21 53 8 42 40 75 | 21 7 89 85 65 30 32 19 68 22 64 82 48 62 39 46 4 57 77 18 55 24 34 29 67
|
||||
Card 12: 60 11 44 35 9 56 93 91 15 32 | 31 45 37 63 26 12 15 14 48 92 81 1 97 65 29 95 57 77 99 93 27 25 58 66 61
|
||||
Card 13: 25 75 5 60 47 83 8 37 2 43 | 52 30 68 13 1 92 89 63 78 57 87 75 28 82 59 46 33 3 65 41 47 69 21 2 96
|
||||
Card 14: 64 44 89 88 1 38 20 99 9 81 | 71 68 91 21 92 75 49 22 27 12 9 26 57 13 66 45 40 37 16 4 44 90 98 85 61
|
||||
Card 15: 16 56 91 62 12 83 25 3 70 61 | 81 55 73 96 13 7 67 99 88 90 87 48 83 35 19 97 9 31 20 49 38 44 41 45 5
|
||||
Card 16: 78 68 81 18 76 41 88 45 24 87 | 59 84 67 36 33 57 42 32 11 74 65 31 54 46 72 39 98 40 16 49 79 19 3 44 22
|
||||
Card 17: 84 11 48 66 54 86 28 4 45 23 | 4 54 42 62 81 8 92 45 47 66 84 48 18 72 28 86 23 34 3 24 73 82 96 11 59
|
||||
Card 18: 46 40 41 22 75 92 68 10 52 3 | 84 73 9 22 7 19 3 65 32 6 99 77 97 63 62 59 57 17 8 68 91 28 39 4 41
|
||||
Card 19: 19 57 22 85 75 69 50 62 65 61 | 35 24 50 47 74 97 61 27 66 57 77 75 22 30 70 41 62 69 85 58 81 65 19 91 63
|
||||
Card 20: 18 13 96 41 20 44 62 97 57 52 | 18 59 96 40 23 58 20 57 41 97 44 62 75 54 85 78 94 52 64 34 37 45 84 13 53
|
||||
Card 21: 34 3 13 85 81 19 37 97 29 91 | 9 97 52 3 35 48 24 34 17 50 21 71 57 36 94 82 19 4 14 83 98 37 80 91 59
|
||||
Card 22: 18 14 95 74 23 71 31 83 51 57 | 94 14 63 18 16 73 57 31 5 23 51 69 85 45 70 35 74 49 79 27 40 95 83 13 71
|
||||
Card 23: 54 12 52 31 58 93 9 45 27 64 | 48 54 93 12 44 64 56 83 35 94 33 4 58 89 8 45 27 1 86 90 52 31 19 57 9
|
||||
Card 24: 56 75 17 67 59 37 76 94 25 36 | 24 14 56 53 82 35 92 96 17 34 25 1 16 86 41 95 64 45 38 63 31 18 80 33 66
|
||||
Card 25: 32 22 47 24 80 92 96 67 5 26 | 22 81 87 47 26 96 92 60 57 64 66 16 5 83 67 49 32 39 71 80 40 63 99 75 53
|
||||
Card 26: 62 36 66 9 3 71 75 67 29 61 | 9 31 66 82 29 41 67 71 38 36 28 76 14 75 69 61 99 57 62 88 70 95 63 10 59
|
||||
Card 27: 46 38 59 90 1 65 16 80 76 34 | 70 15 49 31 27 71 54 46 76 1 8 77 93 2 90 39 14 67 62 16 78 56 68 9 58
|
||||
Card 28: 47 85 54 21 37 14 44 73 12 51 | 78 70 14 77 98 88 25 49 9 79 58 23 52 2 43 17 12 84 59 51 56 89 47 48 6
|
||||
Card 29: 74 37 60 11 56 21 87 44 33 46 | 80 61 34 54 9 3 45 7 55 13 98 84 10 19 14 8 90 81 50 69 31 12 38 29 78
|
||||
Card 30: 29 20 44 62 79 34 52 15 49 48 | 17 84 34 1 33 9 23 55 94 10 95 69 42 79 78 44 51 82 20 25 81 29 15 13 32
|
||||
Card 31: 88 41 38 98 34 40 92 36 25 50 | 33 54 18 53 46 69 8 22 25 36 51 34 42 92 85 45 40 60 84 27 97 39 10 70 41
|
||||
Card 32: 5 28 85 29 95 37 60 34 24 16 | 74 8 48 73 34 65 66 56 64 85 78 17 39 67 92 30 75 22 95 12 29 24 6 2 51
|
||||
Card 33: 71 31 99 53 62 80 65 32 13 23 | 87 20 55 24 42 19 67 77 37 89 32 83 44 9 60 46 47 36 49 35 92 10 82 2 81
|
||||
Card 34: 78 61 12 81 96 82 7 30 80 32 | 62 8 56 89 11 12 39 31 17 18 79 51 30 92 48 5 45 78 41 44 77 98 71 67 73
|
||||
Card 35: 59 35 63 76 51 8 53 70 24 97 | 20 36 31 17 77 26 34 15 41 39 61 24 35 46 80 74 2 71 5 91 16 11 55 87 4
|
||||
Card 36: 46 51 79 66 57 52 21 11 75 33 | 88 64 74 99 22 39 42 11 14 65 1 56 86 8 26 16 72 13 55 20 60 40 19 85 58
|
||||
Card 37: 83 88 1 19 95 30 38 43 14 51 | 98 20 22 55 13 58 93 21 68 11 76 70 71 35 44 90 52 53 75 17 96 27 49 31 26
|
||||
Card 38: 87 49 43 19 16 34 88 66 67 9 | 70 46 63 58 7 53 96 1 59 35 91 85 18 21 93 68 90 73 11 92 60 61 98 38 15
|
||||
Card 39: 24 68 25 61 54 63 30 37 21 73 | 50 84 48 10 81 5 62 28 92 66 96 6 20 83 78 88 31 89 12 71 60 8 34 70 90
|
||||
Card 40: 18 72 44 15 3 19 69 63 73 57 | 14 3 52 76 71 12 50 13 86 21 55 31 27 29 43 47 90 75 9 97 6 32 96 37 18
|
||||
Card 41: 81 66 49 20 86 80 4 55 93 44 | 87 81 7 47 25 85 80 51 76 27 78 10 16 50 33 66 13 64 35 18 44 63 29 92 48
|
||||
Card 42: 27 21 14 28 69 89 94 9 19 46 | 92 13 27 99 96 19 43 54 4 14 45 16 44 83 24 61 2 28 5 90 49 51 63 64 73
|
||||
Card 43: 34 49 58 85 23 88 84 78 89 55 | 72 45 73 23 75 52 84 78 46 55 58 71 98 5 56 91 49 39 88 70 42 59 89 85 34
|
||||
Card 44: 18 69 46 58 73 59 56 23 12 40 | 71 23 87 93 21 84 10 79 47 92 91 13 52 1 32 78 59 95 72 55 97 56 43 61 75
|
||||
Card 45: 33 47 58 69 57 1 82 6 61 48 | 48 97 4 1 67 66 82 12 6 29 21 96 90 33 57 28 47 69 74 27 2 32 58 61 9
|
||||
Card 46: 42 54 98 50 36 86 27 66 29 60 | 32 23 40 62 38 91 43 98 29 85 18 30 66 28 81 35 68 61 11 27 50 22 41 46 42
|
||||
Card 47: 1 31 87 71 53 17 5 93 84 56 | 48 26 14 47 34 44 18 93 17 88 61 8 95 74 53 50 56 80 62 84 99 49 87 52 1
|
||||
Card 48: 40 75 79 29 64 57 33 49 95 68 | 7 39 63 79 89 10 23 40 22 86 92 13 57 29 9 19 90 87 58 12 77 16 75 4 91
|
||||
Card 49: 4 45 87 47 71 35 9 2 81 77 | 93 33 49 75 11 34 62 39 83 40 55 17 84 43 80 60 46 7 18 56 48 66 95 57 74
|
||||
Card 50: 88 42 2 30 24 89 15 93 16 45 | 93 45 72 68 30 28 17 82 64 91 29 98 14 24 88 70 55 48 58 10 42 83 66 2 77
|
||||
Card 51: 91 96 87 48 6 73 95 55 71 89 | 94 49 84 33 82 9 21 32 25 46 65 15 86 83 66 11 37 1 14 61 92 36 35 45 27
|
||||
Card 52: 48 3 94 56 41 13 34 8 96 25 | 40 88 46 14 68 25 75 66 87 55 64 78 92 43 19 97 53 90 83 59 69 31 84 95 13
|
||||
Card 53: 13 45 61 92 91 32 49 58 43 36 | 44 70 55 28 2 6 35 79 24 54 82 95 52 73 75 84 34 57 21 23 33 22 80 88 1
|
||||
Card 54: 61 52 20 8 73 54 83 60 29 6 | 74 40 27 46 81 75 3 42 47 69 22 59 58 49 90 63 57 50 79 70 82 5 53 91 39
|
||||
Card 55: 41 51 64 55 57 44 26 70 62 34 | 24 82 49 39 56 84 31 27 86 77 22 6 73 72 99 47 60 18 53 68 42 19 66 9 50
|
||||
Card 56: 30 89 82 17 72 46 98 5 54 58 | 4 86 18 15 84 41 16 63 44 91 12 31 66 96 94 87 49 59 67 64 80 33 5 11 40
|
||||
Card 57: 39 80 17 47 15 96 69 50 46 24 | 5 83 16 52 57 27 98 43 78 1 66 90 19 6 58 3 49 94 85 62 44 54 75 14 9
|
||||
Card 58: 42 77 37 13 74 40 31 92 36 46 | 16 74 80 59 51 31 95 85 40 93 23 15 32 18 46 97 36 13 79 10 37 99 77 25 92
|
||||
Card 59: 39 1 78 7 57 46 91 26 12 94 | 46 13 26 83 21 1 67 78 50 94 8 12 39 61 86 91 35 29 32 72 30 97 57 16 7
|
||||
Card 60: 62 32 18 51 40 96 93 36 80 84 | 42 93 65 8 2 52 84 70 11 1 92 21 80 99 18 14 17 47 56 90 49 67 19 48 97
|
||||
Card 61: 6 83 74 89 44 73 39 42 47 88 | 72 74 42 21 88 77 18 6 83 85 49 73 5 39 78 44 64 10 47 14 89 53 98 13 92
|
||||
Card 62: 91 86 35 23 30 28 77 88 56 41 | 54 26 90 20 96 78 14 5 47 98 31 55 74 83 33 15 67 92 19 40 73 72 52 81 94
|
||||
Card 63: 87 91 78 92 33 71 80 47 13 65 | 32 33 56 55 2 4 61 71 91 97 93 78 83 74 3 13 47 70 54 80 65 60 49 26 96
|
||||
Card 64: 70 61 63 52 32 35 85 46 54 4 | 42 54 32 84 56 46 29 61 63 78 4 36 80 86 26 17 3 87 48 21 85 52 35 70 22
|
||||
Card 65: 83 95 45 97 49 67 13 92 1 90 | 68 75 20 96 6 33 73 1 50 14 17 66 34 78 54 84 92 9 64 61 85 88 72 42 12
|
||||
Card 66: 1 7 99 75 17 21 48 70 30 13 | 70 80 45 89 75 7 21 99 20 54 42 46 67 85 61 17 1 16 30 92 77 48 13 68 90
|
||||
Card 67: 69 55 20 91 47 31 33 75 56 39 | 69 31 62 20 58 1 93 48 35 55 47 13 56 60 50 75 25 37 91 81 10 39 32 33 54
|
||||
Card 68: 14 97 54 28 73 64 81 32 47 17 | 86 48 88 25 47 65 22 81 28 95 41 14 27 26 46 64 79 61 45 96 32 9 21 54 53
|
||||
Card 69: 6 21 89 82 75 48 46 56 68 47 | 48 32 74 30 13 56 93 90 68 33 41 58 21 47 8 17 65 6 89 97 75 82 46 26 59
|
||||
Card 70: 35 48 78 92 64 30 88 77 76 10 | 76 33 48 67 78 64 24 69 36 14 77 85 30 73 53 91 3 35 96 88 43 84 10 95 92
|
||||
Card 71: 59 78 57 66 15 18 41 83 70 35 | 7 62 19 30 48 97 89 71 40 27 11 63 60 47 23 86 10 84 4 75 80 69 61 67 25
|
||||
Card 72: 80 82 46 70 10 14 55 49 62 9 | 31 76 62 17 8 49 19 50 85 72 77 75 42 48 33 60 54 45 12 91 20 92 15 3 25
|
||||
Card 73: 38 83 96 47 42 99 13 82 36 85 | 74 86 59 16 49 45 81 61 44 39 3 91 9 26 35 25 55 21 19 41 90 70 10 29 4
|
||||
Card 74: 92 36 96 65 24 6 98 13 33 86 | 17 83 30 5 46 51 54 81 44 99 33 56 45 14 57 34 8 16 77 48 40 94 82 73 75
|
||||
Card 75: 14 21 57 66 33 8 90 7 4 28 | 91 61 3 84 89 45 60 56 51 10 58 20 96 78 73 93 97 44 19 15 12 90 35 87 42
|
||||
Card 76: 37 91 60 44 43 3 40 33 95 51 | 24 39 81 1 46 83 97 88 87 6 67 40 22 96 93 2 71 33 29 15 41 16 89 21 68
|
||||
Card 77: 91 84 43 9 87 96 37 64 41 31 | 35 13 30 43 78 32 23 85 84 19 88 68 10 63 27 77 61 50 41 94 54 12 97 86 33
|
||||
Card 78: 9 78 53 16 80 56 91 3 62 70 | 85 64 21 88 51 16 15 4 69 30 13 1 70 17 52 23 90 5 24 50 19 81 41 67 12
|
||||
Card 79: 59 28 42 51 66 58 63 9 24 47 | 69 95 26 36 14 62 13 20 35 25 34 74 40 41 9 39 45 77 5 10 55 96 22 81 49
|
||||
Card 80: 72 83 73 23 85 2 53 22 3 43 | 14 50 67 63 19 76 39 60 31 33 62 92 29 12 49 75 69 78 44 8 96 95 34 65 20
|
||||
Card 81: 2 46 29 50 65 57 55 83 74 12 | 4 70 97 54 68 99 81 5 84 10 73 61 88 66 27 8 56 33 79 47 85 49 17 16 34
|
||||
Card 82: 37 30 10 3 8 34 44 24 57 13 | 42 17 25 65 48 71 4 64 51 83 75 27 72 96 45 18 11 15 70 53 91 14 12 87 59
|
||||
Card 83: 82 81 15 4 54 96 74 72 37 70 | 37 78 72 25 4 66 81 97 6 83 43 96 61 44 15 71 40 54 27 70 82 98 74 93 7
|
||||
Card 84: 97 52 96 23 80 53 57 83 16 62 | 5 31 89 91 84 33 52 83 76 23 64 67 10 97 29 63 96 58 74 53 62 57 80 81 92
|
||||
Card 85: 53 33 76 24 81 68 51 47 40 89 | 70 38 51 50 85 57 89 40 30 61 1 24 54 75 32 33 96 19 14 53 76 20 7 99 47
|
||||
Card 86: 19 96 52 18 15 53 82 16 86 13 | 69 27 32 85 87 30 33 83 11 47 3 21 68 70 42 61 46 2 64 65 44 1 97 48 74
|
||||
Card 87: 18 40 55 62 39 95 60 11 76 46 | 82 81 22 46 92 80 62 91 12 40 76 60 69 78 17 18 11 93 56 39 37 88 3 64 95
|
||||
Card 88: 72 65 91 61 57 4 49 24 45 31 | 28 49 91 31 19 59 65 36 34 87 72 24 60 89 17 12 57 30 75 32 63 8 21 4 25
|
||||
Card 89: 18 24 64 43 33 56 6 67 8 16 | 40 21 27 52 3 23 65 89 16 7 96 31 48 73 33 37 18 99 12 50 74 26 71 84 8
|
||||
Card 90: 75 3 92 35 12 26 49 59 60 55 | 65 58 39 73 3 56 11 44 4 47 68 24 86 10 61 6 72 13 82 42 29 93 97 77 8
|
||||
Card 91: 78 40 49 75 60 15 59 7 31 93 | 71 9 48 10 69 29 65 40 21 57 68 87 12 35 81 70 30 94 36 97 51 43 8 82 5
|
||||
Card 92: 3 53 23 43 15 4 98 11 67 29 | 35 3 93 87 83 60 5 92 1 90 67 23 78 98 20 37 81 71 31 82 95 47 53 75 21
|
||||
Card 93: 20 61 6 36 52 77 59 16 18 81 | 66 29 4 87 61 92 78 30 68 69 67 57 88 83 71 54 24 21 13 56 84 35 60 86 53
|
||||
Card 94: 25 52 87 17 94 41 23 30 72 53 | 93 62 38 77 31 24 21 36 75 64 45 83 56 39 90 29 55 43 71 54 42 98 76 74 28
|
||||
Card 95: 84 66 91 8 26 82 85 96 31 36 | 93 51 40 98 69 74 53 67 86 23 77 41 62 89 64 34 5 26 50 73 42 43 13 19 91
|
||||
Card 96: 7 6 90 39 14 73 66 81 33 67 | 63 26 1 58 29 10 3 13 94 9 85 68 69 19 53 96 90 36 49 99 31 74 54 45 77
|
||||
Card 97: 66 64 77 7 88 18 40 24 10 63 | 28 22 62 41 30 21 19 12 50 43 46 42 56 6 60 36 95 82 97 2 73 55 38 53 8
|
||||
Card 98: 48 10 16 15 93 40 37 72 57 88 | 10 59 38 19 97 23 51 40 35 31 56 54 21 27 28 81 15 67 12 57 37 65 9 22 74
|
||||
Card 99: 45 57 7 23 86 82 15 14 75 35 | 55 19 84 37 82 39 15 77 42 52 44 18 75 45 7 69 67 23 86 6 89 14 43 57 35
|
||||
Card 100: 68 85 29 69 17 44 19 56 92 8 | 8 4 20 98 36 39 78 79 72 81 51 22 13 47 2 77 30 28 64 41 89 57 50 34 16
|
||||
Card 101: 6 91 90 43 85 1 19 2 28 9 | 63 25 2 9 83 85 87 43 91 6 62 64 74 28 19 82 92 29 36 1 71 90 60 99 84
|
||||
Card 102: 20 72 12 52 58 28 30 76 42 55 | 30 47 59 29 20 93 90 33 76 58 78 28 52 83 48 72 54 42 67 17 55 12 36 2 37
|
||||
Card 103: 58 18 40 8 73 69 22 74 26 63 | 61 40 63 41 82 87 22 8 34 6 73 95 69 44 45 85 62 74 27 28 26 4 96 58 15
|
||||
Card 104: 42 71 57 39 22 79 43 80 90 37 | 43 37 76 94 40 67 4 55 74 21 7 42 3 39 28 12 80 57 32 61 95 58 64 90 13
|
||||
Card 105: 60 9 50 14 56 11 54 33 77 84 | 77 81 17 99 11 84 70 60 5 43 83 19 80 13 54 33 50 30 87 31 9 4 37 56 14
|
||||
Card 106: 79 87 86 96 1 8 63 43 39 91 | 6 2 75 63 67 38 11 96 90 91 87 97 86 9 21 77 43 36 79 8 40 85 39 1 13
|
||||
Card 107: 97 83 21 39 74 64 79 70 77 14 | 85 32 55 18 24 14 79 57 51 12 4 21 23 70 26 83 39 66 63 1 64 73 30 8 77
|
||||
Card 108: 18 41 11 62 88 38 73 4 47 36 | 82 53 41 92 65 15 42 47 85 96 26 43 58 62 11 3 54 55 89 63 30 17 20 93 2
|
||||
Card 109: 28 34 55 39 22 99 98 89 86 54 | 58 76 46 70 91 43 2 79 16 25 89 42 78 52 12 56 44 69 80 85 84 99 62 19 15
|
||||
Card 110: 32 38 50 41 8 97 84 60 92 40 | 43 7 51 76 69 38 92 34 41 71 8 49 95 79 32 45 42 58 60 40 4 3 98 31 20
|
||||
Card 111: 61 7 67 98 74 21 79 4 85 68 | 90 80 4 8 46 55 40 28 30 38 64 86 73 51 42 66 69 15 29 6 52 78 82 49 41
|
||||
Card 112: 13 92 98 37 72 52 1 30 42 36 | 17 65 49 6 5 33 40 10 57 72 12 53 7 15 44 18 90 46 81 99 26 16 23 52 66
|
||||
Card 113: 39 30 46 62 55 42 32 77 9 37 | 37 21 50 40 63 97 28 11 51 26 75 86 80 32 16 69 77 60 6 99 9 72 22 55 79
|
||||
Card 114: 54 6 72 17 56 76 23 78 7 38 | 15 76 40 56 8 50 51 97 94 64 13 3 69 24 54 66 14 25 82 1 71 41 47 74 92
|
||||
Card 115: 50 66 30 89 46 20 35 59 22 88 | 96 72 32 97 61 64 25 70 4 11 88 34 46 6 10 73 71 79 45 33 66 50 24 13 42
|
||||
Card 116: 83 33 99 22 90 32 11 28 47 85 | 80 58 57 7 15 1 23 59 86 54 67 36 83 38 34 18 37 35 19 90 45 24 46 4 84
|
||||
Card 117: 95 23 58 8 76 82 60 1 15 80 | 75 77 10 85 36 52 91 54 44 96 97 89 25 67 16 31 99 51 68 83 55 29 3 20 33
|
||||
Card 118: 53 7 99 97 39 37 80 52 18 77 | 76 78 83 34 75 69 39 14 27 44 89 56 23 30 43 48 57 61 29 82 87 93 67 62 12
|
||||
Card 119: 19 22 6 97 71 68 59 95 67 75 | 91 40 20 74 87 46 4 85 63 64 50 88 14 1 54 39 3 62 58 10 28 55 27 86 60
|
||||
Card 120: 37 76 87 74 15 84 14 11 99 60 | 24 15 92 60 25 3 86 1 33 5 62 65 79 6 91 45 11 14 10 2 43 4 68 85 54
|
||||
Card 121: 74 43 96 14 67 85 19 51 80 95 | 27 53 14 15 72 99 85 30 33 20 13 58 12 25 36 18 45 67 34 79 32 76 96 95 55
|
||||
Card 122: 93 51 95 32 2 18 40 72 31 45 | 8 98 70 17 62 22 63 72 69 73 3 26 42 25 1 41 28 13 77 92 32 60 56 2 65
|
||||
Card 123: 9 82 93 20 35 69 87 40 30 67 | 87 10 67 63 76 23 45 35 54 5 75 79 66 40 1 89 71 20 77 43 90 65 9 82 37
|
||||
Card 124: 93 48 59 54 75 8 83 35 4 64 | 71 59 41 35 4 65 49 5 98 91 54 45 76 64 93 75 8 83 48 87 94 32 16 89 82
|
||||
Card 125: 24 14 40 22 2 57 67 35 36 98 | 36 82 19 88 23 55 15 97 78 35 94 24 67 52 14 30 40 56 38 57 2 31 22 98 71
|
||||
Card 126: 22 7 97 12 95 66 69 51 59 88 | 94 88 59 58 70 64 95 29 7 93 68 21 16 19 36 39 41 66 10 76 78 82 63 34 56
|
||||
Card 127: 46 9 32 85 22 20 14 68 98 61 | 69 25 4 70 64 57 14 89 41 98 22 53 27 77 20 56 84 42 85 40 90 6 61 71 60
|
||||
Card 128: 53 84 81 45 23 13 93 34 42 80 | 80 74 39 50 75 49 7 61 43 5 1 51 36 54 57 97 26 32 82 98 68 45 93 37 86
|
||||
Card 129: 40 29 85 88 86 7 49 67 91 92 | 86 38 79 31 57 34 78 17 52 53 22 36 62 75 21 70 88 7 3 49 28 6 85 14 4
|
||||
Card 130: 63 20 36 62 43 98 99 12 46 57 | 14 32 99 22 17 70 5 91 57 95 49 15 28 46 84 89 78 79 43 98 45 50 88 16 23
|
||||
Card 131: 7 16 87 36 73 82 11 40 14 69 | 25 31 82 24 50 38 2 28 4 23 72 6 51 79 86 46 55 97 42 90 84 1 39 32 27
|
||||
Card 132: 67 56 15 63 40 9 59 23 94 27 | 26 65 80 40 46 23 37 78 27 12 34 98 41 59 94 16 50 79 90 15 4 7 6 62 17
|
||||
Card 133: 18 91 27 52 4 34 12 32 65 41 | 45 55 7 3 84 79 54 91 75 80 17 49 42 9 18 48 59 6 8 22 94 10 93 53 57
|
||||
Card 134: 78 75 48 26 14 8 91 41 34 68 | 18 29 57 5 17 22 56 97 74 34 13 50 40 33 62 20 10 71 58 1 21 88 87 8 25
|
||||
Card 135: 5 97 16 92 74 51 61 65 3 14 | 15 50 86 24 99 90 59 32 45 81 97 75 6 25 29 80 9 89 46 70 40 57 42 63 60
|
||||
Card 136: 81 35 23 70 51 14 31 50 67 7 | 32 28 40 58 4 99 18 95 11 90 86 13 84 74 61 5 44 47 24 38 21 1 77 48 78
|
||||
Card 137: 74 99 57 81 5 1 90 9 69 30 | 88 23 97 7 25 68 78 91 53 15 55 81 92 90 12 18 50 71 61 75 8 76 36 19 34
|
||||
Card 138: 37 2 84 13 78 51 29 15 42 71 | 49 30 16 88 79 67 76 75 38 80 91 6 28 83 14 26 1 19 40 18 32 98 74 17 44
|
||||
Card 139: 49 75 16 61 39 4 51 55 17 97 | 11 45 56 47 81 78 67 21 57 42 84 58 8 13 10 91 7 19 46 14 90 87 26 1 18
|
||||
Card 140: 39 19 41 45 17 30 29 66 61 25 | 61 53 29 41 37 30 95 93 45 17 8 21 66 10 14 78 65 18 39 5 52 91 19 25 4
|
||||
Card 141: 7 66 29 40 9 14 34 64 4 31 | 98 63 65 6 92 56 81 67 48 88 49 18 38 61 13 95 28 85 20 17 21 30 58 52 89
|
||||
Card 142: 32 88 54 27 21 86 49 87 44 45 | 15 44 67 75 87 79 21 10 34 70 54 49 88 3 28 32 65 27 43 98 53 64 45 86 9
|
||||
Card 143: 14 7 67 53 37 73 45 18 62 34 | 87 68 3 22 40 86 26 85 70 4 61 78 1 29 48 12 37 10 77 54 99 36 94 79 15
|
||||
Card 144: 92 35 52 27 19 16 58 4 22 85 | 47 37 30 51 96 28 58 81 85 9 19 10 46 22 27 7 35 52 16 60 4 92 53 13 84
|
||||
Card 145: 71 32 62 83 43 20 97 57 78 24 | 88 34 23 25 67 52 11 9 49 80 70 29 43 2 44 45 62 56 33 3 20 98 28 77 79
|
||||
Card 146: 99 11 17 93 16 77 1 46 55 68 | 25 17 77 99 35 53 3 84 98 2 21 74 27 58 16 20 33 22 39 28 69 9 92 46 52
|
||||
Card 147: 56 26 30 23 66 94 82 47 14 49 | 68 41 6 13 99 7 71 67 35 93 57 84 44 40 70 89 42 63 74 22 20 55 33 91 64
|
||||
Card 148: 21 6 43 36 7 44 61 23 93 57 | 53 20 51 59 74 77 16 92 47 25 62 58 18 85 3 63 46 81 99 5 79 70 69 75 34
|
||||
Card 149: 31 36 91 20 17 50 1 18 64 52 | 66 90 80 33 26 24 30 58 45 77 25 29 44 48 6 35 96 13 78 65 68 98 93 89 94
|
||||
Card 150: 81 91 37 66 12 33 59 97 38 32 | 61 38 91 95 75 85 48 44 37 47 84 66 35 62 79 94 25 22 97 17 10 31 96 5 78
|
||||
Card 151: 32 35 11 75 63 61 42 62 10 56 | 4 44 53 12 50 76 51 5 82 25 30 8 89 41 34 98 54 96 37 74 35 16 31 57 65
|
||||
Card 152: 96 60 29 43 99 19 80 8 5 2 | 87 52 19 11 99 35 20 60 55 80 24 21 8 61 38 78 42 28 95 6 64 65 49 59 26
|
||||
Card 153: 53 30 75 13 87 77 56 89 63 6 | 7 54 93 80 47 4 72 9 69 44 97 96 23 24 94 67 55 8 33 30 37 6 14 5 3
|
||||
Card 154: 10 65 46 58 13 25 69 52 19 3 | 47 41 9 3 40 79 89 21 33 73 14 7 74 65 31 62 24 69 60 87 12 16 53 80 82
|
||||
Card 155: 24 51 35 95 93 73 36 65 27 20 | 14 83 97 94 29 39 19 38 33 32 44 92 60 25 76 64 49 71 65 34 91 31 53 74 23
|
||||
Card 156: 52 31 50 54 82 42 23 9 39 3 | 29 64 88 70 48 74 12 90 75 57 23 25 58 68 36 33 73 5 84 28 47 92 50 41 21
|
||||
Card 157: 66 20 50 96 6 84 54 67 59 81 | 77 60 38 65 37 44 15 73 23 83 18 71 89 53 90 36 40 32 2 39 78 63 8 51 19
|
||||
Card 158: 38 46 85 81 87 86 98 90 37 34 | 41 71 35 26 12 19 51 93 39 20 76 24 7 80 50 56 49 2 57 84 68 92 54 1 75
|
||||
Card 159: 61 36 84 47 4 22 49 17 31 75 | 77 83 49 55 84 80 18 44 31 47 22 67 4 68 69 35 75 5 59 13 61 39 36 54 17
|
||||
Card 160: 90 70 62 65 87 95 15 77 76 35 | 70 94 97 10 90 80 35 27 84 87 42 62 54 26 95 57 82 63 1 18 92 25 49 64 21
|
||||
Card 161: 44 6 28 50 79 16 15 83 45 53 | 79 72 12 45 50 35 67 6 89 28 15 61 16 7 46 36 44 55 27 92 1 59 83 53 94
|
||||
Card 162: 29 51 46 64 4 75 37 78 81 71 | 83 71 37 39 74 66 32 1 51 93 43 46 20 3 15 50 81 64 75 73 78 29 33 4 22
|
||||
Card 163: 1 52 37 97 88 47 94 10 98 5 | 85 31 33 46 15 1 16 61 98 59 64 94 83 68 35 11 44 80 38 36 84 72 86 40 29
|
||||
Card 164: 60 40 94 62 18 71 92 25 21 64 | 64 18 58 76 38 55 40 45 71 92 73 75 25 62 12 94 68 79 23 91 21 60 72 39 7
|
||||
Card 165: 63 88 91 22 85 18 39 55 33 84 | 95 88 37 5 39 46 33 61 32 45 74 20 27 35 76 85 84 18 54 86 91 75 22 55 63
|
||||
Card 166: 72 11 31 50 53 82 41 74 62 87 | 42 34 50 11 96 3 77 7 37 22 44 38 62 1 87 68 12 54 74 53 47 82 69 89 85
|
||||
Card 167: 79 26 70 95 25 16 18 37 75 61 | 39 11 68 61 44 53 42 94 37 45 75 78 62 18 95 26 79 92 38 13 16 64 21 91 57
|
||||
Card 168: 94 86 69 88 31 15 62 44 19 14 | 3 24 29 8 44 61 89 7 75 15 91 36 45 70 66 4 35 6 71 22 25 39 55 33 18
|
||||
Card 169: 86 68 72 15 42 99 9 35 2 74 | 42 84 59 86 6 15 53 89 85 79 20 68 62 61 10 2 9 51 99 54 33 35 13 48 93
|
||||
Card 170: 83 6 15 80 93 63 79 50 69 5 | 15 25 6 93 69 50 83 68 16 40 66 58 63 79 52 7 80 34 61 95 5 33 78 91 32
|
||||
Card 171: 33 85 4 12 72 62 49 67 17 53 | 4 17 53 72 47 6 49 56 82 48 12 26 30 85 61 15 36 70 64 25 2 33 67 46 62
|
||||
Card 172: 98 63 26 82 12 61 56 95 27 99 | 76 30 14 95 26 97 71 19 57 67 73 48 63 54 82 18 98 27 61 5 12 44 1 56 74
|
||||
Card 173: 7 32 34 4 22 79 27 10 78 65 | 3 81 65 36 91 62 94 54 41 32 12 28 39 34 18 61 78 79 80 66 9 63 43 72 97
|
||||
Card 174: 14 78 60 32 26 31 15 80 11 72 | 1 31 33 35 73 83 97 36 21 3 26 9 91 23 51 84 82 70 22 20 34 90 98 87 69
|
||||
Card 175: 73 14 7 11 20 64 30 90 62 23 | 60 53 15 73 63 19 71 92 48 89 80 44 78 79 2 76 45 64 42 35 81 27 10 21 26
|
||||
Card 176: 32 30 39 10 1 3 67 66 94 62 | 86 95 56 54 58 35 90 19 74 43 5 48 17 2 46 65 97 71 36 31 69 8 47 94 42
|
||||
Card 177: 24 90 40 47 51 75 63 29 57 10 | 49 68 61 43 30 26 84 59 99 75 44 41 17 24 12 38 90 37 36 35 91 9 89 46 8
|
||||
Card 178: 73 74 31 76 10 21 70 3 30 41 | 39 14 30 70 79 75 97 44 87 20 92 12 86 56 18 46 8 90 23 98 2 59 28 53 3
|
||||
Card 179: 78 44 89 84 50 97 55 90 77 99 | 79 1 88 65 2 50 72 68 7 15 85 41 64 93 37 16 53 44 42 48 89 97 59 60 8
|
||||
Card 180: 55 98 13 45 33 91 88 4 49 37 | 18 44 64 83 56 79 81 26 78 54 72 75 11 70 66 57 73 61 62 34 19 95 93 94 76
|
||||
Card 181: 94 47 65 55 8 45 1 67 71 25 | 99 34 43 64 36 50 6 51 27 59 37 40 3 98 72 78 38 74 82 46 85 90 48 32 84
|
||||
Card 182: 78 75 63 31 30 70 84 50 28 19 | 61 18 58 87 77 48 71 50 91 92 60 86 73 94 85 57 97 15 1 25 74 67 11 68 47
|
||||
Card 183: 94 27 68 41 8 72 48 85 97 49 | 81 35 90 69 76 18 53 1 59 25 88 31 4 93 84 32 9 55 66 50 22 62 43 60 17
|
||||
Card 184: 40 31 56 54 59 98 93 81 24 44 | 62 42 93 56 99 10 81 59 37 6 41 66 44 72 31 30 20 54 51 24 27 83 40 73 98
|
||||
Card 185: 38 73 79 48 3 46 99 93 50 24 | 65 34 40 2 20 92 10 32 67 57 22 47 96 11 7 31 87 6 28 95 77 25 58 29 27
|
||||
Card 186: 47 65 99 98 90 68 13 49 51 10 | 90 82 27 68 84 83 57 50 18 5 49 65 85 10 46 13 21 81 73 51 71 47 98 88 99
|
||||
Card 187: 25 56 18 15 59 47 20 86 50 83 | 25 57 83 36 56 87 50 34 9 70 4 64 77 45 92 13 20 47 48 15 97 18 86 28 59
|
||||
Card 188: 99 16 44 2 85 17 71 45 49 11 | 94 13 45 36 77 89 26 6 39 27 84 1 80 21 73 41 33 90 46 72 65 96 34 71 83
|
||||
Card 189: 34 24 76 68 47 19 85 15 50 46 | 43 67 4 44 14 34 19 61 47 68 50 46 99 94 16 76 15 28 36 27 52 85 88 24 89
|
||||
Card 190: 56 20 43 86 2 88 87 30 14 4 | 43 14 19 92 3 23 87 74 50 97 2 88 18 80 20 86 36 41 95 27 57 98 49 30 26
|
||||
Card 191: 47 2 18 84 91 66 24 6 42 56 | 12 93 7 50 42 45 2 91 66 4 32 47 19 56 49 18 15 24 44 84 97 6 16 31 25
|
||||
Card 192: 42 88 68 56 93 48 9 52 20 70 | 30 93 42 4 68 70 36 56 9 15 88 98 64 67 33 91 20 61 50 27 13 94 52 48 85
|
||||
Card 193: 46 57 19 40 9 7 47 33 86 11 | 65 54 38 43 82 55 79 51 77 73 74 97 75 96 6 47 62 88 92 18 84 48 41 29 52
|
||||
Card 194: 58 23 35 79 82 72 44 93 12 43 | 43 60 2 24 77 48 61 25 44 75 35 12 93 51 36 72 6 31 29 50 37 80 19 14 87
|
||||
Card 195: 15 77 78 50 36 83 68 52 86 26 | 16 72 67 88 14 81 34 24 71 32 91 77 90 1 98 95 7 28 49 84 86 20 44 73 56
|
||||
Card 196: 25 3 32 15 1 56 27 51 82 81 | 87 79 15 11 98 54 56 88 18 92 69 25 66 27 60 58 44 1 51 3 32 81 12 72 41
|
||||
Card 197: 3 99 81 8 93 28 76 7 27 48 | 78 98 85 5 93 77 72 62 69 82 50 9 35 74 18 10 33 67 90 31 79 84 58 29 17
|
||||
Card 198: 26 81 19 24 59 82 8 95 86 17 | 13 22 10 96 19 20 88 3 90 78 24 9 50 34 6 94 7 60 44 76 31 81 26 33 43
|
||||
Card 199: 77 91 58 16 47 94 23 30 88 5 | 38 66 12 25 95 67 72 89 36 45 63 15 54 98 74 57 32 39 59 28 7 62 82 13 26
|
||||
Card 200: 82 47 52 12 83 4 26 93 33 9 | 31 30 91 2 6 27 28 1 81 8 75 92 56 57 41 24 72 85 53 74 59 11 66 32 54
|
||||
Card 201: 4 13 26 57 84 17 63 10 98 56 | 72 85 68 47 44 60 54 34 38 16 8 11 23 84 32 18 69 13 26 35 9 73 43 15 89
|
||||
Card 202: 11 9 1 42 71 78 97 89 8 10 | 33 17 81 48 60 96 69 37 12 46 73 4 76 54 86 91 28 5 51 98 99 84 13 85 32
|
||||
Card 203: 37 80 7 87 79 60 6 49 16 12 | 23 34 15 46 38 20 27 45 33 97 37 14 68 83 49 79 43 70 57 60 11 63 24 35 73
|
||||
Card 204: 84 24 48 76 7 18 77 37 69 5 | 88 39 92 94 34 37 11 40 85 35 2 81 73 58 42 66 83 9 56 12 14 51 62 20 7
|
||||
Card 205: 5 84 4 6 95 77 59 67 74 35 | 58 47 29 34 79 86 35 89 71 96 27 64 90 48 37 78 1 39 46 21 98 91 43 8 56
|
||||
Card 206: 56 21 34 13 1 17 99 11 76 60 | 36 24 83 31 50 19 82 32 61 9 98 71 79 39 97 37 29 13 27 10 52 22 41 40 59
|
||||
Card 207: 62 7 22 90 51 96 12 13 36 52 | 48 37 70 24 73 51 83 3 5 77 29 87 23 18 26 76 19 97 20 86 84 14 63 33 21
|
||||
Card 208: 40 42 5 91 29 59 70 49 23 94 | 82 81 30 61 64 65 19 9 67 75 92 16 26 52 73 43 55 35 17 93 39 90 74 53 51
|
6
advent_2023/puzzle_2023_day_4/input_example_1.txt
Normal file
6
advent_2023/puzzle_2023_day_4/input_example_1.txt
Normal file
@ -0,0 +1,6 @@
|
||||
Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53
|
||||
Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19
|
||||
Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1
|
||||
Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83
|
||||
Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
|
||||
Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11
|
173
advent_2023/puzzle_2023_day_4/src/lib.rs
Normal file
173
advent_2023/puzzle_2023_day_4/src/lib.rs
Normal file
@ -0,0 +1,173 @@
|
||||
use std::cmp;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(Debug, Default, PartialEq, Clone)]
|
||||
pub struct CardNumbers {
|
||||
pub numbers: Vec<u32>,
|
||||
}
|
||||
|
||||
impl FromStr for CardNumbers {
|
||||
type Err = &'static str;
|
||||
|
||||
/// Parses a string `string` to return a value of [`CardNumbers`]
|
||||
///
|
||||
/// If parsing succeeds, return the value inside [`Ok`], otherwise
|
||||
/// when the string is ill-formatted return an error specific to the
|
||||
/// inside [`Err`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::str::FromStr;
|
||||
/// use puzzle_2023_day_4::CardNumbers;
|
||||
///
|
||||
/// let string = "83 86 6 31 17 9 48 53";
|
||||
/// let expected_result = CardNumbers {
|
||||
/// numbers: vec![83, 86, 6, 31, 17, 9, 48, 53],
|
||||
/// };
|
||||
/// let actual_result = CardNumbers::from_str(string).unwrap();
|
||||
///
|
||||
/// assert_eq!(actual_result, expected_result);
|
||||
/// ```
|
||||
fn from_str(string: &str) -> Result<Self, Self::Err> {
|
||||
let result = CardNumbers {
|
||||
numbers: string
|
||||
.split_whitespace()
|
||||
.map(|string| string.trim())
|
||||
.filter(|&string| !string.is_empty())
|
||||
.map(|string| string.parse::<u32>().unwrap_or_default())
|
||||
.collect(),
|
||||
};
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, PartialEq, Clone)]
|
||||
pub struct Card {
|
||||
pub id: usize,
|
||||
pub winning_numbers_count: usize,
|
||||
}
|
||||
|
||||
impl FromStr for Card {
|
||||
type Err = &'static str;
|
||||
|
||||
/// Parses a string `string` to return a value of [`Card`]
|
||||
///
|
||||
/// If parsing succeeds, return the value inside [`Ok`], otherwise
|
||||
/// when the string is ill-formatted return an error specific to the
|
||||
/// inside [`Err`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::str::FromStr;
|
||||
/// use puzzle_2023_day_4::{Card, CardNumbers};
|
||||
///
|
||||
/// let string = "Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53";
|
||||
/// let expected_result = Card {
|
||||
/// id: 1,
|
||||
/// winning_numbers_count: 4,
|
||||
/// };
|
||||
/// let actual_result = Card::from_str(string).unwrap();
|
||||
///
|
||||
/// assert_eq!(actual_result, expected_result);
|
||||
/// ```
|
||||
fn from_str(string: &str) -> Result<Self, Self::Err> {
|
||||
let mut result = Card::default();
|
||||
let mut parts = string.split(": ");
|
||||
result.id = parts
|
||||
.next()
|
||||
.unwrap_or("Card 1")
|
||||
.strip_prefix("Card ")
|
||||
.unwrap_or("1")
|
||||
.trim()
|
||||
.parse()
|
||||
.unwrap_or(1);
|
||||
|
||||
let mut numbers_parts = parts.next().unwrap_or("").split(" | ");
|
||||
|
||||
let winning_numbers =
|
||||
CardNumbers::from_str(numbers_parts.next().unwrap_or("")).unwrap_or_default();
|
||||
let owned_numbers =
|
||||
CardNumbers::from_str(numbers_parts.next().unwrap_or("")).unwrap_or_default();
|
||||
|
||||
result.winning_numbers_count = owned_numbers
|
||||
.numbers
|
||||
.iter()
|
||||
.filter(|&owned_number| winning_numbers.numbers.contains(owned_number))
|
||||
.count();
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn part_1(input: &str) -> usize {
|
||||
input
|
||||
.lines()
|
||||
.map(|line| Card::from_str(line).unwrap_or_default())
|
||||
.map(|card| {
|
||||
let winning_numbers_count = card.winning_numbers_count as u32;
|
||||
let base: usize = 2;
|
||||
if winning_numbers_count > 0 {
|
||||
base.pow(winning_numbers_count.saturating_sub(1))
|
||||
} else {
|
||||
0
|
||||
}
|
||||
})
|
||||
.sum::<usize>()
|
||||
}
|
||||
|
||||
pub fn part_2(input: &str) -> usize {
|
||||
let cards = input
|
||||
.lines()
|
||||
.map(|line| Card::from_str(line).unwrap_or_default())
|
||||
.collect::<Vec<Card>>();
|
||||
let mut cards_identifiers = cards.iter().map(|card| card.id).collect::<Vec<usize>>();
|
||||
|
||||
let mut index_card = 0;
|
||||
loop {
|
||||
if index_card >= cards_identifiers.len() {
|
||||
break;
|
||||
}
|
||||
|
||||
if let Some(card) = cards.get(cards_identifiers.get(index_card).unwrap_or(&0) - 1) {
|
||||
let card_position_index = card.id - 1;
|
||||
let maximum_index = cmp::min(
|
||||
card_position_index + card.winning_numbers_count,
|
||||
cards.len() - 1,
|
||||
);
|
||||
for index in card_position_index + 1..=maximum_index {
|
||||
cards_identifiers.push(index + 1);
|
||||
}
|
||||
}
|
||||
|
||||
index_card += 1;
|
||||
}
|
||||
|
||||
cards_identifiers.len()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod puzzle_2023_day_4_tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_part_1_example() {
|
||||
assert_eq!(part_1(include_str!("../input_example_1.txt")), 13);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part_2_example() {
|
||||
assert_eq!(part_2(include_str!("../input_example_1.txt")), 30);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part_1() {
|
||||
assert_eq!(part_1(include_str!("../input.txt")), 24160);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part_2() {
|
||||
assert_eq!(part_2(include_str!("../input.txt")), 5659035);
|
||||
}
|
||||
}
|
8
advent_2023/puzzle_2023_day_4/src/main.rs
Normal file
8
advent_2023/puzzle_2023_day_4/src/main.rs
Normal file
@ -0,0 +1,8 @@
|
||||
use puzzle_2023_day_4::{part_1, part_2};
|
||||
|
||||
fn main() {
|
||||
let input = include_str!("../input.txt");
|
||||
println!("- Day 4 of 2023: Scratchcards -");
|
||||
println!("Answer Part 1: {}", part_1(input));
|
||||
println!("Answer Part 2: {}", part_2(input));
|
||||
}
|
9
advent_2023/puzzle_2023_day_5/Cargo.toml
Normal file
9
advent_2023/puzzle_2023_day_5/Cargo.toml
Normal file
@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "puzzle_2023_day_5"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
|
||||
[dependencies]
|
||||
rayon = { workspace = true }
|
||||
indicatif = { workspace = true }
|
128
advent_2023/puzzle_2023_day_5/README.md
Normal file
128
advent_2023/puzzle_2023_day_5/README.md
Normal file
@ -0,0 +1,128 @@
|
||||
# - Day 5 of 2023: If You Give A Seed A Fertilizer -
|
||||
|
||||
Source: <https://adventofcode.com/2023/day/5>
|
||||
|
||||
## Instructions - Part 1
|
||||
|
||||
You take the boat and find the gardener right where you were told he would be: managing a giant "garden" that looks more to you like a farm.
|
||||
|
||||
"A water source? Island Island **is** the water source!" You point out that Snow Island isn't receiving any water.
|
||||
|
||||
"Oh, we had to stop the water because we **ran out of sand** to [filter](https://en.wikipedia.org/wiki/Sand_filter) it with! Can't make snow with dirty water. Don't worry, I'm sure we'll get more sand soon; we only turned off the water a few days... weeks... oh no." His face sinks into a look of horrified realization.
|
||||
|
||||
"I've been so busy making sure everyone here has food that I completely forgot to check why we stopped getting more sand! There's a ferry leaving soon that is headed over in that direction - it's much faster than your boat. Could you please go check it out?"
|
||||
|
||||
You barely have time to agree to this request when he brings up another. "While you wait for the ferry, maybe you can help us with our **food production problem**. The latest Island Island [Almanac](https://en.wikipedia.org/wiki/Almanac) just arrived and we're having trouble making sense of it."
|
||||
|
||||
The almanac (your puzzle input) lists all of the seeds that need to be planted. It also lists what type of soil to use with each kind of seed, what type of fertilizer to use with each kind of soil, what type of water to use with each kind of fertilizer, and so on. Every type of seed, soil, fertilizer and so on is identified with a number, but numbers are reused by each category - that is, soil `123` and fertilizer `123` aren't necessarily related to each other.
|
||||
|
||||
For example:
|
||||
|
||||
```txt
|
||||
seeds: 79 14 55 13
|
||||
|
||||
seed-to-soil map:
|
||||
50 98 2
|
||||
52 50 48
|
||||
|
||||
soil-to-fertilizer map:
|
||||
0 15 37
|
||||
37 52 2
|
||||
39 0 15
|
||||
|
||||
fertilizer-to-water map:
|
||||
49 53 8
|
||||
0 11 42
|
||||
42 0 7
|
||||
57 7 4
|
||||
|
||||
water-to-light map:
|
||||
88 18 7
|
||||
18 25 70
|
||||
|
||||
light-to-temperature map:
|
||||
45 77 23
|
||||
81 45 19
|
||||
68 64 13
|
||||
|
||||
temperature-to-humidity map:
|
||||
0 69 1
|
||||
1 0 69
|
||||
|
||||
humidity-to-location map:
|
||||
60 56 37
|
||||
56 93 4
|
||||
```
|
||||
|
||||
The almanac starts by listing which seeds need to be planted: seeds `79`, `14`, `55`, and `13`.
|
||||
|
||||
The rest of the almanac contains a list of **maps** which describe how to convert numbers from a **source category** into numbers in a **destination category**. That is, the section that starts with `seed-to-soil map:` describes how to convert a **seed number** (the source) to a **soil number** (the destination). This lets the gardener and his team know which soil to use with which seeds, which water to use with which fertilizer, and so on.
|
||||
|
||||
Rather than list every source number and its corresponding destination number one by one, the maps describe entire **ranges** of numbers that can be converted. Each line within a map contains three numbers: the **destination range start**, the **source range start**, and the **range length**.
|
||||
|
||||
Consider again the example seed-to-soil map:
|
||||
|
||||
```txt
|
||||
50 98 2
|
||||
52 50 48
|
||||
```
|
||||
|
||||
The first line has a **destination range start** of `50`, a **source range start** of `98`, and a **range length** of `2`. This line means that the source range starts at `98` and contains two values: `98` and `99`. The destination range is the same length, but it starts at `50`, so its two values are `50` and `51`. With this information, you know that seed number `98` corresponds to soil number `50` and that seed number `99` corresponds to soil number `51`.
|
||||
|
||||
The second line means that the source range starts at `50` and contains `48` values: `50`, `51`, ..., `96`, `97`. This corresponds to a destination range starting at 52 and also containing `48` values: `52`, `53`, ..., `98`, `99`. So, seed number `53` corresponds to soil number `55`.
|
||||
|
||||
Any source numbers that **aren't mapped** correspond to the same destination number. So, seed number `10` corresponds to soil number `10`.
|
||||
|
||||
So, the entire list of seed numbers and their corresponding soil numbers looks like this:
|
||||
|
||||
```txt
|
||||
seed soil
|
||||
0 0
|
||||
1 1
|
||||
... ...
|
||||
48 48
|
||||
49 49
|
||||
50 52
|
||||
51 53
|
||||
... ...
|
||||
96 98
|
||||
97 99
|
||||
98 50
|
||||
99 51
|
||||
```
|
||||
|
||||
With this map, you can look up the soil number required for each initial seed number:
|
||||
|
||||
- Seed number `79` corresponds to soil number `81`.
|
||||
- Seed number `14` corresponds to soil number `14`.
|
||||
- Seed number `55` corresponds to soil number `57`.
|
||||
- Seed number `13` corresponds to soil number `13`.
|
||||
|
||||
The gardener and his team want to get started as soon as possible, so they'd like to know the closest location that needs a seed. Using these maps, find **the lowest location number that corresponds to any of the initial seeds**. To do this, you'll need to convert each seed number through other categories until you can find its corresponding **location number**. In this example, the corresponding types are:
|
||||
|
||||
- Seed `79`, soil `81`, fertilizer `81`, water `81`, light `74`, temperature `78`, humidity `78`, **location `82`**.
|
||||
- Seed `14`, soil `14`, fertilizer `53`, water `49`, light `42`, temperature `42`, humidity `43`, **location `43`**.
|
||||
- Seed `55`, soil `57`, fertilizer `57`, water `53`, light `46`, temperature `82`, humidity `82`, **location `86`**.
|
||||
- Seed `13`, soil `13`, fertilizer `52`, water `41`, light `34`, temperature `34`, humidity `35`, **location `35`**.
|
||||
|
||||
So, the lowest location number in this example is **`35`**.
|
||||
|
||||
**What is the lowest location number that corresponds to any of the initial seed numbers?**
|
||||
|
||||
## Instructions - Part 2
|
||||
|
||||
Everyone will starve if you only plant such a small number of seeds. Re-reading the almanac, it looks like the `seeds:` line actually describes **ranges of seed numbers**.
|
||||
|
||||
The values on the initial seeds: line come in pairs. Within each pair, the first value is the start of the range and the second value is the **length** of the range. So, in the first line of the example above:
|
||||
|
||||
```txt
|
||||
seeds: 79 14 55 13
|
||||
```
|
||||
|
||||
This line describes two ranges of seed numbers to be planted in the garden. The first range starts with seed number `79` and contains `14` values: `79`, `80`, ..., `91`, `92`. The second range starts with seed number `55` and contains `13` values: `55`, `56`, ..., `66`, `67`.
|
||||
|
||||
Now, rather than considering four seed numbers, you need to consider a total of **27** seed numbers.
|
||||
|
||||
In the above example, the lowest location number can be obtained from seed number `82`, which corresponds to soil `84`, fertilizer `84`, water `84`, light `77`, temperature `45`, humidity `46`, and location `46`. So, the lowest location number is **`46`**`.
|
||||
|
||||
Consider all of the initial seed numbers listed in the ranges on the first line of the almanac. **What is the lowest location number that corresponds to any of the initial seed numbers?**
|
221
advent_2023/puzzle_2023_day_5/input.txt
Normal file
221
advent_2023/puzzle_2023_day_5/input.txt
Normal file
@ -0,0 +1,221 @@
|
||||
seeds: 2019933646 2719986 2982244904 337763798 445440 255553492 1676917594 196488200 3863266382 36104375 1385433279 178385087 2169075746 171590090 572674563 5944769 835041333 194256900 664827176 42427020
|
||||
|
||||
seed-to-soil map:
|
||||
3566547172 3725495029 569472267
|
||||
2346761246 1249510998 267846697
|
||||
1812605508 937956667 271194541
|
||||
1421378697 1209151208 40359790
|
||||
2083800049 2788751092 262961197
|
||||
2938601691 473979048 463977619
|
||||
473979048 1517357695 947399649
|
||||
4136019439 3566547172 158947857
|
||||
1461738487 3051712289 350867021
|
||||
2614607943 2464757344 323993748
|
||||
|
||||
soil-to-fertilizer map:
|
||||
3107230831 2583931429 576709409
|
||||
970181981 608291332 1441137369
|
||||
743954495 3859046283 158951815
|
||||
3683940240 3227916509 91282070
|
||||
608291332 2448268266 135663163
|
||||
3775222310 2049428701 398839565
|
||||
2411319350 3319198579 539847704
|
||||
2951167054 4017998098 156063777
|
||||
902906310 3160640838 67275671
|
||||
|
||||
fertilizer-to-water map:
|
||||
1257642402 395703749 69589612
|
||||
1800674 2215701547 90550534
|
||||
2757853693 358464863 37238886
|
||||
3285451399 181079109 43937782
|
||||
2346544130 3513448371 192150886
|
||||
3866348216 4231433060 63534236
|
||||
1327232014 1560332334 90281838
|
||||
2538695016 616206288 114467702
|
||||
255018176 225016891 46372244
|
||||
1171065990 3705599257 27021880
|
||||
1070753744 730673990 442780
|
||||
221369008 3479799203 33649168
|
||||
2987721226 271389135 80072982
|
||||
1198087870 732917444 24556356
|
||||
199036270 2306252081 22332738
|
||||
0 731116770 1800674
|
||||
3929882452 3989920675 212758268
|
||||
631506549 757473800 322942578
|
||||
301390420 0 157952443
|
||||
2795092579 157952443 1997721
|
||||
1222644226 2619085211 34998176
|
||||
954449127 499901671 116304617
|
||||
1429766246 159950164 21128945
|
||||
2205492221 2074649638 141051909
|
||||
2749302577 3732621137 8551116
|
||||
459342863 1219863414 57737723
|
||||
3329389181 3741172253 59047790
|
||||
2797090300 2328584819 190630926
|
||||
3278448653 351462117 7002746
|
||||
126959518 1277601137 72076752
|
||||
92351208 465293361 34608310
|
||||
4142640720 3866348216 123572459
|
||||
2143980560 1080416378 43307177
|
||||
1450895191 2672287871 693085369
|
||||
517080586 3365373240 114425963
|
||||
3388436971 1662866566 411783072
|
||||
2187287737 2654083387 18204484
|
||||
1417513852 1650614172 12252394
|
||||
3067794208 1349677889 210654445
|
||||
4266213179 4202678943 28754117
|
||||
2653162718 1123723555 96139859
|
||||
1071196524 2519215745 99869466
|
||||
|
||||
water-to-light map:
|
||||
512627839 90187036 1196629
|
||||
3379634653 2059506154 33434334
|
||||
3286651054 4276482087 18485209
|
||||
4233695090 28914830 61272206
|
||||
3413068987 3322576776 23288997
|
||||
3736304424 3345865773 43267308
|
||||
1246285471 2994853001 251748584
|
||||
3779571732 1946298040 113208114
|
||||
390808412 3287769466 34807310
|
||||
1881283842 2879009693 106527924
|
||||
3964031050 2506138169 12994476
|
||||
3436357984 793897944 162691614
|
||||
2255160753 2092940488 151061610
|
||||
853985057 3506201042 119010035
|
||||
301385394 1856875022 89423018
|
||||
972995092 658665705 34308693
|
||||
4159948022 1315925500 65322692
|
||||
640912738 250463411 213072319
|
||||
1761800914 91383665 102591221
|
||||
450345319 3246601585 5793995
|
||||
3186220306 4173678310 91115364
|
||||
28914830 3633635453 176360375
|
||||
456139314 193974886 56488525
|
||||
2523290324 3809995828 187303152
|
||||
2406222363 3389133081 117067961
|
||||
205275205 2782899504 96110189
|
||||
2135785589 1100569535 119375164
|
||||
1121466033 533846267 124819438
|
||||
1007303785 2244002098 114162248
|
||||
3599049598 3997298980 137254826
|
||||
4077949072 463535730 70310537
|
||||
4225270714 3625211077 8424376
|
||||
1498034055 2519132645 263766859
|
||||
2710593476 1381248192 475626830
|
||||
3977025526 692974398 100923546
|
||||
4148259609 4264793674 11688413
|
||||
1987811766 2358164346 147973823
|
||||
3892779846 1244674296 71251204
|
||||
3340510149 4134553806 39124504
|
||||
1864392135 956589558 16891707
|
||||
425615722 1219944699 24729597
|
||||
513824468 973481265 127088270
|
||||
3277335670 2985537617 9315384
|
||||
3305136263 3252395580 35373886
|
||||
|
||||
light-to-temperature map:
|
||||
1094191559 698410082 28110394
|
||||
383870732 1189042355 107231661
|
||||
3711052230 2164474756 34756304
|
||||
745558539 170241759 7170863
|
||||
491102393 503970250 194439832
|
||||
4034618875 3142749029 146609939
|
||||
3781998432 1718948669 129329785
|
||||
2440091414 3071819711 70929318
|
||||
1301358031 55123603 115118156
|
||||
0 2789116652 87933685
|
||||
770729148 177412622 48955790
|
||||
3772681560 3886204605 9316872
|
||||
752729402 37123857 17999746
|
||||
3745808534 2137385460 7147939
|
||||
2028807236 3677936618 208267987
|
||||
2237075223 3289358968 92979022
|
||||
88764920 1960439220 176946240
|
||||
3568470355 2258695303 142581875
|
||||
3276170082 1848278454 112160766
|
||||
2637902204 1129503077 39814191
|
||||
3000547589 892603630 188042422
|
||||
2511020732 226368412 126881472
|
||||
1122301953 1296274016 52818372
|
||||
1440958847 1353023078 243104929
|
||||
2963423732 0 37123857
|
||||
3388330848 2199231060 48304954
|
||||
1175120325 377732544 126237706
|
||||
819684938 1349092388 3930690
|
||||
3752956473 1169317268 19725087
|
||||
3911328217 2144533399 19941357
|
||||
1416476187 353249884 24482660
|
||||
2677716395 3895521477 285707337
|
||||
265711160 2413138935 118159572
|
||||
685542225 1080646052 48857025
|
||||
3556608598 2401277178 11861757
|
||||
734399250 2247536014 11159289
|
||||
87933685 3677105383 831235
|
||||
3188590011 1596128007 87580071
|
||||
836373414 2531298507 257818145
|
||||
3471876393 2877050337 84732205
|
||||
1684063776 726520476 166083154
|
||||
823615628 3560998296 12757786
|
||||
3436635802 1683708078 35240591
|
||||
3931269574 3573756082 103349301
|
||||
1850146930 3382337990 178660306
|
||||
2330054245 2961782542 110037169
|
||||
|
||||
temperature-to-humidity map:
|
||||
1773059646 4122818507 172148789
|
||||
2417158855 2859734866 110076859
|
||||
977168274 1576624124 28149321
|
||||
4275291678 3797606290 19675618
|
||||
1141296808 749646180 267286171
|
||||
3592756112 2969811725 273274339
|
||||
0 19621130 7167651
|
||||
2059084943 2697725300 48133058
|
||||
2107218001 3920609496 145140777
|
||||
1453481278 1152911564 151292167
|
||||
1408582979 1465584228 44898299
|
||||
7167651 0 19621130
|
||||
2907567891 1829621431 240604380
|
||||
2252358778 3652347291 145258999
|
||||
1005317595 1016932351 135979213
|
||||
1945208435 2745858358 113876508
|
||||
2397617777 4065750273 16506015
|
||||
3251499859 1776094709 53526722
|
||||
2867005672 4082256288 40562219
|
||||
26788781 1304203731 161380497
|
||||
3305026581 2409995769 287729531
|
||||
3866030451 3243086064 409261227
|
||||
2414123792 1773059646 3035063
|
||||
911026677 1510482527 66141597
|
||||
3148172271 3817281908 103327588
|
||||
2527235714 2070225811 339769958
|
||||
188169278 26788781 722857399
|
||||
|
||||
humidity-to-location map:
|
||||
3907319746 3137303541 31421983
|
||||
3085093695 1018495475 286155292
|
||||
2898003508 2491485887 87665522
|
||||
2546787368 2901838353 7997221
|
||||
3835317650 2829836257 72002096
|
||||
2554784589 3509894030 133012322
|
||||
3487595595 3719561871 104747874
|
||||
3714670750 2667334372 120646900
|
||||
975094571 2909835574 227467967
|
||||
2985669030 3864000834 99424665
|
||||
3672962118 2449777255 41708632
|
||||
3631107133 2787981272 41854985
|
||||
3938741729 3963425499 15057061
|
||||
3447904506 3824309745 39691089
|
||||
1824175159 1304650767 641793976
|
||||
242892183 0 6504921
|
||||
3371248987 3642906352 76655519
|
||||
1698833898 2258930589 81940357
|
||||
0 6504921 242892183
|
||||
2465969135 3978482560 80818233
|
||||
3592343469 4256203632 38763664
|
||||
3953798790 3168725524 341168506
|
||||
2775979874 4134179998 122023634
|
||||
1780774255 975094571 43400904
|
||||
1311468847 1946444743 312485846
|
||||
2687796911 2579151409 88182963
|
||||
1202562538 2340870946 108906309
|
||||
1623954693 4059300793 74879205
|
33
advent_2023/puzzle_2023_day_5/input_example_1.txt
Normal file
33
advent_2023/puzzle_2023_day_5/input_example_1.txt
Normal file
@ -0,0 +1,33 @@
|
||||
seeds: 79 14 55 13
|
||||
|
||||
seed-to-soil map:
|
||||
50 98 2
|
||||
52 50 48
|
||||
|
||||
soil-to-fertilizer map:
|
||||
0 15 37
|
||||
37 52 2
|
||||
39 0 15
|
||||
|
||||
fertilizer-to-water map:
|
||||
49 53 8
|
||||
0 11 42
|
||||
42 0 7
|
||||
57 7 4
|
||||
|
||||
water-to-light map:
|
||||
88 18 7
|
||||
18 25 70
|
||||
|
||||
light-to-temperature map:
|
||||
45 77 23
|
||||
81 45 19
|
||||
68 64 13
|
||||
|
||||
temperature-to-humidity map:
|
||||
0 69 1
|
||||
1 0 69
|
||||
|
||||
humidity-to-location map:
|
||||
60 56 37
|
||||
56 93 4
|
276
advent_2023/puzzle_2023_day_5/src/lib.rs
Normal file
276
advent_2023/puzzle_2023_day_5/src/lib.rs
Normal file
@ -0,0 +1,276 @@
|
||||
use indicatif::ParallelProgressIterator;
|
||||
use rayon::prelude::*;
|
||||
use std::ops::Range;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(Debug, Default, PartialEq, Clone)]
|
||||
pub struct RangeConverter {
|
||||
pub source_range: Range<usize>,
|
||||
pub destination_range: Range<usize>,
|
||||
}
|
||||
|
||||
impl FromStr for RangeConverter {
|
||||
type Err = &'static str;
|
||||
|
||||
/// Parses a string `string` to return a value of [`RangeConverter`]
|
||||
///
|
||||
/// If parsing succeeds, return the value inside [`Ok`], otherwise
|
||||
/// when the string is ill-formatted return an error specific to the
|
||||
/// inside [`Err`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::str::FromStr;
|
||||
/// use puzzle_2023_day_5::RangeConverter;
|
||||
///
|
||||
/// let string = "50 98 2 ";
|
||||
/// let expected_result = RangeConverter {
|
||||
/// source_range: 98..100,
|
||||
/// destination_range: 50..52,
|
||||
/// };
|
||||
/// let actual_result = RangeConverter::from_str(string).unwrap();
|
||||
///
|
||||
/// assert_eq!(actual_result, expected_result);
|
||||
/// ```
|
||||
fn from_str(string: &str) -> Result<Self, Self::Err> {
|
||||
let numbers = string
|
||||
.trim()
|
||||
.split_ascii_whitespace()
|
||||
.map(|string| {
|
||||
let result: usize = string.trim().parse().unwrap_or_default();
|
||||
result
|
||||
})
|
||||
.collect::<Vec<usize>>();
|
||||
let destination_range_start = *numbers.first().unwrap_or(&0);
|
||||
let source_range_start = *numbers.get(1).unwrap_or(&0);
|
||||
let range_length = *numbers.get(2).unwrap_or(&0);
|
||||
let result = RangeConverter {
|
||||
source_range: source_range_start..(source_range_start + range_length),
|
||||
destination_range: destination_range_start..(destination_range_start + range_length),
|
||||
};
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, PartialEq, Clone)]
|
||||
pub struct CategoryConverter {
|
||||
pub name: String,
|
||||
pub ranges_converters: Vec<RangeConverter>,
|
||||
}
|
||||
|
||||
impl FromStr for CategoryConverter {
|
||||
type Err = &'static str;
|
||||
|
||||
/// Parses a string `string` to return a value of [`CategoryConverter`]
|
||||
///
|
||||
/// If parsing succeeds, return the value inside [`Ok`], otherwise
|
||||
/// when the string is ill-formatted return an error specific to the
|
||||
/// inside [`Err`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::str::FromStr;
|
||||
/// use puzzle_2023_day_5::{CategoryConverter, RangeConverter};
|
||||
///
|
||||
/// let string = "
|
||||
/// seed-to-soil map:
|
||||
/// 50 98 2
|
||||
/// 52 50 48
|
||||
/// ";
|
||||
/// let expected_result = CategoryConverter {
|
||||
/// name: String::from("seed-to-soil map:"),
|
||||
/// ranges_converters: vec![
|
||||
/// RangeConverter {
|
||||
/// source_range: 98..100,
|
||||
/// destination_range: 50..52,
|
||||
/// },
|
||||
/// RangeConverter {
|
||||
/// source_range: 50..98,
|
||||
/// destination_range: 52..100,
|
||||
/// },
|
||||
/// ],
|
||||
/// };
|
||||
/// let actual_result = CategoryConverter::from_str(string).unwrap();
|
||||
///
|
||||
/// assert_eq!(actual_result, expected_result);
|
||||
/// ```
|
||||
fn from_str(string: &str) -> Result<Self, Self::Err> {
|
||||
let mut lines = string.trim().lines();
|
||||
let name = lines.next().unwrap_or_default();
|
||||
let mut ranges_converters = vec![];
|
||||
for line in lines {
|
||||
ranges_converters.push(RangeConverter::from_str(line).unwrap_or_default());
|
||||
}
|
||||
let result = CategoryConverter {
|
||||
name: String::from(name),
|
||||
ranges_converters,
|
||||
};
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
impl CategoryConverter {
|
||||
pub fn convert(&self, number: usize) -> usize {
|
||||
self.ranges_converters
|
||||
.iter()
|
||||
.find_map(|range_converter| {
|
||||
if range_converter.source_range.contains(&number) {
|
||||
Some(
|
||||
range_converter.destination_range.start
|
||||
+ (number - range_converter.source_range.start),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.unwrap_or(number)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, PartialEq, Clone)]
|
||||
pub struct Almanac {
|
||||
pub seeds: Vec<usize>,
|
||||
pub categories_converters: Vec<CategoryConverter>,
|
||||
}
|
||||
|
||||
impl FromStr for Almanac {
|
||||
type Err = &'static str;
|
||||
|
||||
/// Parses a string `string` to return a value of [`Almanac`]
|
||||
///
|
||||
/// If parsing succeeds, return the value inside [`Ok`], otherwise
|
||||
/// when the string is ill-formatted return an error specific to the
|
||||
/// inside [`Err`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::str::FromStr;
|
||||
/// use puzzle_2023_day_5::{Almanac, CategoryConverter, RangeConverter};
|
||||
///
|
||||
/// let string = "
|
||||
/// seeds: 79 14 55 13
|
||||
///
|
||||
/// seed-to-soil map:
|
||||
/// 50 98 2
|
||||
/// 52 50 48
|
||||
/// ";
|
||||
/// let expected_result = Almanac {
|
||||
/// seeds: vec![79, 14, 55, 13],
|
||||
/// categories_converters: vec![CategoryConverter {
|
||||
/// name: String::from("seed-to-soil map:"),
|
||||
/// ranges_converters: vec![
|
||||
/// RangeConverter {
|
||||
/// source_range: 98..100,
|
||||
/// destination_range: 50..52,
|
||||
/// },
|
||||
/// RangeConverter {
|
||||
/// source_range: 50..98,
|
||||
/// destination_range: 52..100,
|
||||
/// },
|
||||
/// ],
|
||||
/// }],
|
||||
/// };
|
||||
/// let actual_result = Almanac::from_str(string).unwrap();
|
||||
///
|
||||
/// assert_eq!(actual_result, expected_result);
|
||||
/// ```
|
||||
fn from_str(string: &str) -> Result<Self, Self::Err> {
|
||||
let mut categories = string.trim().split("\n\n");
|
||||
let seeds = categories
|
||||
.next()
|
||||
.unwrap_or_default()
|
||||
.strip_prefix("seeds: ")
|
||||
.unwrap_or_default()
|
||||
.split_ascii_whitespace()
|
||||
.map(|string| {
|
||||
let result: usize = string.trim().parse().unwrap_or_default();
|
||||
result
|
||||
})
|
||||
.collect::<Vec<usize>>();
|
||||
let categories_converters = categories
|
||||
.map(|category_string| CategoryConverter::from_str(category_string).unwrap_or_default())
|
||||
.collect::<Vec<CategoryConverter>>();
|
||||
let result = Almanac {
|
||||
seeds,
|
||||
categories_converters,
|
||||
};
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
impl Almanac {
|
||||
pub fn minimum_location(&self) -> usize {
|
||||
self.seeds
|
||||
.par_iter()
|
||||
.map(|&seed| {
|
||||
self.categories_converters
|
||||
.iter()
|
||||
.fold(seed, |accumulator, category_converter| {
|
||||
category_converter.convert(accumulator)
|
||||
})
|
||||
})
|
||||
.progress()
|
||||
.min()
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn set_seeds_as_range_pairs(&mut self) {
|
||||
self.seeds = self
|
||||
.seeds
|
||||
.par_chunks(2)
|
||||
.progress()
|
||||
.flat_map(|chunk| {
|
||||
if let [range_start, range_length] = chunk {
|
||||
let start = *range_start;
|
||||
let length = *range_length;
|
||||
let range = start..(start + length);
|
||||
range.into_iter()
|
||||
} else {
|
||||
let empty_range = 0..0;
|
||||
empty_range.into_iter()
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn part_1(input: &str) -> usize {
|
||||
let almanac = Almanac::from_str(input).unwrap_or_default();
|
||||
almanac.minimum_location()
|
||||
}
|
||||
|
||||
pub fn part_2(input: &str) -> usize {
|
||||
let mut almanac = Almanac::from_str(input).unwrap_or_default();
|
||||
almanac.set_seeds_as_range_pairs();
|
||||
almanac.minimum_location()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod puzzle_2023_day_5_tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_part_1_example() {
|
||||
assert_eq!(part_1(include_str!("../input_example_1.txt")), 35);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part_2_example() {
|
||||
assert_eq!(part_2(include_str!("../input_example_1.txt")), 46);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part_1() {
|
||||
assert_eq!(part_1(include_str!("../input.txt")), 313045984);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
/// Ignored because it is a expensive/slow test to run.
|
||||
fn test_part_2() {
|
||||
assert_eq!(part_2(include_str!("../input.txt")), 20283860);
|
||||
}
|
||||
}
|
8
advent_2023/puzzle_2023_day_5/src/main.rs
Normal file
8
advent_2023/puzzle_2023_day_5/src/main.rs
Normal file
@ -0,0 +1,8 @@
|
||||
use puzzle_2023_day_5::{part_1, part_2};
|
||||
|
||||
fn main() {
|
||||
let input = include_str!("../input.txt");
|
||||
println!("- Day 5 of 2023: If You Give A Seed A Fertilizer -");
|
||||
println!("Answer Part 1: {}", part_1(input));
|
||||
println!("Answer Part 2: {}", part_2(input));
|
||||
}
|
8
advent_2023/puzzle_2023_day_6/Cargo.toml
Normal file
8
advent_2023/puzzle_2023_day_6/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "puzzle_2023_day_6"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
|
||||
[dependencies]
|
||||
rayon = { workspace = true }
|
73
advent_2023/puzzle_2023_day_6/README.md
Normal file
73
advent_2023/puzzle_2023_day_6/README.md
Normal file
@ -0,0 +1,73 @@
|
||||
# - Day 6 àf 2023: Wait For It -
|
||||
|
||||
Source: <https://adventofcode.com/2023/day/6>
|
||||
|
||||
## Instructions - Part 1
|
||||
|
||||
The ferry quickly brings you across Island Island. After asking around, you discover that there is indeed normally a large pile of sand somewhere near here, but you don't see anything besides lots of water and the small island where the ferry has docked.
|
||||
|
||||
As you try to figure out what to do next, you notice a poster on a wall near the ferry dock. "Boat races! Open to the public! Grand prize is an all-expenses-paid trip to **Desert Island**!" That must be where the sand comes from! Best of all, the boat races are starting in just a few minutes.
|
||||
|
||||
You manage to sign up as a competitor in the boat races just in time. The organizer explains that it's not really a traditional race - instead, you will get a fixed amount of time during which your boat has to travel as far as it can, and you win if your boat goes the farthest.
|
||||
|
||||
As part of signing up, you get a sheet of paper (your puzzle input) that lists the **time** allowed for each race and also the best **distance** ever recorded in that race. To guarantee you win the grand prize, you need to make sure you **go farther in each race** than the current record holder.
|
||||
|
||||
The organizer brings you over to the area where the boat races are held. The boats are much smaller than you expected - they're actually **toy boats**, each with a big button on top. Holding down the button **charges the boat**, and releasing the button **allows the boat to move**. Boats move faster if their button was held longer, but time spent holding the button counts against the total race time. You can only hold the button at the start of the race, and boats don't move until the button is released.
|
||||
|
||||
For example:
|
||||
|
||||
```txt
|
||||
Time: 7 15 30
|
||||
Distance: 9 40 200
|
||||
```
|
||||
|
||||
This document describes three races:
|
||||
|
||||
- The first race lasts 7 milliseconds. The record distance in this race is 9 millimeters.
|
||||
- The second race lasts 15 milliseconds. The record distance in this race is 40 millimeters.
|
||||
- The third race lasts 30 milliseconds. The record distance in this race is 200 millimeters.
|
||||
|
||||
Your toy boat has a starting speed of **zero millimeters per millisecond**. For each whole millisecond you spend at the beginning of the race holding down the button, the boat's speed increases by **one millimeter per millisecond**.
|
||||
|
||||
So, because the first race lasts 7 milliseconds, you only have a few options:
|
||||
|
||||
- Don't hold the button at all (that is, hold it for **`0` milliseconds**) at the start of the race. The boat won't move; it will have traveled **`0` millimeters** by the end of the race.
|
||||
- Hold the button for **`1` millisecond** at the start of the race. Then, the boat will travel at a speed of 1 millimeter per millisecond for 6 milliseconds, reaching a total distance traveled of **`6` millimeters**.
|
||||
- Hold the button for **`2` milliseconds**, giving the boat a speed of 2 millimeters per millisecond. It will then get 5 milliseconds to move, reaching a total distance of **`10` millimeters**.
|
||||
- Hold the button for **`3` milliseconds**. After its remaining 4 milliseconds of travel time, the boat will have gone **`12` millimeters**.
|
||||
- Hold the button for **`4` milliseconds**. After its remaining 3 milliseconds of travel time, the boat will have gone **`12` millimeters**.
|
||||
- Hold the button for **`5` milliseconds**, causing the boat to travel a total of **`10` millimeters**.
|
||||
- Hold the button for **`6` milliseconds**, causing the boat to travel a total of **`6` millimeters**.
|
||||
- Hold the button for **`7` milliseconds**. That's the entire duration of the race. You never let go of the button. The boat can't move until you let go of the button. Please make sure you let go of the button so the boat gets to move. **`0` millimeters**.
|
||||
|
||||
Since the current record for this race is `9` millimeters, there are actually **`4`** different ways you could win: you could hold the button for `2`, `3`, `4`, or `5` milliseconds at the start of the race.
|
||||
|
||||
In the second race, you could hold the button for at least `4` milliseconds and at most `11` milliseconds and beat the record, a total of **`8`** different ways to win.
|
||||
|
||||
In the third race, you could hold the button for at least `11` milliseconds and no more than `19` milliseconds and still beat the record, a total of **`9`** ways you could win.
|
||||
|
||||
To see how much margin of error you have, determine the **number of ways you can beat the record** in each race; in this example, if you multiply these values together, you get **`288`** (`4` \* `8` \* `9`).
|
||||
|
||||
Determine the number of ways you could beat the record in each race. **What do you get if you multiply these numbers together?**
|
||||
|
||||
## Instructions - Part 2
|
||||
|
||||
As the race is about to start, you realize the piece of paper with race times and record distances you got earlier actually just has very bad [kerning](https://en.wikipedia.org/wiki/Kerning). There's really **only one race** - ignore the spaces between the numbers on each line.
|
||||
|
||||
So, the example from before:
|
||||
|
||||
```txt
|
||||
Time: 7 15 30
|
||||
Distance: 9 40 200
|
||||
```
|
||||
|
||||
...now instead means this:
|
||||
|
||||
```txt
|
||||
Time: 71530
|
||||
Distance: 940200
|
||||
```
|
||||
|
||||
Now, you have to figure out how many ways there are to win this single race. In this example, the race lasts for **`71530` milliseconds** and the record distance you need to beat is **`940200` millimeters**. You could hold the button anywhere from `14` to `71516` milliseconds and beat the record, a total of **`71503`** ways!
|
||||
|
||||
**How many ways can you beat the record in this one much longer race?**
|
2
advent_2023/puzzle_2023_day_6/input.txt
Normal file
2
advent_2023/puzzle_2023_day_6/input.txt
Normal file
@ -0,0 +1,2 @@
|
||||
Time: 38 94 79 70
|
||||
Distance: 241 1549 1074 1091
|
2
advent_2023/puzzle_2023_day_6/input_example_1.txt
Normal file
2
advent_2023/puzzle_2023_day_6/input_example_1.txt
Normal file
@ -0,0 +1,2 @@
|
||||
Time: 7 15 30
|
||||
Distance: 9 40 200
|
114
advent_2023/puzzle_2023_day_6/src/lib.rs
Normal file
114
advent_2023/puzzle_2023_day_6/src/lib.rs
Normal file
@ -0,0 +1,114 @@
|
||||
use rayon::prelude::*;
|
||||
|
||||
#[derive(Debug, Default, PartialEq, Clone)]
|
||||
pub struct Race {
|
||||
pub maximum_time_in_milliseconds: usize,
|
||||
pub best_distance_in_millimeters_recorded: usize,
|
||||
}
|
||||
|
||||
impl Race {
|
||||
pub fn get_all_winning_strategies(&self) -> Vec<RaceStrategy> {
|
||||
(1..self.maximum_time_in_milliseconds)
|
||||
.into_par_iter()
|
||||
.map(|time_in_milliseconds_holding_button| RaceStrategy {
|
||||
time_in_milliseconds_holding_button,
|
||||
maximum_time_in_milliseconds: self.maximum_time_in_milliseconds,
|
||||
})
|
||||
.filter(|race_strategy| {
|
||||
let distance_in_millimeters_travelled =
|
||||
race_strategy.calculate_distance_in_millimeters_travelled();
|
||||
distance_in_millimeters_travelled > self.best_distance_in_millimeters_recorded
|
||||
})
|
||||
.collect::<Vec<RaceStrategy>>()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, PartialEq, Clone)]
|
||||
pub struct RaceStrategy {
|
||||
pub time_in_milliseconds_holding_button: usize,
|
||||
pub maximum_time_in_milliseconds: usize,
|
||||
}
|
||||
|
||||
impl RaceStrategy {
|
||||
pub fn calculate_distance_in_millimeters_travelled(&self) -> usize {
|
||||
(self.maximum_time_in_milliseconds - self.time_in_milliseconds_holding_button)
|
||||
* self.time_in_milliseconds_holding_button
|
||||
}
|
||||
}
|
||||
|
||||
pub fn part_1(input: &str) -> usize {
|
||||
fn get_numbers_from_line(line: &str) -> Vec<usize> {
|
||||
line.split(':')
|
||||
.last()
|
||||
.unwrap_or_default()
|
||||
.split_ascii_whitespace()
|
||||
.map(|value| value.trim())
|
||||
.filter(|value| !value.is_empty())
|
||||
.map(|value| {
|
||||
let result: usize = value.parse().unwrap_or_default();
|
||||
result
|
||||
})
|
||||
.collect::<Vec<usize>>()
|
||||
}
|
||||
|
||||
let mut lines = input.trim().lines();
|
||||
let maximum_times = get_numbers_from_line(lines.next().unwrap_or_default());
|
||||
let best_distances = get_numbers_from_line(lines.next().unwrap_or_default());
|
||||
maximum_times
|
||||
.iter()
|
||||
.zip(best_distances.iter())
|
||||
.map(
|
||||
|(&maximum_time_in_milliseconds, &best_distance_recorded_in_millimeters)| Race {
|
||||
maximum_time_in_milliseconds,
|
||||
best_distance_in_millimeters_recorded: best_distance_recorded_in_millimeters,
|
||||
},
|
||||
)
|
||||
.map(|race| race.get_all_winning_strategies().len())
|
||||
.product()
|
||||
}
|
||||
|
||||
pub fn part_2(input: &str) -> usize {
|
||||
fn get_number_from_line(line: &str) -> usize {
|
||||
line.split(':')
|
||||
.last()
|
||||
.unwrap_or_default()
|
||||
.replace(' ', "")
|
||||
.trim()
|
||||
.parse()
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
let mut lines = input.trim().lines();
|
||||
let race = Race {
|
||||
maximum_time_in_milliseconds: get_number_from_line(lines.next().unwrap_or_default()),
|
||||
best_distance_in_millimeters_recorded: get_number_from_line(
|
||||
lines.next().unwrap_or_default(),
|
||||
),
|
||||
};
|
||||
race.get_all_winning_strategies().len()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod puzzle_2023_day_6_tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_part_1_example() {
|
||||
assert_eq!(part_1(include_str!("../input_example_1.txt")), 288);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part_2_example() {
|
||||
assert_eq!(part_2(include_str!("../input_example_1.txt")), 71503);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part_1() {
|
||||
assert_eq!(part_1(include_str!("../input.txt")), 1083852);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part_2() {
|
||||
assert_eq!(part_2(include_str!("../input.txt")), 23501589);
|
||||
}
|
||||
}
|
8
advent_2023/puzzle_2023_day_6/src/main.rs
Normal file
8
advent_2023/puzzle_2023_day_6/src/main.rs
Normal file
@ -0,0 +1,8 @@
|
||||
use puzzle_2023_day_6::{part_1, part_2};
|
||||
|
||||
fn main() {
|
||||
let input = include_str!("../input.txt");
|
||||
println!("- Day 6 of 2023: Wait For It -");
|
||||
println!("Answer Part 1: {}", part_1(input));
|
||||
println!("Answer Part 2: {}", part_2(input));
|
||||
}
|
8
advent_2023/puzzle_2023_day_7/Cargo.toml
Normal file
8
advent_2023/puzzle_2023_day_7/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "puzzle_2023_day_7"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
|
||||
[dependencies]
|
||||
array-init = { workspace = true }
|
87
advent_2023/puzzle_2023_day_7/README.md
Normal file
87
advent_2023/puzzle_2023_day_7/README.md
Normal file
@ -0,0 +1,87 @@
|
||||
# - Day 7 of 2023: Camel Cards -
|
||||
|
||||
Source: <https://adventofcode.com/2023/day/7>
|
||||
|
||||
## Instructions - Part 1
|
||||
|
||||
Your all-expenses-paid trip turns out to be a one-way, five-minute ride in an [airship](https://en.wikipedia.org/wiki/Airship). (At least it's a **cool** airship!) It drops you off at the edge of a vast desert and descends back to Island Island.
|
||||
|
||||
"Did you bring the parts?"
|
||||
|
||||
You turn around to see an Elf completely covered in white clothing, wearing goggles, and riding a large [camel](https://en.wikipedia.org/wiki/Dromedary).
|
||||
|
||||
"Did you bring the parts?" she asks again, louder this time. You aren't sure what parts she's looking for; you're here to figure out why the sand stopped.
|
||||
|
||||
"The parts! For the sand, yes! Come with me; I will show you." She beckons you onto the camel.
|
||||
|
||||
After riding a bit across the sands of Desert Island, you can see what look like very large rocks covering half of the horizon. The Elf explains that the rocks are all along the part of Desert Island that is directly above Island Island, making it hard to even get there. Normally, they use big machines to move the rocks and filter the sand, but the machines have broken down because Desert Island recently stopped receiving the **parts** they need to fix the machines.
|
||||
|
||||
You've already assumed it'll be your job to figure out why the parts stopped when she asks if you can help. You agree automatically.
|
||||
|
||||
Because the journey will take a few days, she offers to teach you the game of **Camel Cards**. Camel Cards is sort of similar to [poker](https://en.wikipedia.org/wiki/List_of_poker_hands) except it's designed to be easier to play while riding a camel.
|
||||
|
||||
In Camel Cards, you get a list of **hands**, and your goal is to order them based on the **strength** of each hand. A hand consists of **five cards** labeled one of `A`, `K`, `Q`, `J`, `T`, `9`, `8`, `7`, `6`, `5`, `4`, `3`, or `2`. The relative strength of each card follows this order, where `A` is the highest and `2` is the lowest.
|
||||
|
||||
Every hand is exactly one **type**. From strongest to weakest, they are:
|
||||
|
||||
- **Five of a kind**, where all five cards have the same label: `AAAAA`
|
||||
- **Four of a kind**, where four cards have the same label and one card has a different label: `AA8AA`
|
||||
- **Full house**, where three cards have the same label, and the remaining two cards share a different label: `23332`
|
||||
- **Three of a kind**, where three cards have the same label, and the remaining two cards are each different from any other card in the hand: `TTT98`
|
||||
- **Two pair**, where two cards share one label, two other cards share a second label, and the remaining card has a third label: `23432`
|
||||
- **One pair**, where two cards share one label, and the other three cards have a different label from the pair and each other: `A23A4`
|
||||
- **High card**, where all cards' labels are distinct: `23456`
|
||||
|
||||
Hands are primarily ordered based on type; for example, every **full house** is stronger than any **three of a kind**.
|
||||
|
||||
If two hands have the same type, a second ordering rule takes effect. Start by comparing the **first card in each hand**. If these cards are different, the hand with the stronger first card is considered stronger. If the first card in each hand have the **same label**, however, then move on to considering the **second card in each hand**. If they differ, the hand with the higher second card wins; otherwise, continue with the third card in each hand, then the fourth, then the fifth.
|
||||
|
||||
So, `33332` and `2AAAA` are both **four of a kind** hands, but `33332` is stronger because its first card is stronger. Similarly, `77888` and `77788` are both a **full house**, but `77888` is stronger because its third card is stronger (and both hands have the same first and second card).
|
||||
|
||||
To play Camel Cards, you are given a list of hands and their corresponding **bid** (your puzzle input). For example:
|
||||
|
||||
```txt
|
||||
32T3K 765
|
||||
T55J5 684
|
||||
KK677 28
|
||||
KTJJT 220
|
||||
QQQJA 483
|
||||
```
|
||||
|
||||
This example shows five hands; each hand is followed by its **bid** amount. Each hand wins an amount equal to its bid multiplied by its **rank**, where the weakest hand gets rank 1, the second-weakest hand gets rank 2, and so on up to the strongest hand. Because there are five hands in this example, the strongest hand will have rank 5 and its bid will be multiplied by 5.
|
||||
|
||||
So, the first step is to put the hands in order of strength:
|
||||
|
||||
- `32T3K` is the only **one pair** and the other hands are all a stronger type, so it gets rank **`1`**.
|
||||
- `KK677` and `KTJJT` are both **two pair**. Their first cards both have the same label, but the second card of `KK677` is stronger (`K` vs `T`), so `KTJJT` gets rank **`2`** and `KK677` gets rank **`3`**.
|
||||
- `T55J5` and `QQQJA` are both **three of a kind**. `QQQJA` has a stronger first card, so it gets rank **`5`** and `T55J5` gets rank **`4`**.
|
||||
|
||||
Now, you can determine the total winnings of this set of hands by adding up the result of multiplying each hand's bid with its rank (`765` \* 1 + `220` \* 2 + `28` \* 3 + `684` \* 4 + `483` \* 5). So the **total winnings** in this example are **`6440`**.
|
||||
|
||||
Find the rank of every hand in your set. **What are the total winnings?**
|
||||
|
||||
## Instructions - Part 2
|
||||
|
||||
To make things a little more interesting, the Elf introduces one additional rule. Now, `J` cards are [jokers](<https://en.wikipedia.org/wiki/Joker_(playing_card)>) - wildcards that can act like whatever card would make the hand the strongest type possible.
|
||||
|
||||
To balance this, **`J` cards are now the weakest** individual cards, weaker even than `2`. The other cards stay in the same order: `A`, `K`, `Q`, `T`, `9`, `8`, `7`, `6`, `5`, `4`, `3`, `2`, `J`.
|
||||
|
||||
`J` cards can pretend to be whatever card is best for the purpose of determining hand type; for example, `QJJQ2` is now considered **four of a kind**. However, for the purpose of breaking ties between two hands of the same type, `J` is always treated as `J`, not the card it's pretending to be: `JKKK2` is weaker than `QQQQ2` because `J` is weaker than `Q`.
|
||||
|
||||
Now, the above example goes very differently:
|
||||
|
||||
```txt
|
||||
32T3K 765
|
||||
T55J5 684
|
||||
KK677 28
|
||||
KTJJT 220
|
||||
QQQJA 483
|
||||
```
|
||||
|
||||
- `2T3K` is still the only **one pair**; it doesn't contain any jokers, so its strength doesn't increase.
|
||||
- `KK677` is now the only **two pair**, making it the second-weakest hand.
|
||||
- `T55J5`, `KTJJT`, and `QQQJA` are now all **four of a kind**! `T55J5` gets rank 3, `QQQJA` gets rank 4, and `KTJJT` gets rank 5.
|
||||
|
||||
With the new joker rule, the total winnings in this example are **`5905`**.
|
||||
|
||||
Using the new joker rule, find the rank of every hand in your set. **What are the new total winnings?**
|
1000
advent_2023/puzzle_2023_day_7/input.txt
Normal file
1000
advent_2023/puzzle_2023_day_7/input.txt
Normal file
File diff suppressed because it is too large
Load Diff
5
advent_2023/puzzle_2023_day_7/input_example_1.txt
Normal file
5
advent_2023/puzzle_2023_day_7/input_example_1.txt
Normal file
@ -0,0 +1,5 @@
|
||||
32T3K 765
|
||||
T55J5 684
|
||||
KK677 28
|
||||
KTJJT 220
|
||||
QQQJA 483
|
282
advent_2023/puzzle_2023_day_7/src/lib.rs
Normal file
282
advent_2023/puzzle_2023_day_7/src/lib.rs
Normal file
@ -0,0 +1,282 @@
|
||||
use core::str::FromStr;
|
||||
use std::{cmp::Ordering, collections::HashMap};
|
||||
|
||||
#[derive(Debug, Default, PartialEq, Eq, Clone)]
|
||||
pub struct Card {
|
||||
pub label: char,
|
||||
}
|
||||
|
||||
impl Card {
|
||||
const LABELS: [char; 13] = [
|
||||
'A', 'K', 'Q', 'J', 'T', '9', '8', '7', '6', '5', '4', '3', '2',
|
||||
];
|
||||
|
||||
pub fn strength(&self) -> usize {
|
||||
Card::LABELS.len()
|
||||
- Card::LABELS
|
||||
.iter()
|
||||
.position(|¤t| current == self.label)
|
||||
.unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Card {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.strength().cmp(&other.strength())
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for Card {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<char> for Card {
|
||||
fn from(label: char) -> Self {
|
||||
Card { label }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, PartialEq, Eq, Copy, Clone)]
|
||||
pub enum CardsHandType {
|
||||
#[default]
|
||||
HighCard = 1,
|
||||
OnePair = 2,
|
||||
TwoPair = 3,
|
||||
ThreeOfAKind = 4,
|
||||
FullHouse = 5,
|
||||
FourOfAKind = 6,
|
||||
FiveOfAKind = 7,
|
||||
}
|
||||
|
||||
impl CardsHandType {
|
||||
pub const fn strength(&self) -> usize {
|
||||
*self as usize
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for CardsHandType {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.strength().cmp(&other.strength())
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for CardsHandType {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, PartialEq, Eq, Clone)]
|
||||
pub struct CardsHand {
|
||||
pub cards: [Card; 5],
|
||||
pub bid: usize,
|
||||
}
|
||||
|
||||
impl CardsHand {
|
||||
pub fn hand_type(&self) -> CardsHandType {
|
||||
let mut label_counts: HashMap<char, usize> = HashMap::new();
|
||||
for card in &self.cards {
|
||||
if let Some(label_count) = label_counts.get_mut(&card.label) {
|
||||
*label_count += 1;
|
||||
} else {
|
||||
label_counts.insert(card.label, 1);
|
||||
}
|
||||
}
|
||||
let keys = label_counts.keys();
|
||||
if keys.len() == 1 {
|
||||
return CardsHandType::FiveOfAKind;
|
||||
}
|
||||
if keys.len() == 2 && label_counts.iter().any(|(_, &value)| value == 4) {
|
||||
return CardsHandType::FourOfAKind;
|
||||
}
|
||||
if keys.len() == 2 && label_counts.iter().any(|(_, &value)| value == 3) {
|
||||
return CardsHandType::FullHouse;
|
||||
}
|
||||
if keys.len() == 3 && label_counts.iter().any(|(_, &value)| value == 3) {
|
||||
return CardsHandType::ThreeOfAKind;
|
||||
}
|
||||
if keys.len() == 3 && label_counts.iter().any(|(_, &value)| value == 2) {
|
||||
return CardsHandType::TwoPair;
|
||||
}
|
||||
if keys.len() == 5 {
|
||||
return CardsHandType::HighCard;
|
||||
}
|
||||
CardsHandType::OnePair
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for CardsHand {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
if self.hand_type() != other.hand_type() {
|
||||
return self
|
||||
.hand_type()
|
||||
.strength()
|
||||
.cmp(&other.hand_type().strength());
|
||||
}
|
||||
for (self_card, other_card) in self.cards.iter().zip(other.cards.iter()) {
|
||||
if self_card != other_card {
|
||||
return self_card.cmp(other_card);
|
||||
}
|
||||
}
|
||||
Ordering::Equal
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for CardsHand {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for CardsHand {
|
||||
type Err = &'static str;
|
||||
|
||||
/// Parses a string `string` to return a value of [`CardsHand`]
|
||||
///
|
||||
/// If parsing succeeds, return the value inside [`Ok`], otherwise
|
||||
/// when the string is ill-formatted return an error specific to the
|
||||
/// inside [`Err`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::str::FromStr;
|
||||
/// use puzzle_2023_day_7::{Card, CardsHand, CardsHandType};
|
||||
///
|
||||
/// let string = "32T3K 765";
|
||||
/// let expected_result = CardsHand {
|
||||
/// cards: [Card { label: '3' }, Card { label: '2' }, Card { label: 'T' }, Card { label: '3' }, Card { label: 'K' } ],
|
||||
/// bid: 765,
|
||||
/// };
|
||||
///
|
||||
/// let actual_result = CardsHand::from_str(string).unwrap();
|
||||
/// let actual_hand_type = actual_result.hand_type();
|
||||
/// assert_eq!(actual_result, expected_result);
|
||||
/// ```
|
||||
fn from_str(string: &str) -> Result<Self, Self::Err> {
|
||||
let mut input = string.split_ascii_whitespace();
|
||||
let result = CardsHand {
|
||||
cards: array_init::from_iter(input.next().unwrap_or_default().chars().map(Card::from))
|
||||
.unwrap_or_default(),
|
||||
bid: input
|
||||
.next()
|
||||
.unwrap_or_default()
|
||||
.trim()
|
||||
.parse()
|
||||
.unwrap_or_default(),
|
||||
};
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, PartialEq, Eq, Clone)]
|
||||
pub struct CamelCards {
|
||||
cards_hands: Vec<CardsHand>,
|
||||
}
|
||||
|
||||
impl FromStr for CamelCards {
|
||||
type Err = &'static str;
|
||||
|
||||
fn from_str(string: &str) -> Result<Self, Self::Err> {
|
||||
Ok(CamelCards {
|
||||
cards_hands: string
|
||||
.trim()
|
||||
.lines()
|
||||
.map(|line| CardsHand::from_str(line.trim()).unwrap_or_default())
|
||||
.collect::<Vec<CardsHand>>(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn part_1(input: &str) -> usize {
|
||||
let mut camel_cards = CamelCards::from_str(input).unwrap_or_default();
|
||||
camel_cards.cards_hands.sort();
|
||||
camel_cards
|
||||
.cards_hands
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, card_hand)| {
|
||||
let rank = index + 1;
|
||||
card_hand.bid * rank
|
||||
})
|
||||
.sum()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod puzzle_2023_day_7_tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_part_1_example() {
|
||||
assert_eq!(part_1(include_str!("../input_example_1.txt")), 6440);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part_1() {
|
||||
assert_eq!(part_1(include_str!("../input.txt")), 250370104);
|
||||
}
|
||||
|
||||
mod hand_types {
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::{CardsHand, CardsHandType};
|
||||
|
||||
#[test]
|
||||
fn test_five_of_a_kind() {
|
||||
let cards_hand = CardsHand::from_str("AAAAA").unwrap();
|
||||
let expected = CardsHandType::FiveOfAKind;
|
||||
let actual = cards_hand.hand_type();
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_four_of_a_kind() {
|
||||
let cards_hand = CardsHand::from_str("AA8AA").unwrap();
|
||||
let expected = CardsHandType::FourOfAKind;
|
||||
let actual = cards_hand.hand_type();
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_full_house() {
|
||||
let cards_hand = CardsHand::from_str("23332").unwrap();
|
||||
let expected = CardsHandType::FullHouse;
|
||||
let actual = cards_hand.hand_type();
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_three_of_a_kind() {
|
||||
let cards_hand = CardsHand::from_str("TTT98").unwrap();
|
||||
let expected = CardsHandType::ThreeOfAKind;
|
||||
let actual = cards_hand.hand_type();
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_two_pair() {
|
||||
let cards_hand = CardsHand::from_str("23432").unwrap();
|
||||
let expected = CardsHandType::TwoPair;
|
||||
let actual = cards_hand.hand_type();
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_one_pair() {
|
||||
let cards_hand = CardsHand::from_str("A23A4").unwrap();
|
||||
let expected = CardsHandType::OnePair;
|
||||
let actual = cards_hand.hand_type();
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_high_card() {
|
||||
let cards_hand = CardsHand::from_str("23456").unwrap();
|
||||
let expected = CardsHandType::HighCard;
|
||||
let actual = cards_hand.hand_type();
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
}
|
||||
}
|
8
advent_2023/puzzle_2023_day_7/src/main.rs
Normal file
8
advent_2023/puzzle_2023_day_7/src/main.rs
Normal file
@ -0,0 +1,8 @@
|
||||
use puzzle_2023_day_7::part_1;
|
||||
|
||||
fn main() {
|
||||
let input = include_str!("../input.txt");
|
||||
println!("- Day 7 of 2023: Camel Cards -");
|
||||
println!("Answer Part 1: {}", part_1(input));
|
||||
// println!("Answer Part 2: {}", part_2(input));
|
||||
}
|
5
advent_2023/puzzle_2023_day_8/Cargo.toml
Normal file
5
advent_2023/puzzle_2023_day_8/Cargo.toml
Normal file
@ -0,0 +1,5 @@
|
||||
[package]
|
||||
name = "puzzle_2023_day_8"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
78
advent_2023/puzzle_2023_day_8/README.md
Normal file
78
advent_2023/puzzle_2023_day_8/README.md
Normal file
@ -0,0 +1,78 @@
|
||||
# - Day 8 of 2023: Haunted Wasteland -
|
||||
|
||||
Source: <https://adventofcode.com/2023/day/8>
|
||||
|
||||
## Instructions - Part 1
|
||||
|
||||
You're still riding a camel across Desert Island when you spot a sandstorm quickly approaching. When you turn to warn the Elf, she disappears before your eyes! To be fair, she had just finished warning you about **ghosts** a few minutes ago.
|
||||
|
||||
One of the camel's pouches is labeled "maps" - sure enough, it's full of documents (your puzzle input) about how to navigate the desert. At least, you're pretty sure that's what they are; one of the documents contains a list of left/right instructions, and the rest of the documents seem to describe some kind of **network** of labeled nodes.
|
||||
|
||||
It seems like you're meant to use the **left/right** instructions **to navigate the network**. Perhaps if you have the camel follow the same instructions, you can escape the haunted wasteland!
|
||||
|
||||
After examining the maps for a bit, two nodes stick out: `AAA` and `ZZZ`. You feel like `AAA` is where you are now, and you have to follow the left/right instructions until you reach `ZZZ`.
|
||||
|
||||
This format defines each node of the network individually. For example:
|
||||
|
||||
```txt
|
||||
RL
|
||||
|
||||
AAA = (BBB, CCC)
|
||||
BBB = (DDD, EEE)
|
||||
CCC = (ZZZ, GGG)
|
||||
DDD = (DDD, DDD)
|
||||
EEE = (EEE, EEE)
|
||||
GGG = (GGG, GGG)
|
||||
ZZZ = (ZZZ, ZZZ)
|
||||
```
|
||||
|
||||
Starting with `AAA`, you need to **look up the next element** based on the next left/right instruction in your input. In this example, start with `AAA` and go **right** (`R`) by choosing the right element of `AAA`, **`CCC`**. Then, `L` means to choose the **left** element of `CCC`, **`ZZZ`**. By following the left/right instructions, you reach `ZZZ` in **`2`** steps.
|
||||
|
||||
Of course, you might not find `ZZZ` right away. If you run out of left/right instructions, repeat the whole sequence of instructions as necessary: `RL` really means `RLRLRLRLRLRLRLRL...` and so on. For example, here is a situation that takes **`6`** steps to reach `ZZZ`:
|
||||
|
||||
```txt
|
||||
LLR
|
||||
|
||||
AAA = (BBB, BBB)
|
||||
BBB = (AAA, ZZZ)
|
||||
ZZZ = (ZZZ, ZZZ)
|
||||
```
|
||||
|
||||
Starting at `AAA`, follow the left/right instructions. **How many steps are required to reach `ZZZ`?**
|
||||
|
||||
## Instructions - Part 2
|
||||
|
||||
The sandstorm is upon you and you aren't any closer to escaping the wasteland. You had the camel follow the instructions, but you've barely left your starting position. It's going to take **significantly more steps** to escape!
|
||||
|
||||
What if the map isn't for people - what if the map is for **ghosts**? Are ghosts even bound by the laws of spacetime? Only one way to find out.
|
||||
|
||||
After examining the maps a bit longer, your attention is drawn to a curious fact: the number of nodes with names ending in `A` is equal to the number ending in `Z`! If you were a ghost, you'd probably just **start at every node that ends with `A`** and follow all of the paths at the same time until they all simultaneously end up at nodes that end with `Z`.
|
||||
|
||||
For example:
|
||||
|
||||
```txt
|
||||
LR
|
||||
|
||||
11A = (11B, XXX)
|
||||
11B = (XXX, 11Z)
|
||||
11Z = (11B, XXX)
|
||||
22A = (22B, XXX)
|
||||
22B = (22C, 22C)
|
||||
22C = (22Z, 22Z)
|
||||
22Z = (22B, 22B)
|
||||
XXX = (XXX, XXX)
|
||||
```
|
||||
|
||||
Here, there are two starting nodes, `11A` and `22A` (because they both end with `A`). As you follow each left/right instruction, use that instruction to **simultaneously** navigate away from both nodes you're currently on. Repeat this process until **all** of the nodes you're currently on end with `Z`. (If only some of the nodes you're on end with `Z`, they act like any other node and you continue as normal.) In this example, you would proceed as follows:
|
||||
|
||||
- Step 0: You are at `11A` and `22A`.
|
||||
- Step 1: You choose all of the **left** paths, leading you to `11B` and `22B`.
|
||||
- Step 2: You choose all of the **right** paths, leading you to **`11Z`** and `22C`.
|
||||
- Step 3: You choose all of the **left** paths, leading you to `11B` and **`22Z`**.
|
||||
- Step 4: You choose all of the **right** paths, leading you to **`11Z`** and `22B`.
|
||||
- Step 5: You choose all of the **left** paths, leading you to `11B` and `22C`.
|
||||
- Step 6: You choose all of the **right** paths, leading you to **`11Z`** and **`22Z`**.
|
||||
|
||||
So, in this example, you end up entirely on nodes that end in `Z` after **`6`** steps.
|
||||
|
||||
Simultaneously start on every node that ends with `A`. **How many steps does it take before you're only on nodes that end with `Z`?**
|
732
advent_2023/puzzle_2023_day_8/input.txt
Normal file
732
advent_2023/puzzle_2023_day_8/input.txt
Normal file
@ -0,0 +1,732 @@
|
||||
LLLLLLLRRRLRRRLRLRLRLRRLLRRRLRLLRRRLLRRLRRLRRLRLRRLRLRRRLRRLRLRRRLRRLRRLRLRRLLRLLRLRRRLRRLRLLLLRRLLLLRLRLRLRRRLRLRLLLRLRRRLRRRLRRRLRLRRLRRRLRLLLRLLRRLRRRLRRLRRLRRLRLRRRLRLRLRLLRRRLRRRLRRLRRRLLLRRLRRLRRRLRLRRRLRRRLRLRRLRRRLRLRRLRLRRLRRRLRLRRLRLLRRRLLRLRRLRRRLLLRLRRLRRRR
|
||||
|
||||
DGK = (KVQ, XHR)
|
||||
KTC = (TVB, MTH)
|
||||
CGR = (VVK, BKP)
|
||||
LCG = (FQC, KHX)
|
||||
PSZ = (FSF, QSM)
|
||||
FBJ = (FHP, SPX)
|
||||
KJD = (NRQ, VDH)
|
||||
NCM = (JPJ, KNG)
|
||||
TXH = (HNK, VHQ)
|
||||
NND = (TRC, DFM)
|
||||
JQN = (CNX, XLD)
|
||||
RHB = (CDG, GBT)
|
||||
JBN = (PXV, GVN)
|
||||
DFC = (JRN, TXH)
|
||||
TXG = (CHT, VBL)
|
||||
XXQ = (JDC, JGV)
|
||||
SVF = (FVD, LHQ)
|
||||
FVK = (LCG, RNB)
|
||||
XKT = (MPF, XJJ)
|
||||
MHB = (JSJ, VQM)
|
||||
FVC = (HXF, VVN)
|
||||
JJR = (VNS, SLM)
|
||||
RMT = (GDS, XHP)
|
||||
CHT = (PXS, VLF)
|
||||
SFJ = (XGC, LPM)
|
||||
BJL = (XDN, VXN)
|
||||
PQK = (NHS, DVB)
|
||||
PDB = (JPQ, TVJ)
|
||||
RGL = (DNN, NCN)
|
||||
KRN = (SBL, PHL)
|
||||
MTF = (PJL, KQR)
|
||||
BTL = (CCF, LDP)
|
||||
NLV = (CPM, HVL)
|
||||
GCQ = (QMF, JVH)
|
||||
KVH = (VKD, PQG)
|
||||
RLB = (GSS, JVP)
|
||||
QRB = (TNL, DKN)
|
||||
JFV = (RDR, NSB)
|
||||
BFC = (LGH, XLX)
|
||||
HGQ = (SLM, VNS)
|
||||
FQC = (VFQ, BXC)
|
||||
DDS = (XHR, KVQ)
|
||||
VQV = (SFT, BFQ)
|
||||
XFD = (HVV, FLH)
|
||||
TVP = (XQF, KSS)
|
||||
GBH = (NPX, LDB)
|
||||
KHL = (MGS, MMD)
|
||||
NPX = (BJL, SFF)
|
||||
VMG = (DHX, GVC)
|
||||
RTJ = (XRF, BPK)
|
||||
TLM = (NCG, QBB)
|
||||
LXS = (TVB, MTH)
|
||||
XNM = (QFL, KQK)
|
||||
KQR = (QRD, JBN)
|
||||
JQD = (DNN, NCN)
|
||||
QCF = (MXL, MXL)
|
||||
QMH = (NKG, SDJ)
|
||||
NKK = (MCB, RLB)
|
||||
MPJ = (BTL, JTF)
|
||||
TLS = (VPJ, LMD)
|
||||
XJB = (LML, TKZ)
|
||||
HGF = (HBF, QHB)
|
||||
KNJ = (QKM, XLR)
|
||||
XCF = (QCJ, HTN)
|
||||
HFS = (NKC, JFV)
|
||||
QLS = (QBB, NCG)
|
||||
QFL = (NXQ, QBN)
|
||||
MTH = (FLN, LQR)
|
||||
VND = (KMM, MQH)
|
||||
NQQ = (VVH, NDL)
|
||||
BTV = (QSM, FSF)
|
||||
SLT = (NRQ, VDH)
|
||||
NKG = (TBV, XCV)
|
||||
SLM = (LBN, HPK)
|
||||
CMQ = (KKS, VBH)
|
||||
JTF = (LDP, CCF)
|
||||
VFC = (GKH, KPS)
|
||||
KCC = (JVM, MTF)
|
||||
KFP = (MVX, NMX)
|
||||
NQF = (QSK, KCC)
|
||||
GGC = (VBV, TJR)
|
||||
QQS = (NKK, NQC)
|
||||
LXK = (FXC, QBC)
|
||||
DVQ = (TFF, LKB)
|
||||
PBL = (BGQ, FHQ)
|
||||
KHV = (BVJ, XSD)
|
||||
LDB = (SFF, BJL)
|
||||
RJG = (LJB, CJM)
|
||||
RCX = (QTB, PPL)
|
||||
FLH = (HSX, KVX)
|
||||
XTV = (HST, VCC)
|
||||
GDC = (CMH, NCT)
|
||||
RDP = (FKR, GHJ)
|
||||
NXM = (PVV, KRX)
|
||||
SCQ = (MFN, GRB)
|
||||
MRT = (XGT, VLK)
|
||||
DHJ = (XHP, GDS)
|
||||
XFL = (TJK, QMH)
|
||||
XQF = (CCQ, RPH)
|
||||
CLV = (CKD, CCD)
|
||||
CMT = (NCD, XDM)
|
||||
NCT = (SXG, CLF)
|
||||
JSS = (GMJ, LJC)
|
||||
TLQ = (CRC, DXQ)
|
||||
DMJ = (HHB, DRV)
|
||||
JBH = (FVC, HDX)
|
||||
QXK = (QSB, JBH)
|
||||
DQN = (QMD, GDN)
|
||||
SDH = (PRH, BCX)
|
||||
QSB = (HDX, FVC)
|
||||
MTP = (VVG, SPN)
|
||||
CTM = (MFG, GGJ)
|
||||
HND = (MNV, TXG)
|
||||
MJS = (DMJ, QQG)
|
||||
JNL = (LKB, TFF)
|
||||
QLL = (FKM, HNH)
|
||||
PNM = (PQR, NRL)
|
||||
VSF = (LPM, XGC)
|
||||
QBC = (QQS, MVF)
|
||||
BFM = (FBP, BQJ)
|
||||
KNG = (RTJ, CXN)
|
||||
VFQ = (HFS, LBS)
|
||||
LKB = (QVB, TXF)
|
||||
KQD = (CDJ, CDJ)
|
||||
ZZZ = (DHJ, RMT)
|
||||
XKX = (HVP, NJF)
|
||||
GSL = (QMS, DHM)
|
||||
PNT = (CDJ, GJZ)
|
||||
KBN = (CMQ, JBG)
|
||||
DNX = (SFM, GFJ)
|
||||
NMX = (XRR, LKL)
|
||||
VPJ = (PSK, GQL)
|
||||
XQD = (QCF, QCF)
|
||||
HRM = (RHB, XXJ)
|
||||
LCL = (MRT, FMB)
|
||||
DRG = (RNB, LCG)
|
||||
BKP = (QLL, MMQ)
|
||||
FSF = (SLR, XGV)
|
||||
KHX = (BXC, VFQ)
|
||||
SXG = (NHL, KGK)
|
||||
MJD = (TDH, RFP)
|
||||
NRL = (CSG, MPT)
|
||||
FBP = (QGC, GXH)
|
||||
HDT = (LHQ, FVD)
|
||||
BMP = (RMG, JXM)
|
||||
NCN = (SLT, KJD)
|
||||
NXQ = (JPP, QQL)
|
||||
NGV = (HNJ, VVQ)
|
||||
NPN = (MXL, NJK)
|
||||
FVD = (XBQ, NKF)
|
||||
GQM = (QCG, GGC)
|
||||
QBP = (XML, HND)
|
||||
VQT = (BTL, JTF)
|
||||
HKP = (CMH, NCT)
|
||||
JHP = (NDL, VVH)
|
||||
FRL = (SHD, FNH)
|
||||
FLN = (NVL, HGF)
|
||||
MXH = (QSD, KKR)
|
||||
BGL = (XCX, RFC)
|
||||
RSQ = (MKH, TLS)
|
||||
VML = (RJM, CXK)
|
||||
XHP = (MJS, DNP)
|
||||
GRV = (XRN, TVQ)
|
||||
GKH = (BCF, VSD)
|
||||
SPH = (MVX, NMX)
|
||||
TLD = (LFR, GFQ)
|
||||
LML = (QKS, NND)
|
||||
PKT = (VXC, CMF)
|
||||
LLQ = (THT, GRV)
|
||||
CKD = (SPB, QDV)
|
||||
KRM = (JQV, JNG)
|
||||
RNS = (HJJ, MLV)
|
||||
FKR = (FKK, BHN)
|
||||
XNH = (SCQ, KLF)
|
||||
GDN = (LBL, FHT)
|
||||
CRB = (NHQ, QRB)
|
||||
JKQ = (DPT, KBN)
|
||||
NJF = (RJG, NGF)
|
||||
NRT = (NSK, CSL)
|
||||
LJR = (VTT, HCQ)
|
||||
HLK = (DFC, DPV)
|
||||
PQR = (MPT, CSG)
|
||||
DNF = (NJF, HVP)
|
||||
MPV = (HJD, XSF)
|
||||
TBV = (XTJ, SVH)
|
||||
LKX = (XFJ, HBM)
|
||||
KTP = (CGR, RVR)
|
||||
HVL = (BJH, QXK)
|
||||
GJD = (XJJ, MPF)
|
||||
HLC = (VVQ, HNJ)
|
||||
JTX = (NCD, XDM)
|
||||
CSG = (MFF, RKT)
|
||||
PCH = (PGJ, GQM)
|
||||
SFF = (VXN, XDN)
|
||||
TCF = (KNG, JPJ)
|
||||
LDP = (XFD, SBS)
|
||||
XCR = (GJD, XKT)
|
||||
QBM = (GFB, LRH)
|
||||
CLP = (RJM, CXK)
|
||||
MTT = (HST, VCC)
|
||||
TQL = (BPM, GGT)
|
||||
LFR = (HNF, RDP)
|
||||
JHN = (CMT, JTX)
|
||||
XCX = (CHG, CHG)
|
||||
XGT = (HLK, QJF)
|
||||
TQS = (TKL, MNF)
|
||||
KFL = (HGQ, JJR)
|
||||
LHQ = (XBQ, NKF)
|
||||
CCQ = (DBP, HHC)
|
||||
TKL = (VDN, PBP)
|
||||
LBX = (BXM, SDH)
|
||||
XLX = (NGJ, LHJ)
|
||||
GVN = (BPG, TNK)
|
||||
CCX = (HCQ, VTT)
|
||||
KQK = (QBN, NXQ)
|
||||
NQC = (MCB, RLB)
|
||||
MPF = (DFT, SBG)
|
||||
BNH = (MLV, HJJ)
|
||||
CJM = (LBH, TNM)
|
||||
CND = (VKB, PGQ)
|
||||
HXM = (GMJ, LJC)
|
||||
TKZ = (NND, QKS)
|
||||
RKT = (LNQ, KFL)
|
||||
GXH = (RQP, LBX)
|
||||
TFF = (QVB, TXF)
|
||||
LNK = (FDC, MXH)
|
||||
KPK = (BNH, RNS)
|
||||
QQG = (HHB, DRV)
|
||||
MFP = (PQK, NBF)
|
||||
VVK = (QLL, MMQ)
|
||||
GFB = (RHN, LCN)
|
||||
PPD = (QCJ, HTN)
|
||||
FXV = (BPM, GGT)
|
||||
KSS = (CCQ, RPH)
|
||||
KCM = (LTB, PCH)
|
||||
RHN = (FXV, TQL)
|
||||
LFV = (DDJ, NQF)
|
||||
JKG = (BGQ, FHQ)
|
||||
MBS = (RQJ, LDQ)
|
||||
HHC = (NGV, HLC)
|
||||
CCD = (QDV, SPB)
|
||||
RFM = (FTB, HSB)
|
||||
QCG = (VBV, TJR)
|
||||
GRH = (LXK, LGQ)
|
||||
CDJ = (QQJ, BFC)
|
||||
THT = (TVQ, XRN)
|
||||
QRD = (PXV, GVN)
|
||||
VHQ = (SXV, GJL)
|
||||
MLV = (VRM, MCP)
|
||||
XRR = (CLV, PBJ)
|
||||
NMS = (DGK, DDS)
|
||||
JPS = (JKT, KHL)
|
||||
DJJ = (QMS, DHM)
|
||||
MFG = (TLQ, VQD)
|
||||
GPQ = (SHL, BNR)
|
||||
QVB = (GDC, HKP)
|
||||
LNN = (CMF, VXC)
|
||||
VBQ = (LNN, PKT)
|
||||
MMS = (SVV, HRM)
|
||||
BGJ = (HXM, JSS)
|
||||
QCK = (JSJ, VQM)
|
||||
PKB = (XNH, JQH)
|
||||
BCF = (TQR, TLL)
|
||||
JRN = (VHQ, HNK)
|
||||
SHL = (DMK, JBX)
|
||||
LRG = (NSK, CSL)
|
||||
NJV = (FJH, TXC)
|
||||
GHQ = (FSB, HFX)
|
||||
LHN = (TLS, MKH)
|
||||
HBF = (BMP, GLM)
|
||||
DTP = (DVQ, JNL)
|
||||
FXR = (FTB, HSB)
|
||||
PDS = (XLD, CNX)
|
||||
SXV = (CPC, JNF)
|
||||
QMF = (GGF, JDP)
|
||||
JVP = (GPC, DNX)
|
||||
RMG = (HRF, PKB)
|
||||
LRH = (LCN, RHN)
|
||||
HVP = (RJG, NGF)
|
||||
TRC = (VKX, RQL)
|
||||
PJL = (QRD, JBN)
|
||||
HNK = (GJL, SXV)
|
||||
CHM = (NBF, PQK)
|
||||
PGH = (KMM, MQH)
|
||||
SDN = (MFP, CHM)
|
||||
DMK = (VRP, NNX)
|
||||
MRR = (NGK, SMQ)
|
||||
QDV = (NDM, JPT)
|
||||
PGJ = (QCG, GGC)
|
||||
BVJ = (NLV, HBR)
|
||||
PGQ = (BGK, GBH)
|
||||
LKL = (CLV, PBJ)
|
||||
FDC = (KKR, QSD)
|
||||
JDP = (PDB, PTX)
|
||||
NJJ = (HSJ, GRH)
|
||||
TVJ = (HDT, SVF)
|
||||
NJK = (RBV, ZZZ)
|
||||
HHN = (DPP, TLD)
|
||||
QMS = (BLS, TQS)
|
||||
QVR = (CVB, BNJ)
|
||||
FFQ = (RMJ, HGZ)
|
||||
LGQ = (QBC, FXC)
|
||||
JPP = (RSG, KTG)
|
||||
DPV = (TXH, JRN)
|
||||
HBR = (CPM, HVL)
|
||||
NSK = (JQN, PDS)
|
||||
SBS = (HVV, FLH)
|
||||
BFQ = (VBQ, JPB)
|
||||
LBN = (LXJ, CCR)
|
||||
RBD = (KRM, PNX)
|
||||
NQX = (LML, LML)
|
||||
XSA = (QKS, NND)
|
||||
NDB = (HFX, FSB)
|
||||
QMD = (LBL, FHT)
|
||||
XTJ = (JDT, JDT)
|
||||
GLH = (SHL, BNR)
|
||||
FXC = (MVF, QQS)
|
||||
HSX = (NFN, LVG)
|
||||
JNF = (JJH, FNR)
|
||||
CXK = (SPC, TVP)
|
||||
GGF = (PDB, PTX)
|
||||
XBQ = (QNX, JCQ)
|
||||
LJC = (SFJ, VSF)
|
||||
MMD = (XLK, CND)
|
||||
HFG = (JKT, KHL)
|
||||
NHQ = (TNL, DKN)
|
||||
JVM = (KQR, PJL)
|
||||
CGH = (RTC, VFC)
|
||||
HNF = (GHJ, FKR)
|
||||
TMF = (NMS, GJH)
|
||||
NGJ = (NXM, BDB)
|
||||
MRM = (JKQ, MPS)
|
||||
QTC = (JSS, HXM)
|
||||
TNM = (JFF, QXR)
|
||||
DHK = (LJR, CCX)
|
||||
XSB = (MRR, CXC)
|
||||
XRN = (XDP, QBP)
|
||||
XCV = (XTJ, SVH)
|
||||
VVA = (QSM, FSF)
|
||||
NKC = (RDR, NSB)
|
||||
MXL = (RBV, RBV)
|
||||
PTX = (TVJ, JPQ)
|
||||
VRL = (NQX, XJB)
|
||||
RQK = (MPS, JKQ)
|
||||
PBJ = (CKD, CCD)
|
||||
VRP = (DQN, QLC)
|
||||
KLF = (MFN, GRB)
|
||||
XXJ = (GBT, CDG)
|
||||
HST = (QHV, MMS)
|
||||
SFT = (JPB, VBQ)
|
||||
NRR = (LCL, MQR)
|
||||
CSL = (JQN, PDS)
|
||||
LHJ = (BDB, NXM)
|
||||
TXK = (DHK, KLC)
|
||||
CDK = (XCX, XCX)
|
||||
FHT = (NGQ, JHN)
|
||||
QQJ = (LGH, XLX)
|
||||
BQJ = (GXH, QGC)
|
||||
TTA = (QKM, XLR)
|
||||
TVB = (FLN, LQR)
|
||||
PPL = (FRL, NCX)
|
||||
SPS = (XFJ, HBM)
|
||||
SVH = (JDT, VRL)
|
||||
QBB = (PXG, MTP)
|
||||
JSJ = (VVB, NRR)
|
||||
KKS = (RGL, JQD)
|
||||
JDT = (NQX, NQX)
|
||||
GKQ = (LLT, JRH)
|
||||
VVH = (BPT, KRN)
|
||||
JCQ = (CRB, PBS)
|
||||
QXR = (BTV, PSZ)
|
||||
VQR = (RCX, KKP)
|
||||
QSM = (SLR, XGV)
|
||||
JKD = (JDC, JGV)
|
||||
XLD = (LFS, QVR)
|
||||
TJK = (NKG, SDJ)
|
||||
PVV = (HDK, VQV)
|
||||
BDB = (PVV, KRX)
|
||||
MPS = (KBN, DPT)
|
||||
FHP = (PPD, XCF)
|
||||
HTN = (KCM, PXC)
|
||||
GHJ = (BHN, FKK)
|
||||
JCC = (LQM, KVH)
|
||||
LQR = (HGF, NVL)
|
||||
LGM = (DDJ, NQF)
|
||||
NJN = (QCF, NPN)
|
||||
PRH = (DFF, DFF)
|
||||
XDM = (FBJ, PJM)
|
||||
HFN = (KRS, XSB)
|
||||
GLM = (JXM, RMG)
|
||||
RQP = (BXM, SDH)
|
||||
BPG = (QJT, KTP)
|
||||
JPB = (LNN, PKT)
|
||||
DKN = (CJD, BGR)
|
||||
CDG = (GSL, DJJ)
|
||||
XDN = (CGM, VMG)
|
||||
NQP = (SKT, JCC)
|
||||
DNP = (QQG, DMJ)
|
||||
NNX = (DQN, QLC)
|
||||
FTB = (JFL, VJJ)
|
||||
FHQ = (SMJ, XFK)
|
||||
GGT = (KPK, LNT)
|
||||
NGF = (LJB, CJM)
|
||||
QFX = (KCN, TMF)
|
||||
NKF = (JCQ, QNX)
|
||||
DBP = (NGV, HLC)
|
||||
RBV = (RMT, DHJ)
|
||||
NML = (MBV, VCG)
|
||||
KXJ = (MXH, FDC)
|
||||
GFQ = (RDP, HNF)
|
||||
SHD = (CMG, CTM)
|
||||
GTX = (LNK, KXJ)
|
||||
HXF = (KTC, LXS)
|
||||
CMM = (NQP, SBR)
|
||||
SDJ = (TBV, XCV)
|
||||
CHG = (RMJ, RMJ)
|
||||
DPT = (CMQ, JBG)
|
||||
BGR = (RLM, NML)
|
||||
THM = (XQD, NJN)
|
||||
HJJ = (MCP, VRM)
|
||||
NRQ = (JHR, GCQ)
|
||||
KKR = (HSN, NJJ)
|
||||
KVX = (LVG, NFN)
|
||||
LTT = (TLD, DPP)
|
||||
NVL = (QHB, HBF)
|
||||
CXN = (XRF, BPK)
|
||||
KLC = (CCX, LJR)
|
||||
JDC = (DNF, XKX)
|
||||
MGS = (XLK, CND)
|
||||
RLM = (VCG, MBV)
|
||||
VDN = (NMQ, TPR)
|
||||
HSB = (JFL, VJJ)
|
||||
HDS = (KLC, DHK)
|
||||
XSD = (NLV, HBR)
|
||||
HJD = (NJQ, PBQ)
|
||||
CGM = (DHX, GVC)
|
||||
LDQ = (PBL, JKG)
|
||||
RDR = (XHQ, MGQ)
|
||||
GPC = (GFJ, SFM)
|
||||
NQT = (KRS, XSB)
|
||||
TDH = (RBD, XLP)
|
||||
QJF = (DFC, DPV)
|
||||
VNS = (HPK, LBN)
|
||||
QSD = (NJJ, HSN)
|
||||
JHR = (QMF, JVH)
|
||||
SMQ = (FXR, RFM)
|
||||
CMG = (MFG, GGJ)
|
||||
NKQ = (VFC, RTC)
|
||||
VXC = (LHN, RSQ)
|
||||
DHX = (LCT, XNM)
|
||||
TCX = (NQT, HFN)
|
||||
DRV = (TFN, QBM)
|
||||
JPT = (GQX, XCR)
|
||||
HRF = (JQH, XNH)
|
||||
MCS = (BGJ, QTC)
|
||||
PQG = (NCM, TCF)
|
||||
XHR = (PJK, VPN)
|
||||
MLX = (PGH, VND)
|
||||
MKH = (VPJ, LMD)
|
||||
TJR = (VQT, MPJ)
|
||||
VLF = (GLG, QFX)
|
||||
JNG = (KLR, MPV)
|
||||
HDK = (BFQ, SFT)
|
||||
HFX = (MLX, SPL)
|
||||
BXC = (HFS, LBS)
|
||||
CCT = (GTX, HPT)
|
||||
VLK = (HLK, QJF)
|
||||
NCD = (PJM, FBJ)
|
||||
VGT = (JNL, DVQ)
|
||||
LMD = (PSK, GQL)
|
||||
KRX = (HDK, VQV)
|
||||
QNX = (CRB, PBS)
|
||||
NJQ = (GHQ, NDB)
|
||||
TNV = (FBP, BQJ)
|
||||
GNR = (XQD, NJN)
|
||||
KKP = (QTB, PPL)
|
||||
DBX = (KCQ, CPS)
|
||||
VRM = (TLM, QLS)
|
||||
LVG = (BRP, NJV)
|
||||
NHL = (SPS, LKX)
|
||||
MNV = (VBL, CHT)
|
||||
PJK = (HHN, LTT)
|
||||
VBH = (JQD, RGL)
|
||||
GRB = (NKQ, CGH)
|
||||
SKT = (KVH, LQM)
|
||||
TPR = (RXR, KHV)
|
||||
VVB = (LCL, MQR)
|
||||
VKX = (MRM, RQK)
|
||||
LTB = (PGJ, GQM)
|
||||
QCJ = (KCM, PXC)
|
||||
BGQ = (SMJ, SMJ)
|
||||
RCV = (NQQ, JHP)
|
||||
DHM = (TQS, BLS)
|
||||
KRS = (CXC, MRR)
|
||||
JFL = (BLT, PNM)
|
||||
TXC = (NRT, LRG)
|
||||
MVX = (LKL, XRR)
|
||||
QSK = (JVM, MTF)
|
||||
BGK = (LDB, NPX)
|
||||
GJZ = (BFC, QQJ)
|
||||
PXC = (LTB, PCH)
|
||||
HMQ = (BGJ, QTC)
|
||||
RXR = (BVJ, XSD)
|
||||
BXM = (PRH, BCX)
|
||||
FJH = (LRG, NRT)
|
||||
GJH = (DGK, DDS)
|
||||
BPT = (SBL, PHL)
|
||||
RQL = (RQK, MRM)
|
||||
SJB = (RQJ, LDQ)
|
||||
NFN = (NJV, BRP)
|
||||
MND = (NQQ, JHP)
|
||||
NMQ = (KHV, RXR)
|
||||
XGV = (TXK, HDS)
|
||||
SPC = (KSS, XQF)
|
||||
RMJ = (SMR, QRS)
|
||||
CNX = (LFS, QVR)
|
||||
KLR = (HJD, XSF)
|
||||
XLP = (KRM, PNX)
|
||||
LPM = (CMM, PHF)
|
||||
FNR = (CCT, VTP)
|
||||
NGQ = (CMT, JTX)
|
||||
CCR = (BFM, TNV)
|
||||
LCN = (FXV, TQL)
|
||||
HVV = (HSX, KVX)
|
||||
FSB = (MLX, SPL)
|
||||
GGJ = (TLQ, VQD)
|
||||
NHS = (DRG, FVK)
|
||||
RQJ = (PBL, JKG)
|
||||
VCC = (MMS, QHV)
|
||||
HDX = (VVN, HXF)
|
||||
VQM = (NRR, VVB)
|
||||
TFN = (GFB, LRH)
|
||||
QRS = (VQR, MDS)
|
||||
HBM = (VTQ, SDN)
|
||||
CCF = (SBS, XFD)
|
||||
VCG = (HMQ, MCS)
|
||||
NBF = (DVB, NHS)
|
||||
DVB = (FVK, DRG)
|
||||
PGB = (TDH, RFP)
|
||||
XRF = (KFP, SPH)
|
||||
KMM = (PDJ, GQN)
|
||||
KTG = (GGQ, HNR)
|
||||
BJH = (JBH, QSB)
|
||||
JJH = (CCT, VTP)
|
||||
LBH = (JFF, JFF)
|
||||
GLG = (TMF, KCN)
|
||||
TQR = (THM, GNR)
|
||||
MQH = (GQN, PDJ)
|
||||
MQR = (FMB, MRT)
|
||||
FNH = (CTM, CMG)
|
||||
SMR = (VQR, MDS)
|
||||
GDS = (DNP, MJS)
|
||||
LCT = (KQK, QFL)
|
||||
VKB = (GBH, BGK)
|
||||
VTQ = (CHM, MFP)
|
||||
TNK = (QJT, KTP)
|
||||
HNJ = (VVS, GCX)
|
||||
JKT = (MMD, MGS)
|
||||
PBP = (TPR, NMQ)
|
||||
CPS = (KNJ, RFZ)
|
||||
RNB = (KHX, FQC)
|
||||
CMF = (LHN, RSQ)
|
||||
HPK = (CCR, LXJ)
|
||||
MFN = (NKQ, CGH)
|
||||
HHB = (QBM, TFN)
|
||||
DDJ = (QSK, KCC)
|
||||
DFM = (RQL, VKX)
|
||||
FKM = (GKQ, VJG)
|
||||
HSJ = (LGQ, LXK)
|
||||
HPT = (KXJ, LNK)
|
||||
BNR = (JBX, DMK)
|
||||
GJL = (CPC, JNF)
|
||||
DFF = (KCQ, KCQ)
|
||||
MCB = (GSS, JVP)
|
||||
CPC = (JJH, FNR)
|
||||
XLR = (MJK, DSM)
|
||||
SBG = (JDG, XFL)
|
||||
XSF = (NJQ, PBQ)
|
||||
NGK = (RFM, FXR)
|
||||
HSN = (GRH, HSJ)
|
||||
LQM = (PQG, VKD)
|
||||
VXN = (VMG, CGM)
|
||||
PSK = (VGT, DTP)
|
||||
JQH = (KLF, SCQ)
|
||||
RJM = (SPC, TVP)
|
||||
VSD = (TLL, TQR)
|
||||
KCN = (GJH, NMS)
|
||||
QHB = (GLM, BMP)
|
||||
FMB = (VLK, XGT)
|
||||
GBT = (DJJ, GSL)
|
||||
LGH = (NGJ, LHJ)
|
||||
SLR = (HDS, TXK)
|
||||
VVQ = (GCX, VVS)
|
||||
MDS = (RCX, KKP)
|
||||
KVQ = (VPN, PJK)
|
||||
CLF = (NHL, KGK)
|
||||
XFK = (KQD, PNT)
|
||||
CJD = (NML, RLM)
|
||||
MCP = (TLM, QLS)
|
||||
SPL = (PGH, VND)
|
||||
GSS = (GPC, DNX)
|
||||
RPH = (DBP, HHC)
|
||||
HNR = (XXQ, JKD)
|
||||
VBV = (VQT, MPJ)
|
||||
PHF = (NQP, SBR)
|
||||
BRP = (FJH, TXC)
|
||||
AAA = (RMT, DHJ)
|
||||
PBQ = (GHQ, NDB)
|
||||
PXG = (VVG, SPN)
|
||||
PNX = (JQV, JNG)
|
||||
XHQ = (SJB, MBS)
|
||||
VBL = (VLF, PXS)
|
||||
VVG = (MTT, XTV)
|
||||
PXS = (GLG, QFX)
|
||||
MMQ = (FKM, HNH)
|
||||
PHG = (HFN, NQT)
|
||||
MFF = (KFL, LNQ)
|
||||
PJM = (FHP, SPX)
|
||||
SMJ = (KQD, KQD)
|
||||
XGC = (CMM, PHF)
|
||||
PDJ = (QCK, MHB)
|
||||
SPN = (MTT, XTV)
|
||||
BPK = (KFP, SPH)
|
||||
MVF = (NQC, NKK)
|
||||
LJB = (LBH, LBH)
|
||||
GQN = (QCK, MHB)
|
||||
NCG = (MTP, PXG)
|
||||
GQL = (VGT, DTP)
|
||||
NCX = (FNH, SHD)
|
||||
HGZ = (QRS, SMR)
|
||||
GMJ = (VSF, SFJ)
|
||||
RFP = (XLP, RBD)
|
||||
TXF = (GDC, HKP)
|
||||
NBA = (SMR, QRS)
|
||||
QTB = (FRL, NCX)
|
||||
QLC = (GDN, QMD)
|
||||
QHV = (SVV, HRM)
|
||||
XTM = (GRV, THT)
|
||||
VPN = (HHN, LTT)
|
||||
RFZ = (XLR, QKM)
|
||||
CMH = (SXG, CLF)
|
||||
GFJ = (TCX, PHG)
|
||||
VTT = (LGM, LFV)
|
||||
RTC = (GKH, KPS)
|
||||
XFJ = (VTQ, SDN)
|
||||
GCX = (PGB, MJD)
|
||||
MJK = (CLP, VML)
|
||||
QQL = (RSG, KTG)
|
||||
NSB = (XHQ, MGQ)
|
||||
HCQ = (LGM, LFV)
|
||||
GQX = (GJD, XKT)
|
||||
RVR = (VVK, BKP)
|
||||
JBG = (KKS, VBH)
|
||||
JFF = (BTV, BTV)
|
||||
BPM = (LNT, KPK)
|
||||
LNQ = (JJR, HGQ)
|
||||
FKK = (GLH, GPQ)
|
||||
SBL = (CDK, BGL)
|
||||
LNT = (BNH, RNS)
|
||||
JRH = (JPS, HFG)
|
||||
VVS = (MJD, PGB)
|
||||
DPP = (LFR, GFQ)
|
||||
MNF = (PBP, VDN)
|
||||
QKM = (DSM, MJK)
|
||||
JPJ = (CXN, RTJ)
|
||||
QGC = (RQP, LBX)
|
||||
CVB = (MND, RCV)
|
||||
RFC = (CHG, FFQ)
|
||||
KPS = (BCF, VSD)
|
||||
XML = (MNV, TXG)
|
||||
JVH = (JDP, GGF)
|
||||
CRC = (XTM, LLQ)
|
||||
VJG = (JRH, LLT)
|
||||
SPB = (JPT, NDM)
|
||||
JGV = (XKX, DNF)
|
||||
GGQ = (XXQ, JKD)
|
||||
XLK = (PGQ, VKB)
|
||||
JBX = (NNX, VRP)
|
||||
RSG = (HNR, GGQ)
|
||||
GVC = (LCT, XNM)
|
||||
XDP = (XML, HND)
|
||||
CXC = (SMQ, NGK)
|
||||
PXV = (TNK, BPG)
|
||||
NDM = (XCR, GQX)
|
||||
CPM = (BJH, QXK)
|
||||
KGK = (LKX, SPS)
|
||||
BLT = (NRL, PQR)
|
||||
BHN = (GLH, GPQ)
|
||||
BLS = (TKL, MNF)
|
||||
PHL = (CDK, BGL)
|
||||
BCX = (DFF, DBX)
|
||||
HNH = (GKQ, VJG)
|
||||
VKD = (NCM, TCF)
|
||||
DSM = (VML, CLP)
|
||||
DNN = (SLT, KJD)
|
||||
SBR = (SKT, JCC)
|
||||
TNL = (BGR, CJD)
|
||||
DFT = (XFL, JDG)
|
||||
MPT = (RKT, MFF)
|
||||
TVQ = (XDP, QBP)
|
||||
LLT = (JPS, HFG)
|
||||
DXQ = (XTM, LLQ)
|
||||
SFM = (PHG, TCX)
|
||||
BNJ = (MND, RCV)
|
||||
PBS = (NHQ, QRB)
|
||||
JXM = (HRF, PKB)
|
||||
VTP = (HPT, GTX)
|
||||
SVV = (XXJ, RHB)
|
||||
MHA = (QQJ, BFC)
|
||||
MBV = (HMQ, MCS)
|
||||
VJJ = (BLT, PNM)
|
||||
QJT = (RVR, CGR)
|
||||
VVN = (LXS, KTC)
|
||||
QKS = (TRC, DFM)
|
||||
MGQ = (MBS, SJB)
|
||||
NDL = (BPT, KRN)
|
||||
JPQ = (SVF, HDT)
|
||||
VDH = (JHR, GCQ)
|
||||
KCQ = (KNJ, KNJ)
|
||||
XJJ = (DFT, SBG)
|
||||
JQV = (MPV, KLR)
|
||||
VQD = (DXQ, CRC)
|
||||
JDG = (TJK, QMH)
|
||||
SPX = (XCF, PPD)
|
||||
LXJ = (TNV, BFM)
|
||||
LBL = (NGQ, JHN)
|
||||
QBN = (QQL, JPP)
|
||||
LFS = (CVB, BNJ)
|
||||
LBS = (JFV, NKC)
|
||||
TLL = (THM, GNR)
|
9
advent_2023/puzzle_2023_day_8/input_example_1.txt
Normal file
9
advent_2023/puzzle_2023_day_8/input_example_1.txt
Normal file
@ -0,0 +1,9 @@
|
||||
RL
|
||||
|
||||
AAA = (BBB, CCC)
|
||||
BBB = (DDD, EEE)
|
||||
CCC = (ZZZ, GGG)
|
||||
DDD = (DDD, DDD)
|
||||
EEE = (EEE, EEE)
|
||||
GGG = (GGG, GGG)
|
||||
ZZZ = (ZZZ, ZZZ)
|
5
advent_2023/puzzle_2023_day_8/input_example_2.txt
Normal file
5
advent_2023/puzzle_2023_day_8/input_example_2.txt
Normal file
@ -0,0 +1,5 @@
|
||||
LLR
|
||||
|
||||
AAA = (BBB, BBB)
|
||||
BBB = (AAA, ZZZ)
|
||||
ZZZ = (ZZZ, ZZZ)
|
10
advent_2023/puzzle_2023_day_8/input_example_3.txt
Normal file
10
advent_2023/puzzle_2023_day_8/input_example_3.txt
Normal file
@ -0,0 +1,10 @@
|
||||
LR
|
||||
|
||||
11A = (11B, XXX)
|
||||
11B = (XXX, 11Z)
|
||||
11Z = (11B, XXX)
|
||||
22A = (22B, XXX)
|
||||
22B = (22C, 22C)
|
||||
22C = (22Z, 22Z)
|
||||
22Z = (22B, 22B)
|
||||
XXX = (XXX, XXX)
|
168
advent_2023/puzzle_2023_day_8/src/lib.rs
Normal file
168
advent_2023/puzzle_2023_day_8/src/lib.rs
Normal file
@ -0,0 +1,168 @@
|
||||
use core::str::FromStr;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Debug, Default, PartialEq, Eq, Clone)]
|
||||
pub struct DesertMap {
|
||||
pub directions: Vec<HorizontalDirection>,
|
||||
pub nodes: HashMap<String, [String; 2]>,
|
||||
}
|
||||
|
||||
impl FromStr for DesertMap {
|
||||
type Err = &'static str;
|
||||
|
||||
/// Parses a string `string` to return a value of [`DesertMap`]
|
||||
///
|
||||
/// If parsing succeeds, return the value inside [`Ok`], otherwise
|
||||
/// when the string is ill-formatted return an error specific to the
|
||||
/// inside [`Err`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::str::FromStr;
|
||||
/// use std::collections::HashMap;
|
||||
/// use puzzle_2023_day_8::{DesertMap, HorizontalDirection};
|
||||
///
|
||||
/// let string = "
|
||||
/// RL
|
||||
///
|
||||
/// AAA = (BBB, CCC)
|
||||
/// BBB = (DDD, EEE)
|
||||
/// CCC = (ZZZ, GGG)
|
||||
/// ";
|
||||
/// let expected_result = DesertMap {
|
||||
/// directions: vec![HorizontalDirection::Right, HorizontalDirection::Left],
|
||||
/// nodes: HashMap::from([
|
||||
/// (String::from("AAA"), [String::from("BBB"), String::from("CCC")]),
|
||||
/// (String::from("BBB"), [String::from("DDD"), String::from("EEE")]),
|
||||
/// (String::from("CCC"), [String::from("ZZZ"), String::from("GGG")]),
|
||||
/// ])
|
||||
/// };
|
||||
///
|
||||
/// let actual_result = DesertMap::from_str(string).unwrap();
|
||||
/// assert_eq!(actual_result, expected_result);
|
||||
/// ```
|
||||
fn from_str(string: &str) -> Result<Self, Self::Err> {
|
||||
let mut result = DesertMap::default();
|
||||
let mut lines = string.trim().lines();
|
||||
let first_line = lines.next().unwrap_or_default();
|
||||
for character in first_line.chars() {
|
||||
result.directions.push(HorizontalDirection::from(character));
|
||||
}
|
||||
lines.next();
|
||||
for line in lines {
|
||||
let mut line_splitted = line.split(" = ");
|
||||
let key = line_splitted.next().unwrap_or_default();
|
||||
let values_line = line_splitted
|
||||
.next()
|
||||
.unwrap_or_default()
|
||||
.replace(['(', ')'], "");
|
||||
let mut values_line = values_line.split(", ");
|
||||
let value = [
|
||||
values_line.next().unwrap_or_default().to_string(),
|
||||
values_line.next().unwrap_or_default().to_string(),
|
||||
];
|
||||
result.nodes.insert(key.to_string(), value);
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, PartialEq, Eq, Copy, Clone)]
|
||||
pub enum HorizontalDirection {
|
||||
#[default]
|
||||
Left = 0,
|
||||
Right = 1,
|
||||
}
|
||||
|
||||
impl HorizontalDirection {
|
||||
pub const fn index(&self) -> usize {
|
||||
*self as usize
|
||||
}
|
||||
}
|
||||
|
||||
impl From<char> for HorizontalDirection {
|
||||
fn from(direction: char) -> Self {
|
||||
if direction == 'R' {
|
||||
return HorizontalDirection::Right;
|
||||
}
|
||||
HorizontalDirection::Left
|
||||
}
|
||||
}
|
||||
|
||||
const KEY_START: &str = "AAA";
|
||||
|
||||
const KEY_END: &str = "ZZZ";
|
||||
|
||||
pub fn part_1(input: &str) -> usize {
|
||||
let mut desert_map = DesertMap::from_str(input).unwrap_or_default();
|
||||
let mut steps = 0;
|
||||
let mut current_step_key = KEY_START.to_string();
|
||||
while current_step_key != KEY_END {
|
||||
let direction_index = steps % desert_map.directions.len();
|
||||
let current_direction = &desert_map.directions[direction_index];
|
||||
let current_step_value =
|
||||
if let Some(step_value) = desert_map.nodes.get_mut(¤t_step_key) {
|
||||
step_value
|
||||
} else {
|
||||
break;
|
||||
};
|
||||
current_step_key = current_step_value[current_direction.index()].to_string();
|
||||
steps += 1;
|
||||
}
|
||||
steps
|
||||
}
|
||||
|
||||
pub fn part_2(input: &str) -> usize {
|
||||
let desert_map = DesertMap::from_str(input).unwrap_or_default();
|
||||
let mut current_step_keys: Vec<String> = desert_map
|
||||
.nodes
|
||||
.keys()
|
||||
.filter(|key| key.ends_with('A'))
|
||||
.map(|key| key.to_string())
|
||||
.collect();
|
||||
let mut steps = 0;
|
||||
while !current_step_keys
|
||||
.iter()
|
||||
.all(|step_key| step_key.ends_with('Z'))
|
||||
{
|
||||
let direction_index = steps % desert_map.directions.len();
|
||||
let current_direction = &desert_map.directions[direction_index];
|
||||
for current_step_key in current_step_keys.iter_mut() {
|
||||
let current_step_value =
|
||||
if let Some(step_value) = desert_map.nodes.get(current_step_key) {
|
||||
step_value
|
||||
} else {
|
||||
break;
|
||||
};
|
||||
*current_step_key = current_step_value[current_direction.index()].to_string();
|
||||
}
|
||||
steps += 1;
|
||||
}
|
||||
steps
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod puzzle_2023_day_8_tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_part_1_example_1() {
|
||||
assert_eq!(part_1(include_str!("../input_example_1.txt")), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part_1_example_2() {
|
||||
assert_eq!(part_1(include_str!("../input_example_2.txt")), 6);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part_1() {
|
||||
assert_eq!(part_1(include_str!("../input.txt")), 15871);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part_2_example_3() {
|
||||
assert_eq!(part_2(include_str!("../input_example_3.txt")), 6);
|
||||
}
|
||||
}
|
8
advent_2023/puzzle_2023_day_8/src/main.rs
Normal file
8
advent_2023/puzzle_2023_day_8/src/main.rs
Normal file
@ -0,0 +1,8 @@
|
||||
use puzzle_2023_day_8::{part_1, part_2};
|
||||
|
||||
fn main() {
|
||||
let input = include_str!("../input.txt");
|
||||
println!("- Day 8 of 2023: Haunted Wasteland -");
|
||||
println!("Answer Part 1: {}", part_1(input));
|
||||
println!("Answer Part 2: {}", part_2(input));
|
||||
}
|
Reference in New Issue
Block a user