day 7 part 1

This commit is contained in:
Dominic 2023-12-07 15:48:28 +01:00
parent 146735881a
commit ca8d1c7708
Signed by: msrd0
GPG key ID: DCC8C247452E98F9
2 changed files with 1139 additions and 0 deletions

1000
inputs/day7.txt Normal file

File diff suppressed because it is too large Load diff

139
src/bin/day7.rs Normal file
View file

@ -0,0 +1,139 @@
#![forbid(elided_lifetimes_in_paths, unsafe_code)]
use aoc23::read;
use chumsky::{prelude::*, text::int};
use std::{
collections::{BTreeSet, HashMap},
fmt::{self, Debug}
};
macro_rules! cards {
($($ident:ident = $char:literal),+) => {
#[derive(Clone, Copy, Eq, Hash, PartialEq, PartialOrd, Ord)]
enum Card { $($ident),+ }
impl Card {
fn parser() -> impl Parser<char, Self, Error = Simple<char>> {
choice((
$(just($char).map(|_| Self::$ident)),+
))
}
}
impl Debug for Card {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
$(Self::$ident => write!(f, "{}", $char)),+
}
}
}
}
}
cards! {
Two = '2',
Three = '3',
Four = '4',
Five = '5',
Six = '6',
Seven = '7',
Eight = '8',
Nine = '9',
Ten = 'T',
Junior = 'J',
Queen = 'Q',
King = 'K',
Ass = 'A'
}
#[derive(Debug, Eq, PartialEq, PartialOrd, Ord)]
enum Type {
/// All distinct (e.g. `23456`).
HighCard,
/// One pair (e.g. `A23A4`).
OnePair,
/// Two pair (e.g. `23432`).
TwoPair,
/// Three of a kind (e.g. `TTT98`).
ThreeOfAKind,
/// Full house (e.g. `23332`).
FullHouse,
/// Four of a kind (e.g. `AA8AA`).
FourOfAKind,
/// Five of a kind (e.g. `AAAAA`).
FiveOfAKind
}
#[derive(Debug, Eq, PartialEq, PartialOrd, Ord)]
struct Hand {
ty: Type,
cards: [Card; 5],
bid: usize
}
impl Hand {
fn new(cards: [Card; 5], bid: usize) -> Self {
let mut counts: HashMap<Card, usize> = HashMap::new();
for card in cards {
*counts.entry(card).or_default() += 1;
}
let ty = if counts.values().any(|c| *c == 5) {
Type::FiveOfAKind
} 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) {
Type::FullHouse
} else {
Type::ThreeOfAKind
}
} else {
let pairs = counts.values().filter(|c| **c == 2).count();
match pairs {
2 => Type::TwoPair,
1 => Type::OnePair,
0 => Type::HighCard,
_ => unreachable!()
}
};
Self { ty, cards, bid }
}
fn parser() -> impl Parser<char, Self, Error = Simple<char>> {
Card::parser()
.repeated()
.exactly(5)
.then_ignore(just(" "))
.then(int(10))
.map(|(cards, bid)| {
Self::new(cards.try_into().unwrap(), bid.parse().unwrap())
})
}
}
fn parser() -> impl Parser<char, Vec<Hand>, Error = Simple<char>> {
Hand::parser()
.then_ignore(just("\n"))
.repeated()
.then_ignore(end())
}
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::<usize>()
);
Ok(())
}