diff --git a/README.md b/README.md index b6548cc..08a2510 100644 --- a/README.md +++ b/README.md @@ -19,11 +19,12 @@ Solutions for [Advent of Code](https://adventofcode.com/) in [Rust](https://www. | Day | Part 1 | Part 2 | | :---: | :---: | :---: | -| [Day 1](./src/bin/01.rs) | `36.9µs` | `82.8µs` | -| [Day 2](./src/bin/02.rs) | `44.4µs` | `43.1µs` | -| [Day 3](./src/bin/03.rs) | `116.0µs` | `113.7µs` | +| [Day 1](./src/bin/01.rs) | `38.2µs` | `81.2µs` | +| [Day 2](./src/bin/02.rs) | `43.7µs` | `43.2µs` | +| [Day 3](./src/bin/03.rs) | `115.3µs` | `113.3µs` | +| [Day 4](./src/bin/04.rs) | `52.3µs` | `55.3µs` | -**Total: 0.44ms** +**Total: 0.54ms** --- diff --git a/data/examples/04.txt b/data/examples/04.txt new file mode 100644 index 0000000..71f208a --- /dev/null +++ b/data/examples/04.txt @@ -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 \ No newline at end of file diff --git a/src/bin/04.rs b/src/bin/04.rs new file mode 100644 index 0000000..cb7dd89 --- /dev/null +++ b/src/bin/04.rs @@ -0,0 +1,63 @@ +advent_of_code::solution!(4); + +pub fn part_one(input: &str) -> Option { + Some( + input + .lines() + .filter_map(winning_number_count) + .filter(|&c| c > 0) + .map(|c| 1 << (c - 1)) + .sum(), + ) +} + +pub fn part_two(input: &str) -> Option { + let lines = input.lines().collect::>(); + let mut copies = vec![1; lines.len()]; + let mut total = 0; + for (index, line) in lines.into_iter().enumerate() { + let card_copies = copies[index]; + total += card_copies; + let winning_numbers = winning_number_count(line).unwrap_or(0) as usize; + for i in 0..winning_numbers { + if let Some(elem) = copies.get_mut(index + i + 1) { + *elem += card_copies; + } + } + } + Some(total) +} + +fn winning_number_count(card: &str) -> Option { + let (_, numbers_part) = card.split_once(':')?; + let (winning_str, have_str) = numbers_part.split_once('|')?; + let mut winning_numbers = [false; 100]; + for s in winning_str.split_whitespace() { + winning_numbers[s.parse::().ok()?] = true; + } + let mut count = 0; + for s in have_str.split_whitespace() { + let num = s.parse::().ok()?; + if winning_numbers[num] { + count += 1; + } + } + Some(count) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part_one() { + let result = part_one(&advent_of_code::template::read_file("examples", DAY)); + assert_eq!(result, Some(13)); + } + + #[test] + fn test_part_two() { + let result = part_two(&advent_of_code::template::read_file("examples", DAY)); + assert_eq!(result, Some(30)); + } +}