Attempt at day7 part 2

This commit is contained in:
Dennis Brentjes 2023-12-08 11:44:14 +01:00
parent a19e839fe0
commit cacc884cf1
1 changed files with 208 additions and 41 deletions

View File

@ -2,24 +2,52 @@ use std::{path::Path, str::FromStr};
use itertools::Itertools;
use::std::hash::Hash;
use crate::{error::AdventError, input::read_into_vec};
#[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> {
self.strength().partial_cmp(&other.strength())
}
}
impl Ord for Card {
impl Ord for dyn Card {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.strength().cmp(&other.strength())
}
}
impl Card {
impl Card for CardOne {
fn strength(self: &Self) -> u32 {
match self.0 {
'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)]
enum HandType {
None,
@ -52,43 +103,127 @@ enum HandType {
FiveOfAKind,
}
#[derive(Debug, Eq)]
struct Hand {
cards: [Card;5],
#[derive(PartialEq, Eq)]
struct HandOne {
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> {
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) => {}
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 {
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 {
self.hand_type == other.hand_type
self.get_hand_type() == other.get_hand_type()
}
}
impl Hand {
impl HandOne {
fn new() -> Self {
Hand {
cards: [Card(' '), Card(' '), Card(' '), Card(' '), Card(' ')],
Self {
cards: [
Box::new(CardOne(' ')),
Box::new(CardOne(' ')),
Box::new(CardOne(' ')),
Box::new(CardOne(' ')),
Box::new(CardOne(' '))
],
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) -> () {
let counts = self.cards.iter().counts();
let value_counts = counts.iter().map(|c| { c.1 }).collect_vec();
@ -113,36 +248,41 @@ impl Hand {
(_, _) => panic!("Hand type match should never fail")
};
}
}
fn get_hand_type(&self) -> &HandType {
&self.hand_type
}
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)
fn get_cards(&self) -> &[Box<dyn Card>;5] {
&self.cards
}
}
#[derive(Debug, Eq)]
struct Line {
hand: Hand,
#[derive(Eq)]
struct LineOne {
hand: Box<dyn Hand>,
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 {
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> {
match self.hand.partial_cmp(&other.hand) {
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 {
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;
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 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>()?;
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> {
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();
Ok(lines.iter().enumerate().fold(0, |acc, (rank, hand)| {
acc + (rank as u32 + 1) * hand.bid
@ -178,7 +345,7 @@ pub fn one() -> 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();
Ok(0)
}