Complete 2023 day 4
This commit is contained in:
parent
7db1c351c0
commit
ed03f386be
@ -60,13 +60,13 @@ Take a seat in the large pile of colorful cards. **How many points are they wort
|
||||
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
|
||||
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
|
||||
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,
|
||||
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.)
|
||||
@ -85,16 +85,16 @@ 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 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!
|
||||
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?
|
||||
scratchcards, **how many total scratchcards do you end up with?**
|
||||
|
||||
|
||||
|
@ -8,6 +8,7 @@ struct ScratchCard {
|
||||
winning: Vec<usize>,
|
||||
chosen: Vec<usize>,
|
||||
chosen_winners: HashSet<usize>,
|
||||
cw_count: usize,
|
||||
}
|
||||
|
||||
impl ScratchCard {
|
||||
@ -20,10 +21,17 @@ impl ScratchCard {
|
||||
}
|
||||
|
||||
fn find_chosen_winners(&mut self) {
|
||||
// We've done this already
|
||||
if self.cw_count > 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
self.winning
|
||||
.iter()
|
||||
.filter(|w| self.chosen.contains(w))
|
||||
.for_each(|cw| _ = self.chosen_winners.insert(*cw));
|
||||
|
||||
self.cw_count = self.chosen_winners.len();
|
||||
}
|
||||
|
||||
fn score(&mut self) -> usize {
|
||||
@ -50,15 +58,63 @@ impl GameMap {
|
||||
))
|
||||
}
|
||||
|
||||
fn find_all_chosen_winners(&mut self) {
|
||||
self.0.iter_mut().for_each(|(_, sc)| {
|
||||
fn get_original_card_matches(&mut self) -> HashMap<usize, usize> {
|
||||
HashMap::from_iter(self.0.iter_mut().map(|(id, sc)| {
|
||||
sc.find_chosen_winners();
|
||||
})
|
||||
(*id, sc.cw_count)
|
||||
}))
|
||||
}
|
||||
|
||||
fn get_score_sum(&mut self) -> usize {
|
||||
self.0.iter_mut().map(|(_, sc)| sc.score()).sum()
|
||||
}
|
||||
|
||||
fn get_scratchcard_counts(&mut self) -> HashMap<usize, usize> {
|
||||
let match_map: HashMap<usize, usize> = self.get_original_card_matches();
|
||||
let mut copy_map: HashMap<usize, usize> = HashMap::new();
|
||||
let mut count_map: HashMap<usize, usize> =
|
||||
match_map.iter().map(|(id, _)| (*id, 1usize)).collect();
|
||||
|
||||
for id in 1..=match_map.len() {
|
||||
let raw_match_count = match_map.get(&id);
|
||||
if raw_match_count.is_none() {
|
||||
break;
|
||||
}
|
||||
let match_count = *raw_match_count.unwrap();
|
||||
let copy_count = match copy_map.get(&id) {
|
||||
Some(n) => *n + 1,
|
||||
None => 1,
|
||||
};
|
||||
|
||||
for _ in 0..copy_count {
|
||||
let add_range = id + 1..=id + match_count;
|
||||
for n in add_range {
|
||||
let raw_count = count_map.get(&n);
|
||||
if let Some(count) = raw_count {
|
||||
count_map.insert(n, *count + 1);
|
||||
let copy_count = match copy_map.get(&n) {
|
||||
Some(num) => *num + 1,
|
||||
None => 1,
|
||||
};
|
||||
copy_map.insert(n, copy_count);
|
||||
} else {
|
||||
// No value means the value of n is greater than
|
||||
// the amount of original cards
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
count_map
|
||||
}
|
||||
|
||||
fn get_total_scratchcard_count(&mut self) -> usize {
|
||||
self.get_scratchcard_counts()
|
||||
.into_iter()
|
||||
.map(|(_, count)| count)
|
||||
.sum()
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_game_table_line(line: &str) -> (usize, ScratchCard) {
|
||||
@ -85,8 +141,15 @@ fn part_one() {
|
||||
println!("Part 1 Score Sum {}", sum);
|
||||
}
|
||||
|
||||
fn part_two() {
|
||||
let mut map = GameMap::parse(FILE_STR);
|
||||
let card_count = map.get_total_scratchcard_count();
|
||||
println!("Part 2 Scratchcard Count: {}", card_count);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
part_one();
|
||||
part_two();
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -100,4 +163,23 @@ mod tests {
|
||||
let actual = map.get_score_sum();
|
||||
assert_eq!(13, actual);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part2_example() {
|
||||
let mut map = GameMap::parse(EXAMPLE_FILE_STR);
|
||||
let actual = map.get_total_scratchcard_count();
|
||||
assert_eq!(30, actual);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_example_card_counts() {
|
||||
let mut map = GameMap::parse(EXAMPLE_FILE_STR);
|
||||
let count_map = map.get_scratchcard_counts();
|
||||
assert_eq!(Some(1), count_map.get(&1).copied());
|
||||
assert_eq!(Some(2), count_map.get(&2).copied());
|
||||
assert_eq!(Some(4), count_map.get(&3).copied());
|
||||
assert_eq!(Some(8), count_map.get(&4).copied());
|
||||
assert_eq!(Some(14), count_map.get(&5).copied());
|
||||
assert_eq!(Some(1), count_map.get(&6).copied());
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user