diff --git a/src/bin/day7.rs b/src/bin/day7.rs index 60d6d36..4feeaf3 100644 --- a/src/bin/day7.rs +++ b/src/bin/day7.rs @@ -1,3 +1,4 @@ +#![allow(clippy::no_effect)] #![forbid(elided_lifetimes_in_paths, unsafe_code)] use aoc23::read; @@ -13,6 +14,10 @@ macro_rules! cards { enum Card { $($ident),+ } impl Card { + fn all_cards() -> [Self; 0 $(+ { $char; 1 })+] { + [$(Self::$ident),+] + } + fn parser() -> impl Parser> { choice(( $(just($char).map(|_| Self::$ident)),+ @@ -31,6 +36,7 @@ macro_rules! cards { } cards! { + Joker = '*', Two = '2', Three = '3', Four = '4', @@ -74,27 +80,39 @@ struct Hand { impl Hand { fn new(cards: [Card; 5], bid: usize) -> Self { let mut counts: HashMap = HashMap::new(); + let mut jokers = 0; for card in cards { - *counts.entry(card).or_default() += 1; + if card == Card::Joker { + jokers += 1; + } else { + *counts.entry(card).or_default() += 1; + } + } + match counts.values_mut().max() { + Some(max) => { + *max += jokers; + }, + None => { + counts.insert(Card::Joker, jokers); + } } - let ty = if counts.values().any(|c| *c == 5) { + let ty = if counts.values().any(|c| *c >= 5) { Type::FiveOfAKind - } else if counts.values().any(|c| *c == 4) { + } else if counts.values().any(|c| *c >= 4) { Type::FourOfAKind - } else if counts.values().any(|c| *c == 3) { - if counts.values().any(|c| *c == 2) { + } else if counts.values().any(|c| *c >= 3) { + if counts.values().filter(|c| **c >= 2).count() >= 2 { Type::FullHouse } else { Type::ThreeOfAKind } } else { - let pairs = counts.values().filter(|c| **c == 2).count(); + let pairs = counts.values().filter(|c| **c >= 2).count(); match pairs { - 2 => Type::TwoPair, - 1 => Type::OnePair, 0 => Type::HighCard, - _ => unreachable!() + 1 => Type::OnePair, + _ => Type::TwoPair } }; @@ -120,20 +138,43 @@ fn parser() -> impl Parser, Error = Simple> { .then_ignore(end()) } +fn sum_hands<'a>(hands: impl IntoIterator) -> usize { + hands + .into_iter() + .enumerate() + .map(|(i, hand)| (i + 1) * hand.bid) + .sum::() +} + fn main() -> anyhow::Result<()> { let hands = read("inputs/day7.txt", parser())?; // eprintln!("{hands:?}"); let sorted: BTreeSet<&Hand> = hands.iter().collect(); // eprintln!("{sorted:?}"); - println!( - "{}", - sorted - .into_iter() - .enumerate() - .map(|(i, hand)| (i + 1) * hand.bid) - .sum::() - ); + let sum = sum_hands(sorted); + println!("{sum}"); + // assert_eq!(sum, 251106089); + + let sorted: BTreeSet = hands + .iter() + .map(|hand| { + let mut cards = hand.cards; + for card in &mut cards { + if *card == Card::Junior { + *card = Card::Joker; + } + } + let hand = Hand::new(cards, hand.bid); + // eprintln!("{hand:?}"); + hand + }) + .collect(); + // eprintln!("{sorted:#?}"); + let sum = sum_hands(&sorted); + println!("{sum}"); + // assert!(sum > 249135400); + // assert!(sum < 249779500); Ok(()) }