Skip to content

Commit cc65aa8

Browse files
committed
Merge branch 'Day7'
2 parents 976512b + d79afdc commit cc65aa8

File tree

3 files changed

+53
-32
lines changed

3 files changed

+53
-32
lines changed

src/bin/day7/README.md

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
# Day 7
22
## Input
3-
You get a list of hands, and your goal is to order them based on the strength of each hand. A hand consists of five cards labeled one of `A, K, Q, J, T, 9, 8, 7, 6, 5, 4, 3, or 2`.
4-
5-
The relative strength of each card follows this order, where `A` is the highest and `2` is the lowest
3+
You get a list of hands & bids pairs, and your goal is to order them based on the strength of each hand.
64
```
75
32T3K 765
86
T55J5 684
97
KK677 28
108
KTJJT 220
119
QQQJA 483
1210
```
11+
A hand consists of five cards labeled one of `A, K, Q, J, T, 9, 8, 7, 6, 5, 4, 3, or 2`. The relative strength of each card follows this order, where `A` is the highest and `2` is the lowest
1312
Every hand is exactly one type. From strongest to weakest, they are:
1413

1514
* **Five of a kind**, where all five cards have the same label: `AAAAA`
@@ -24,12 +23,13 @@ If two hands have the same type, a second ordering rule takes effect. Start by c
2423
## Part 1: Output
2524
Find the rank of every hand in your set and calculate the total winnings of this set of hands by adding up the result of multiplying each hand's bid with its rank
2625
```
27-
Rank 0 - ("32T3K", OnePair) => "32T3K"
28-
Rank 1 - ("JJ958", OnePair) => "JJ958"
26+
Rank 1 - ("32T3K", OnePair) => "32T3K"
2927
Rank 2 - ("KTJJT", TwoPair) => "KTJJT"
3028
Rank 3 - ("KK677", TwoPair) => "KK677"
3129
Rank 4 - ("T55J5", ThreeOfAKind) => "T55J5"
3230
Rank 5 - ("QQQJA", ThreeOfAKind) => "QQQJA
31+
32+
765 * 1 + 220 * 2 + 28 * 3 + 684 * 4 + 483 * 5 = 6440
3333
```
3434
## Part 2: Output
3535
Now, `J` cards are jokers - wildcards that can act like whatever card would make the hand the strongest type possible.
@@ -38,19 +38,20 @@ To balance this, `J` cards are now the weakest individual cards, weaker even tha
3838

3939
Using the new joker rule, find the rank of every hand in your set. What are the new total winnings?
4040
```
41-
Rank 0 - ("32T3K", OnePair) => "32T3K"
42-
Rank 1 - ("KK677", TwoPair) => "KK677"
43-
Rank 2 - ("JJ958", ThreeOfAKind) => "JJ958"
41+
Rank 1 - ("32T3K", OnePair) => "32T3K"
42+
Rank 2 - ("KK677", TwoPair) => "KK677"
4443
Rank 3 - ("T55J5", FourOfAKind) => "T55J5"
4544
Rank 4 - ("QQQJA", FourOfAKind) => "QQQJA"
4645
Rank 5 - ("KTJJT", FourOfAKind) => "KTJJT"
46+
47+
765 * 1 + 28 * 2 + 684 * 3 + 483 * 4 + 220 * 5 = 5905
4748
```
4849
## Approach
49-
To find the type of hand, use a Hashmap to extract the counts for character in the string, then convert the Hashmap to a Vector and reverse sort it. Now you should have in reverse order all the unique cards and card frequency.
50+
To find the type of hand, use a `Hashmap` to extract the frequency per character in the hand, then convert the `Hashmap` to a `Vector` and reverse sort it. Now you should have in reverse order all the unique cards and card frequency i.e. `[('A',2),('J',2),('2',1)]`
5051

