day 7 part 2

This commit is contained in:
Dominic 2023-12-07 16:17:58 +01:00
parent ca8d1c7708
commit 3c4e784d97
Signed by: msrd0
GPG key ID: DCC8C247452E98F9

View file

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