Implemented Day 7 part 1.

This commit is contained in:
Dennis Brentjes
2023-12-08 11:04:03 +01:00
parent 63ce6b5cf2
commit a19e839fe0
6 changed files with 1190 additions and 4 deletions

184
src/days/day7.rs Normal file
View File

@@ -0,0 +1,184 @@
use std::{path::Path, str::FromStr};
use itertools::Itertools;
use crate::{error::AdventError, input::read_into_vec};
#[derive(Debug, Eq, PartialEq, Hash)]
struct Card(char);
impl PartialOrd for Card {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.strength().partial_cmp(&other.strength())
}
}
impl Ord for Card {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.strength().cmp(&other.strength())
}
}
impl Card {
fn strength(self: &Self) -> u32 {
match self.0 {
'2' => 2,
'3' => 3,
'4' => 4,
'5' => 5,
'6' => 6,
'7' => 7,
'8' => 8,
'9' => 9,
'T' => 10,
'J' => 11,
'Q' => 12,
'K' => 13,
'A' => 14,
_ => panic!("Invalid card found")
}
}
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
enum HandType {
None,
HighCard,
OnePair,
TwoPair,
ThreeOfAKind,
FullHouse,
FourOfAKind,
FiveOfAKind,
}
#[derive(Debug, Eq)]
struct Hand {
cards: [Card;5],
hand_type: HandType,
}
impl PartialOrd for Hand {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
match self.hand_type.partial_cmp(&other.hand_type) {
Some(core::cmp::Ordering::Equal) => {}
ord => return ord,
}
self.cards.partial_cmp(&other.cards)
}
}
impl Ord for Hand {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.hand_type.cmp(&other.hand_type)
}
}
impl PartialEq for Hand {
fn eq(&self, other: &Self) -> bool {
self.hand_type == other.hand_type
}
}
impl Hand {
fn new() -> Self {
Hand {
cards: [Card(' '), Card(' '), Card(' '), Card(' '), Card(' ')],
hand_type: HandType::None
}
}
fn determine_type(&mut self) -> () {
let counts = self.cards.iter().counts();
let value_counts = counts.iter().map(|c| { c.1 }).collect_vec();
self.hand_type = match (counts.len(), value_counts) {
(5, _) => HandType::HighCard,
(4, _) => HandType::OnePair,
(3, c) => {
if c.contains(&&3) {
HandType::ThreeOfAKind
} else {
HandType::TwoPair
}
}
(2, c) => {
if c.contains(&&4) {
HandType::FourOfAKind
} else {
HandType::FullHouse
}
}
(1, _) => HandType::FiveOfAKind,
(_, _) => panic!("Hand type match should never fail")
};
}
}
impl FromStr for Hand {
type Err = AdventError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut hand: Hand = Hand::new();
for i in 0..s.len() {
hand.cards[i] = Card(s.chars().nth(i).ok_or(AdventError("Couldn't convert into Card".into()))?);
hand.determine_type();
}
Ok(hand)
}
}
#[derive(Debug, Eq)]
struct Line {
hand: Hand,
bid: u32,
}
impl PartialEq for Line {
fn eq(&self, other: &Self) -> bool {
self.hand == other.hand
}
}
impl PartialOrd for Line {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
match self.hand.partial_cmp(&other.hand) {
Some(core::cmp::Ordering::Equal) => {}
ord => return ord,
}
self.bid.partial_cmp(&other.bid)
}
}
impl Ord for Line {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.hand.cmp(&other.hand)
}
}
impl FromStr for Line {
type Err = AdventError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut split = s.trim().split_ascii_whitespace();
let hand = Hand::from_str(split.nth(0).ok_or(AdventError("no hand found".into()))?)?;
let bid = split.nth(0).ok_or(AdventError("no score found".into()))?.parse::<u32>()?;
Ok(Line { hand, bid })
}
}
pub fn one() -> Result<u32, AdventError> {
let mut lines = read_into_vec::<Line>(Path::new("resources/input7.txt".into()))?;
lines.sort();
Ok(lines.iter().enumerate().fold(0, |acc, (rank, hand)| {
acc + (rank as u32 + 1) * hand.bid
}))
}
pub fn two() -> Result<u32, AdventError> {
let mut lines = read_into_vec::<Line>(Path::new("resources/input7.txt".into()))?;
lines.sort();
Ok(0)
}

View File

@@ -3,4 +3,5 @@ pub mod day2;
pub mod day3;
pub mod day4;
pub mod day5;
pub mod day6;
pub mod day6;
pub mod day7;

View File

@@ -17,6 +17,7 @@ fn main() -> Result<(), AdventError> {
(day4::one as fn() -> Result<u32, AdventError>, day4::two as fn() -> Result<u32, AdventError>),
(day5::one as fn() -> Result<u32, AdventError>, day5::two as fn() -> Result<u32, AdventError>),
(day6::one as fn() -> Result<u32, AdventError>, day6::two as fn() -> Result<u32, AdventError>),
(day7::one as fn() -> Result<u32, AdventError>, day7::two as fn() -> Result<u32, AdventError>),
];
if env::args().len() == 1 {