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:
parent
44624770cd
commit
03e59ecf8f
1 changed files with 51 additions and 75 deletions
|
@ -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 })
|
||||||
|
@ -79,14 +83,7 @@ impl Ord for Hand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialOrd for Hand {
|
fn hand_type_no_joker(&self) -> HandType {
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
|
|
||||||
Some(self.cmp(other))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Hand {
|
|
||||||
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()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue