Compare commits
No commits in common. "3c4e784d9754300895d5f089933416448697f33a" and "146735881add3e58062989d791329985ae870f98" have entirely different histories.
3c4e784d97
...
146735881a
2 changed files with 0 additions and 1180 deletions
1000
inputs/day7.txt
1000
inputs/day7.txt
File diff suppressed because it is too large
Load diff
180
src/bin/day7.rs
180
src/bin/day7.rs
|
@ -1,180 +0,0 @@
|
||||||
#![allow(clippy::no_effect)]
|
|
||||||
#![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 all_cards() -> [Self; 0 $(+ { $char; 1 })+] {
|
|
||||||
[$(Self::$ident),+]
|
|
||||||
}
|
|
||||||
|
|
||||||
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! {
|
|
||||||
Joker = '*',
|
|
||||||
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();
|
|
||||||
let mut jokers = 0;
|
|
||||||
for card in cards {
|
|
||||||
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) {
|
|
||||||
Type::FiveOfAKind
|
|
||||||
} else if counts.values().any(|c| *c >= 4) {
|
|
||||||
Type::FourOfAKind
|
|
||||||
} 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();
|
|
||||||
match pairs {
|
|
||||||
0 => Type::HighCard,
|
|
||||||
1 => Type::OnePair,
|
|
||||||
_ => Type::TwoPair
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
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 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<()> {
|
|
||||||
let hands = read("inputs/day7.txt", parser())?;
|
|
||||||
// eprintln!("{hands:?}");
|
|
||||||
|
|
||||||
let sorted: BTreeSet<&Hand> = hands.iter().collect();
|
|
||||||
// eprintln!("{sorted:?}");
|
|
||||||
let sum = sum_hands(sorted);
|
|
||||||
println!("{sum}");
|
|
||||||
// assert_eq!(sum, 251106089);
|
|
||||||
|
|
||||||
let sorted: BTreeSet<Hand> = 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(())
|
|
||||||
}
|
|
Loading…
Reference in a new issue