From ed8137d599a687fc842fc135bd2ecdf680d0e427 Mon Sep 17 00:00:00 2001 From: Lars Martens Date: Mon, 4 Dec 2023 12:38:07 +0100 Subject: [PATCH] Solve day 4 --- input/04-test | 6 +++++ src/bin/04.rs | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 input/04-test create mode 100644 src/bin/04.rs diff --git a/input/04-test b/input/04-test new file mode 100644 index 0000000..71f208a --- /dev/null +++ b/input/04-test @@ -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..1a9f6cc --- /dev/null +++ b/src/bin/04.rs @@ -0,0 +1,74 @@ +use std::collections::HashSet; + +const INPUT: &str = include_str!("../../input/04"); +const TEST_INPUT: &str = include_str!("../../input/04-test"); + +fn main() { + assert_eq!(part1(TEST_INPUT), 13); + println!("Part 1: {}", part1(INPUT)); + assert_eq!(part2(TEST_INPUT), 30); + println!("Part 2: {}", part2(INPUT)); +} + +fn part1(input: &str) -> u64 { + parse_cards(input).map(|card| card.score()).sum() +} + +fn part2(input: &str) -> u64 { + let mut cards: Vec = parse_cards(input).collect(); + + for i in 0..cards.len() { + let winning = cards[i].count_winning(); + for win in 1..=winning { + let win = i + win; + if win < cards.len() { + cards[win].copies += cards[i].copies; + } + } + } + + cards.iter().map(|card| card.copies).sum() +} + +#[derive(Clone)] +struct Card { + copies: u64, + winning: HashSet, + owned: HashSet, +} + +impl Card { + fn count_winning(&self) -> usize { + self.winning.intersection(&self.owned).count() + } + + fn score(&self) -> u64 { + let got_winning = self.count_winning(); + if got_winning > 0 { + 2u64.pow(got_winning as u32 - 1) + } else { + 0 + } + } + + fn parse(line: &str) -> Self { + let (_id, line) = line.split_once(": ").unwrap(); + let (winning, owned) = line.split_once(" | ").unwrap(); + + Self { + copies: 1, + winning: parse_numbers(winning), + owned: parse_numbers(owned), + } + } +} + +fn parse_cards(input: &str) -> impl Iterator + '_ { + input.lines().map(Card::parse) +} + +fn parse_numbers(line: &str) -> HashSet { + line.split_ascii_whitespace() + .map(|n| n.parse().unwrap()) + .collect() +}