Attempt at day7 part 2

This commit is contained in:
Dennis Brentjes 2023-12-08 11:44:14 +01:00
parent a19e839fe0
commit cacc884cf1

View File

@ -2,24 +2,52 @@ use std::{path::Path, str::FromStr};
use itertools::Itertools; use itertools::Itertools;
use::std::hash::Hash;
use crate::{error::AdventError, input::read_into_vec}; use crate::{error::AdventError, input::read_into_vec};
#[derive(Debug, Eq, PartialEq, Hash)] #[derive(Debug, Eq, PartialEq, Hash)]
struct Card(char); struct CardOne(char);
impl PartialOrd for Card { #[derive(Debug, Eq, PartialEq, Hash)]
enum CardTwo {
Card(char),
Joker,
}
trait Card {
fn strength(self: &Self) -> u32;
}
impl Hash for dyn Card {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.strength().hash(state)
}
}
impl Eq for dyn Card {
}
impl PartialEq for dyn Card {
fn eq(&self, other: &Self) -> bool {
self.strength().eq(&other.strength())
}
}
impl PartialOrd for dyn Card {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.strength().partial_cmp(&other.strength()) self.strength().partial_cmp(&other.strength())
} }
} }
impl Ord for Card { impl Ord for dyn Card {
fn cmp(&self, other: &Self) -> std::cmp::Ordering { fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.strength().cmp(&other.strength()) self.strength().cmp(&other.strength())
} }
} }
impl Card { impl Card for CardOne {
fn strength(self: &Self) -> u32 { fn strength(self: &Self) -> u32 {
match self.0 { match self.0 {
'2' => 2, '2' => 2,
@ -40,6 +68,29 @@ impl Card {
} }
} }
impl Card for CardTwo {
fn strength(self: &Self) -> u32 {
match self {
Self::Card(c) => match c {
'2' => 2,
'3' => 3,
'4' => 4,
'5' => 5,
'6' => 6,
'7' => 7,
'8' => 8,
'9' => 9,
'T' => 10,
'Q' => 12,
'K' => 13,
'A' => 14,
_ => panic!("Invalid card found")
},
Self::Joker => 1
}
}
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
enum HandType { enum HandType {
None, None,
@ -52,43 +103,127 @@ enum HandType {
FiveOfAKind, FiveOfAKind,
} }
#[derive(Debug, Eq)] #[derive(PartialEq, Eq)]
struct Hand { struct HandOne {
cards: [Card;5],
hand_type: HandType, hand_type: HandType,
cards: [Box<dyn Card>;5],
} }
impl PartialOrd for Hand { #[derive(PartialEq, Eq)]
struct HandTwo {
hand_type: HandType,
cards: [Box<dyn Card>;5]
}
impl HandTwo {
fn new() -> Self {
Self {
cards: [
Box::new(CardTwo::Card(' ')),
Box::new(CardTwo::Card(' ')),
Box::new(CardTwo::Card(' ')),
Box::new(CardTwo::Card(' ')),
Box::new(CardTwo::Card(' '))
],
hand_type: HandType::None
}
}
}
impl Hand for HandTwo {
fn determine_type(&mut self) -> () {
todo!()
}
fn get_hand_type(&self) -> &HandType {
todo!()
}
fn get_cards(&self) -> &[Box<dyn Card>;5] {
todo!()
}
}
trait Hand {
fn determine_type(&mut self) -> ();
fn get_hand_type(&self) -> &HandType;
fn get_cards(&self) -> &[Box<dyn Card>;5];
}
impl PartialOrd for dyn Hand {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
match self.hand_type.partial_cmp(&other.hand_type) { match self.get_hand_type().partial_cmp(&other.get_hand_type()) {
Some(core::cmp::Ordering::Equal) => {} Some(core::cmp::Ordering::Equal) => {}
ord => return ord, ord => return ord,
} }
self.cards.partial_cmp(&other.cards) self.get_cards().partial_cmp(&other.get_cards())
} }
} }
impl Ord for Hand { impl Eq for dyn Hand {
}
impl Ord for dyn Hand {
fn cmp(&self, other: &Self) -> std::cmp::Ordering { fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.hand_type.cmp(&other.hand_type) self.get_hand_type().cmp(&other.get_hand_type())
} }
} }
impl PartialEq for Hand { impl PartialEq for dyn Hand {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.hand_type == other.hand_type self.get_hand_type() == other.get_hand_type()
} }
} }
impl Hand { impl HandOne {
fn new() -> Self { fn new() -> Self {
Hand { Self {
cards: [Card(' '), Card(' '), Card(' '), Card(' '), Card(' ')], cards: [
Box::new(CardOne(' ')),
Box::new(CardOne(' ')),
Box::new(CardOne(' ')),
Box::new(CardOne(' ')),
Box::new(CardOne(' '))
],
hand_type: HandType::None hand_type: HandType::None
} }
} }
}
impl FromStr for HandOne {
type Err = AdventError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut hand = HandOne::new();
for i in 0..s.len() {
hand.cards[i] = Box::new(CardOne(s.chars().nth(i).ok_or(AdventError("Couldn't convert into Card".into()))?));
}
hand.determine_type();
Ok(hand)
}
}
impl FromStr for HandTwo {
type Err = AdventError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut hand = HandTwo::new();
for i in 0..s.len() {
hand.cards[i] = Box::new(match s.chars().nth(i).ok_or(AdventError("Couldn't convert into Card".into()))? {
'J' => CardTwo::Joker,
c => CardTwo::Card(c),
});
};
hand.determine_type();
Ok(hand)
}
}
impl Hand for HandOne {
fn determine_type(&mut self) -> () { fn determine_type(&mut self) -> () {
let counts = self.cards.iter().counts(); let counts = self.cards.iter().counts();
let value_counts = counts.iter().map(|c| { c.1 }).collect_vec(); let value_counts = counts.iter().map(|c| { c.1 }).collect_vec();
@ -113,36 +248,41 @@ impl Hand {
(_, _) => panic!("Hand type match should never fail") (_, _) => panic!("Hand type match should never fail")
}; };
} }
fn get_hand_type(&self) -> &HandType {
&self.hand_type
} }
fn get_cards(&self) -> &[Box<dyn Card>;5] {
&self.cards
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)] #[derive(Eq)]
struct Line { struct LineOne {
hand: Hand, hand: Box<dyn Hand>,
bid: u32, bid: u32,
} }
impl PartialEq for Line { #[derive(Eq)]
struct LineTwo {
hand: Box<dyn Hand>,
bid: u32,
}
impl PartialEq for LineOne {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.hand == other.hand self.hand.as_ref() == other.hand.as_ref()
} }
} }
impl PartialOrd for Line { impl PartialEq for LineTwo {
fn eq(&self, other: &Self) -> bool {
self.hand.as_ref() == other.hand.as_ref()
}
}
impl PartialOrd for LineOne {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
match self.hand.partial_cmp(&other.hand) { match self.hand.partial_cmp(&other.hand) {
Some(core::cmp::Ordering::Equal) => {} Some(core::cmp::Ordering::Equal) => {}
@ -152,25 +292,52 @@ impl PartialOrd for Line {
} }
} }
impl Ord for Line { impl PartialOrd for LineTwo {
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 LineOne {
fn cmp(&self, other: &Self) -> std::cmp::Ordering { fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.hand.cmp(&other.hand) self.hand.cmp(&other.hand)
} }
} }
impl FromStr for Line { impl Ord for LineTwo {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.hand.cmp(&other.hand)
}
}
impl FromStr for LineOne {
type Err = AdventError; type Err = AdventError;
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut split = s.trim().split_ascii_whitespace(); let mut split = s.trim().split_ascii_whitespace();
let hand = Hand::from_str(split.nth(0).ok_or(AdventError("no hand found".into()))?)?; let hand = Box::new(HandOne::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>()?; let bid = split.nth(0).ok_or(AdventError("no score found".into()))?.parse::<u32>()?;
Ok(Line { hand, bid }) Ok(Self { hand, bid })
}
}
impl FromStr for LineTwo {
type Err = AdventError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut split = s.trim().split_ascii_whitespace();
let hand = Box::new(HandTwo::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(Self { hand, bid })
} }
} }
pub fn one() -> Result<u32, AdventError> { pub fn one() -> Result<u32, AdventError> {
let mut lines = read_into_vec::<Line>(Path::new("resources/input7.txt".into()))?; let mut lines = read_into_vec::<LineOne>(Path::new("resources/input7.txt".into()))?;
lines.sort(); lines.sort();
Ok(lines.iter().enumerate().fold(0, |acc, (rank, hand)| { Ok(lines.iter().enumerate().fold(0, |acc, (rank, hand)| {
acc + (rank as u32 + 1) * hand.bid acc + (rank as u32 + 1) * hand.bid
@ -178,7 +345,7 @@ pub fn one() -> Result<u32, AdventError> {
} }
pub fn two() -> Result<u32, AdventError> { pub fn two() -> Result<u32, AdventError> {
let mut lines = read_into_vec::<Line>(Path::new("resources/input7.txt".into()))?; let mut lines = read_into_vec::<LineTwo>(Path::new("resources/input7.txt".into()))?;
lines.sort(); lines.sort();
Ok(0) Ok(0)
} }