Advent 2023 Day 7, 8 & 9

This commit is contained in:
Jos van Goor 2023-12-09 15:20:29 +01:00
parent 57429c49e9
commit 582af3d9f3
9 changed files with 2364 additions and 0 deletions

View file

@ -0,0 +1,124 @@
use std::{fs::read_to_string, collections::{HashMap, btree_map::Values}};
#[derive(Debug, Copy, Clone)]
#[derive(PartialEq, PartialOrd, Eq, Ord)]
enum Rank {
HighCard,
OnePair,
TwoPair,
ThreeOfAKind,
FullHouse,
FourOfAKind,
FiveOfAKind,
}
impl Rank {
fn signature(&self) -> Vec<i32> {
match self {
Rank::HighCard => vec![1, 1, 1, 1, 1],
Rank::OnePair => vec![2, 1, 1, 1],
Rank::TwoPair => vec![2, 2, 1],
Rank::ThreeOfAKind => vec![3, 1, 1],
Rank::FullHouse => vec![3, 2],
Rank::FourOfAKind => vec![4, 1],
Rank::FiveOfAKind => vec![5]
}
}
fn matches(&self, hand: &Vec<i32>) -> bool {
let signature = self.signature();
if hand.len() != signature.len() {
return false;
}
signature.iter().zip(hand.iter()).filter(|&(lhs, rhs)| lhs == rhs).count() == signature.len()
}
fn mapping() -> HashMap<Vec<i32>, Rank> {
HashMap::from([
(Rank::HighCard{}.signature(), Rank::HighCard),
(Rank::OnePair{}.signature(), Rank::OnePair),
(Rank::TwoPair{}.signature(), Rank::TwoPair),
(Rank::ThreeOfAKind{}.signature(), Rank::ThreeOfAKind),
(Rank::FullHouse{}.signature(), Rank::FullHouse),
(Rank::FourOfAKind{}.signature(), Rank::FourOfAKind),
(Rank::FiveOfAKind{}.signature(), Rank::FiveOfAKind),
])
}
fn card_values() -> HashMap<u8, i32> {
HashMap::from([
(b'2', 0),
(b'3', 1),
(b'4', 2),
(b'5', 3),
(b'6', 4),
(b'7', 5),
(b'8', 6),
(b'9', 7),
(b'T', 8),
(b'J', 9),
(b'Q', 10),
(b'K', 11),
(b'A', 12),
])
}
fn parse(line: &str, mapping: &HashMap<Vec<i32>, Rank>, values: &HashMap<u8, i32>) -> (Rank, u64) {
let mut counts = HashMap::<u8, i32>::new();
let mut tiebreaker: u64 = 0;
for idx in 0..line.len() {
*counts.entry(line.as_bytes()[idx]).or_insert(0) += 1;
tiebreaker = tiebreaker * 100 + values[&line.as_bytes()[idx]] as u64;
}
let mut signature = counts.values().map(|a| *a).collect::<Vec<_>>();
signature.sort_by(|a, b| b.cmp(a));
(mapping[&signature], tiebreaker)
}
}
struct Hand {
cards: String,
score: u64,
rank: Rank,
tiebreaker: u64,
}
impl Hand {
fn parse(line: &str, mapping: &HashMap<Vec<i32>, Rank>, values: &HashMap<u8, i32>) -> Hand {
let (cards, score) = line.split_once(' ').unwrap();
let (rank, tiebreaker) = Rank::parse(cards, mapping, values);
Hand{cards: String::from(cards), score: score.parse::<u64>().unwrap(), rank, tiebreaker}
}
}
fn main() {
let mapping = Rank::mapping();
let card_values = Rank::card_values();
let mut hands = read_to_string("input.txt").unwrap().lines().map(|line| {
Hand::parse(line, &mapping, &card_values)
}).collect::<Vec<_>>();
hands.sort_by(|lhs, rhs| {
if lhs.rank == rhs.rank {
return lhs.tiebreaker.cmp(&rhs.tiebreaker);
}
lhs.rank.cmp(&rhs.rank)
});
let mut score_base = 1;
let mut points = 0;
for hand in &hands {
points += score_base * hand.score;
score_base += 1;
}
println!("Total points: {}", points);
}