51-
Hence the types are derived from two values (a) number of unique cards & (b) the highest card freq
52+
Hence, the types are derived from two values (a) number of unique cards; `array.len()` & (b) the highest card freq; `array[0].freq`
5253
```
53-
match array_length {
54+
match array.len() {
5455
1 => HandType::FiveOfAKind,
5556
2 if array[0].freq ==4 => HandType::FourOfAKind,
5657
2 => HandType::FullHouse,
@@ -65,5 +66,5 @@ The Joker card affects the two key parameters like this
6566
2. `new highest card freq` = highest card freq + Joker card frequency
6667

6768
Watch out for unique hand cases like
68-
1. `JJ123`', hence if Joker is the most frequency card you have to pick the card with `highest card freq` coming after the joker
69-
2. '`JJJJ`' ignore the Joker logic
69+
1. `JJ123`, hence if the Joker is the most frequent card, you have to pick the next in order card that has the highest card frequency after the joker one.
70+
2. `JJJJJ` no joker logic applies in this case

src/bin/day7/hand.rs

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,28 +17,25 @@ pub(crate) struct Hand {
1717
pub(crate) layout: String,
1818
pub(crate) hands_type: HandType,
1919
pub(crate) ord_layout: String,
20-
pub(crate) cards: Vec<(char,u8)>
20+
pub(crate) cards: Vec<(char,u8)>,
21+
joker_pos: Option<usize>
2122
}
2223
impl Hand {
23-
pub(crate) fn get_type(&self, joker: Option<char>) -> HandType {
24+
pub(crate) fn get_type(&self) -> HandType {
2425
let mut unique_cards = self.cards.len() as u32;
25-
let mut most_freq = self.cards[0].1;
26+
let mut freq = self.cards[0].1;
2627

27-
// watch out for cases like `JJ234` or `JJJJJ`
28-
// Joker is the most common card or the only card
29-
if joker.is_some() && unique_cards > 1 {
30-
let j = joker.unwrap();
31-
if let Some(&(_, joker_freq)) = self.cards.iter().find(|(card,_)| card.eq(&j)) {
32-
unique_cards -= 1;
33-
most_freq += if self.cards[0].0 == j { self.cards[1].1 } else { joker_freq };
34-
}
28+
// if we have joker position && and is not a 'JJJJJ' case
29+
if self.joker_pos.is_some() && unique_cards > 1 {
30+
unique_cards -= 1;
31+
freq += self.cards[self.joker_pos.unwrap()].1;
3532
}
3633

3734
match unique_cards {
3835
1 => HandType::FiveOfAKind,
39-
2 if most_freq ==4 => HandType::FourOfAKind,
36+
2 if freq == 4 => HandType::FourOfAKind,
4037
2 => HandType::FullHouse,
41-
3 if most_freq ==3 => HandType::ThreeOfAKind,
38+
3 if freq == 3 => HandType::ThreeOfAKind,
4239
3 => HandType::TwoPair,
4340
4 => HandType::OnePair,
4441
_ => HandType::HighCard
@@ -51,24 +48,46 @@ impl Hand {
5148
.map(|(&i,o)| (i,o) )
5249
.collect::<HashMap<char,char>>();
5350

51+
let mut joker_pos = None;
5452
let (cards,ord_layout)= input.chars()
5553
.fold((HashMap::with_capacity(5),String::with_capacity(5)), |(mut cards, mut ord_layout), card| {
5654
*cards.entry(card).or_insert(0) += 1;
5755
ord_layout.push( ord_card[&card]);
5856
(cards, ord_layout)
5957
});
6058

59+
// extract the HashMap onto an array
6160
let mut cards= cards.into_iter().collect::<Vec<_>>();
62-
cards.sort_by_key(|(_,d)| *d);
61+
// reverse sort the array by order of card freq
62+
// hence the most frequent is 1st, then then 2nd least freq, etc
63+
cards.sort_by_key(|(_,freq)| *freq);
6364
cards.reverse();
6465

66+
// if we are dealing with a Joker case
67+
joker
68+
.is_some_and(|joker| {
69+
// find Joker's freq order i.e. 1st, 2nd, etc and store it for later
70+
// if there is no Joker in the hand, we exit this with None
71+
// no position == no Joker
72+
joker_pos = cards.iter().position(|(card,_)| joker.eq(card));
73+
// if it is 1st and not the only card in the hand; we deal with JJ123 cases
74+
cards.len() > 1 && joker_pos.eq(&Some(0))
75+
})
76+
.then(|| {
77+
// move to the last place & update its position
78+
cards.rotate_left(1);
79+
joker_pos = Some(cards.len()-1);
80+
Some(())
81+
});
82+
6583
let mut hand = Hand {
6684
layout: String::from(input),
6785
ord_layout,
6886
hands_type: HandType::HighCard,
69-
cards
87+
cards,
88+
joker_pos
7089
};
71-
hand.hands_type = hand.get_type(joker);
90+
hand.hands_type = hand.get_type();
7291
hand
7392
}
7493
}
@@ -104,7 +123,7 @@ impl Debug for Hand {
104123
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
105124
f.write_fmt(format_args!("Layout {:?}, ",&self.layout))?;
106125
f.debug_struct("Hand")
107-
.field("type",&self.hands_type)
126+
.field("Type",&self.hands_type)
108127
.finish()?;
109128
f.write_str(", Cards ")?;
110129
f.debug_map()

src/bin/day7/main.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
mod hand;
22

3-
use crate::hand::{Hand,HandType};
3+
use crate::hand::Hand;
44
use std::time::Instant;
55

66
static CAMEL_ORDER_PART1: [char; 13] = [ '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A' ];
@@ -38,6 +38,7 @@ fn main() {
3838
#[cfg(test)]
3939
mod test {
4040
use super::*;
41+
use crate::hand::HandType;
4142

4243
#[test]
4344
fn test_card_ordering_joker() {
@@ -91,7 +92,7 @@ mod test {
9192
vec![OnePair, FourOfAKind, TwoPair, FourOfAKind, FourOfAKind, ThreeOfAKind],
9293
hands.iter()
9394
.inspect(|h| print!("{:?} => ",(&h.layout,&h.ord_layout)))
94-
.map(|h| h.get_type(Some('J')) )
95+
.map(|h| h.get_type() )
9596
.inspect(|ht| println!("{:?}",ht))
9697
.collect::<Vec<HandType>>()
9798
)

0 commit comments

Comments
 (0)