1
0
Fork 0

day(07): don't implement Ord

Makes it easier to implement a function that generates comparator based
on the card ranking and the hand type deduction.

Signed-off-by: Matej Focko <mfocko@redhat.com>
This commit is contained in:
Matej Focko 2023-12-07 10:26:54 +01:00
parent 44624770cd
commit 03e59ecf8f
Signed by: mfocko
GPG key ID: 7C47D46246790496

View file

@ -20,7 +20,7 @@ enum HandType {
} }
lazy_static! { lazy_static! {
static ref CARDS: Vec<char> = static ref CARDS_1: Vec<char> =
vec!['2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A',]; vec!['2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A',];
static ref CARDS_2: Vec<char> = static ref CARDS_2: Vec<char> =
vec!['J', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'Q', 'K', 'A',]; vec!['J', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'Q', 'K', 'A',];
@ -45,10 +45,14 @@ impl FromStr for Hand {
} }
} }
impl Ord for Hand { impl Hand {
fn cmp(&self, other: &Self) -> cmp::Ordering { fn make_comparator<'a>(
let my_type = self.hand_type(); card_ordering: &'a [char],
let other_type = other.hand_type(); hand_type_getter: &'a dyn Fn(&Self) -> HandType,
) -> impl Fn(&Hand, &Hand) -> cmp::Ordering + 'a {
|x: &Self, y: &Self| {
let my_type = hand_type_getter(x);
let other_type = hand_type_getter(y);
match my_type.partial_cmp(&other_type) { match my_type.partial_cmp(&other_type) {
Some(cmp::Ordering::Equal) => {} Some(cmp::Ordering::Equal) => {}
@ -56,13 +60,13 @@ impl Ord for Hand {
_ => {} _ => {}
} }
for (my, other) in self.cards.iter().zip(other.cards.iter()) { for (my, other) in x.cards.iter().zip(y.cards.iter()) {
let l = CARDS let l = card_ordering
.iter() .iter()
.enumerate() .enumerate()
.find_map(|(i, c)| if c == my { Some(i) } else { None }) .find_map(|(i, c)| if c == my { Some(i) } else { None })
.unwrap(); .unwrap();
let r = CARDS let r = card_ordering
.iter() .iter()
.enumerate() .enumerate()
.find_map(|(i, c)| if c == other { Some(i) } else { None }) .find_map(|(i, c)| if c == other { Some(i) } else { None })
@ -77,16 +81,9 @@ impl Ord for Hand {
cmp::Ordering::Equal cmp::Ordering::Equal
} }
}
impl PartialOrd for Hand {
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
Some(self.cmp(other))
} }
}
impl Hand { fn hand_type_no_joker(&self) -> HandType {
fn hand_type(&self) -> HandType {
let freqs = self.cards.iter().counts(); let freqs = self.cards.iter().counts();
let mut pairs = 0; let mut pairs = 0;
@ -154,6 +151,23 @@ impl Hand {
struct Day07 { struct Day07 {
hands: Vec<Hand>, hands: Vec<Hand>,
} }
impl Day07 {
fn solve(
&mut self,
card_ordering: &[char],
hand_type_getter: &dyn Fn(&Hand) -> HandType,
) -> i32 {
self.hands
.sort_by(Hand::make_comparator(card_ordering, hand_type_getter));
self.hands
.iter()
.enumerate()
.map(|(r, h)| (r as i32 + 1) * h.bid)
.sum()
}
}
impl Solution<Output1, Output2> for Day07 { impl Solution<Output1, Output2> for Day07 {
fn new<P: AsRef<Path>>(pathname: P) -> Self { fn new<P: AsRef<Path>>(pathname: P) -> Self {
let hands = file_to_structs(pathname); let hands = file_to_structs(pathname);
@ -162,49 +176,11 @@ impl Solution<Output1, Output2> for Day07 {
} }
fn part_1(&mut self) -> Output1 { fn part_1(&mut self) -> Output1 {
self.hands.sort(); self.solve(&CARDS_1, &Hand::hand_type_no_joker)
self.hands
.iter()
.enumerate()
.map(|(r, h)| (r as i32 + 1) * h.bid)
.sum()
} }
fn part_2(&mut self) -> Output2 { fn part_2(&mut self) -> Output2 {
self.hands.sort_by(|x, y| { self.solve(&CARDS_2, &Hand::hand_type_with_joker)
let my_type = x.hand_type_with_joker();
let other_type = y.hand_type_with_joker();
match my_type.partial_cmp(&other_type) {
Some(core::cmp::Ordering::Equal) => {}
ord => return ord.unwrap(),
}
for (my, other) in x.cards.iter().zip(y.cards.iter()) {
let l = CARDS_2
.iter()
.enumerate()
.find_map(|(i, c)| if c == my { Some(i) } else { None })
.unwrap();
let r = CARDS_2
.iter()
.enumerate()
.find_map(|(i, c)| if c == other { Some(i) } else { None })
.unwrap();
match l.partial_cmp(&r) {
Some(core::cmp::Ordering::Equal) => {}
ord => return ord.unwrap(),
}
}
unreachable!()
});
self.hands
.iter()
.enumerate()
.map(|(r, h)| (r as i32 + 1) * h.bid)
.sum()
} }
} }