day 7 part 1

This commit is contained in:
Dylan Thies
2023-12-07 21:10:06 -05:00
parent ca674a4ebb
commit 71457ff52e
3 changed files with 245 additions and 4 deletions

78
2023/Cargo.lock generated
View File

@@ -89,6 +89,8 @@ version = "2023.0.0"
dependencies = [ dependencies = [
"itertools", "itertools",
"nom", "nom",
"num",
"num-traits",
] ]
[[package]] [[package]]
@@ -273,6 +275,82 @@ dependencies = [
"minimal-lexical", "minimal-lexical",
] ]
[[package]]
name = "num"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af"
dependencies = [
"num-bigint",
"num-complex",
"num-integer",
"num-iter",
"num-rational",
"num-traits",
]
[[package]]
name = "num-bigint"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-complex"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214"
dependencies = [
"num-traits",
]
[[package]]
name = "num-integer"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-iter"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
dependencies = [
"autocfg",
"num-bigint",
"num-integer",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
dependencies = [
"autocfg",
]
[[package]] [[package]]
name = "pin-project-lite" name = "pin-project-lite"
version = "0.2.13" version = "0.2.13"

View File

@@ -10,3 +10,5 @@ repository.workspace = true
[dependencies] [dependencies]
nom.workspace = true nom.workspace = true
itertools.workspace = true itertools.workspace = true
num = "0.4.1"
num-traits = "0.2.17"

View File

@@ -1,20 +1,181 @@
#![warn(clippy::all, clippy::pedantic)] #![warn(clippy::all, clippy::pedantic)]
use itertools::Itertools;
use nom::{character::complete, multi::separated_list1, sequence::separated_pair, IResult};
use std::{
cmp::{Ord, Ordering, PartialOrd},
collections::BTreeMap,
str::FromStr,
};
#[derive(Debug)]
struct Day1Part1Error;
#[derive(Debug, Ord, Eq, PartialEq, PartialOrd)]
enum Card {
Two,
Three,
Four,
Five,
Six,
Seven,
Eight,
Nine,
Ten,
Jack,
Queen,
King,
Ace,
}
impl FromStr for Card {
type Err = Day1Part1Error;
fn from_str(input: &str) -> Result<Self, Self::Err> {
match input {
"2" => Ok(Self::Two),
"3" => Ok(Self::Three),
"4" => Ok(Self::Four),
"5" => Ok(Self::Five),
"6" => Ok(Self::Six),
"7" => Ok(Self::Seven),
"8" => Ok(Self::Eight),
"9" => Ok(Self::Nine),
"T" => Ok(Self::Ten),
"J" => Ok(Self::Jack),
"Q" => Ok(Self::Queen),
"K" => Ok(Self::King),
"A" => Ok(Self::Ace),
_ => Err(Day1Part1Error),
}
}
}
impl From<&Card> for &u32 {
fn from(value: &Card) -> Self {
match value {
Card::Two => &2,
Card::Three => &3,
Card::Four => &4,
Card::Five => &5,
Card::Six => &6,
Card::Seven => &7,
Card::Eight => &8,
Card::Nine => &9,
Card::Ten => &10,
Card::Jack => &11,
Card::Queen => &12,
Card::King => &13,
Card::Ace => &14,
}
}
}
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
enum HandType {
FiveOfAKind,
FourOfAKind,
FullHouse,
ThreeOfAKind,
TwoPair,
OnePair,
HighCard,
}
impl From<&Hand> for HandType {
fn from(value: &Hand) -> Self {
let map = value.cards.iter().fold(BTreeMap::new(), |mut acc, card| {
if let Some(c) = acc.get_mut(card) {
*c += 1;
} else {
acc.insert(card, 1);
}
acc
});
match map
.iter()
.sorted_by(|a, b| b.1.cmp(a.1))
.collect::<Vec<_>>()[..]
{
[(_, 5), ..] => Self::FiveOfAKind,
[(_, 4), ..] => Self::FourOfAKind,
[(_, 3), (_, 2), ..] => Self::FullHouse,
[(_, 3), ..] => Self::ThreeOfAKind,
[(_, 2), (_, 2), ..] => Self::TwoPair,
[(_, 2), ..] => Self::OnePair,
_ => Self::HighCard,
}
}
}
#[derive(Debug, Eq, PartialEq, Ord)]
struct Hand {
pub cards: [Card; 5],
pub bet: u32,
}
impl PartialOrd for Hand {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
let a = HandType::from(self);
let b = HandType::from(other);
let c = b.cmp(&a);
match c {
Ordering::Equal => self
.cards
.iter()
.interleave(other.cards.iter())
.tuples::<(_, _)>()
.find_map(|(a, b)| {
if b.cmp(a).is_ne() {
Some(a.cmp(b))
} else {
None
}
}),
x => Some(x),
}
}
}
#[must_use] #[must_use]
pub fn part1(_input: &str) -> String { pub fn part1(_input: &str) -> String {
"Not Finished".to_string() let (_, mut hands) = parse_input(_input).expect("always valid input");
hands.sort();
dbg!(hands)
.iter()
.enumerate()
.map(|(i, hand)| (i + 1) * hand.bet as usize)
.sum::<usize>()
.to_string()
}
fn parse_hand(input: &str) -> IResult<&str, Hand> {
let (input, (cards, bet)) =
separated_pair(complete::alphanumeric1, complete::space1, complete::u32)(input)?;
let cards = cards
.chars()
.filter_map(|c| c.to_string().parse().ok())
.collect::<Vec<_>>()
.try_into()
.expect("should work");
Ok((input, Hand { cards, bet }))
}
fn parse_input(input: &str) -> IResult<&str, Vec<Hand>> {
separated_list1(complete::line_ending, parse_hand)(input)
} }
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
const INPUT: &str = ""; const INPUT: &str = "32T3K 765
T55J5 684
KK677 28
KTJJT 220
QQQJA 483";
#[test] #[test]
fn part1_works() { fn part1_works() {
let result = part1(INPUT); let result = part1(INPUT);
assert_eq!(result, "Not Finished".to_string()); assert_eq!(result, "6440".to_string());
} }
} }