Part 07
This commit is contained in:
18
.vscode/launch.json
vendored
18
.vscode/launch.json
vendored
@@ -188,6 +188,24 @@
|
||||
},
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}"
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "Debug executable 'part07'",
|
||||
"cargo": {
|
||||
"args": [
|
||||
"build",
|
||||
"--bin=part07",
|
||||
"--package=advent-of-code-2023"
|
||||
],
|
||||
"filter": {
|
||||
"name": "part07",
|
||||
"kind": "bin"
|
||||
}
|
||||
},
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}"
|
||||
}
|
||||
]
|
||||
}
|
||||
156
src/bin/part07.rs
Normal file
156
src/bin/part07.rs
Normal file
@@ -0,0 +1,156 @@
|
||||
use std::{collections::HashMap, time};
|
||||
|
||||
#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Clone, Hash)]
|
||||
enum HandType {
|
||||
FiveOfAKind,
|
||||
FourOfAKind,
|
||||
FullHouse,
|
||||
ThreeOfAKind,
|
||||
TwoPair,
|
||||
OnePair,
|
||||
HighCard,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Hand {
|
||||
cards: String,
|
||||
handtype: HandType,
|
||||
bid: u32,
|
||||
rank: u32,
|
||||
}
|
||||
|
||||
impl Hand {
|
||||
fn new(cards: String, bid: u32) -> Hand {
|
||||
let handtype = get_handtype(&cards);
|
||||
Hand { cards, handtype, bid, rank: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
fn get_card_rank(hand: &Hand, index: u8) -> u8 {
|
||||
match hand.cards.chars().nth(index as usize).unwrap() {
|
||||
'2' => 1,
|
||||
'3' => 2,
|
||||
'4' => 3,
|
||||
'5' => 4,
|
||||
'6' => 5,
|
||||
'7' => 6,
|
||||
'8' => 7,
|
||||
'9' => 8,
|
||||
'T' => 9,
|
||||
'J' => 0, // 10 in Part 1, 0 in Part 2
|
||||
'Q' => 11,
|
||||
'K' => 12,
|
||||
'A' => 13,
|
||||
_ => panic!("Invalid card rank"),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_handtype(cards: &String) -> HandType {
|
||||
let cards = cards.chars().collect::<Vec<_>>();
|
||||
let mut card_counts = HashMap::new();
|
||||
|
||||
for card in cards.clone() {
|
||||
if card == 'J' {
|
||||
continue;
|
||||
}
|
||||
let count = card_counts.entry(card).or_insert(0);
|
||||
*count += 1;
|
||||
}
|
||||
|
||||
let mut counts: Vec<u32> = card_counts.values().map(|v| *v as u32).collect::<Vec<_>>();
|
||||
counts.sort();
|
||||
|
||||
let total_counts = counts.iter().sum::<u32>();
|
||||
if (1..5).contains(&total_counts) {
|
||||
let highest_count = counts.last_mut().unwrap();
|
||||
*highest_count += cards.len() as u32 - total_counts;
|
||||
} else if total_counts == 0 {
|
||||
counts.push(5);
|
||||
}
|
||||
|
||||
match counts.as_slice() {
|
||||
[5] => HandType::FiveOfAKind,
|
||||
[1, 4] => HandType::FourOfAKind,
|
||||
[2, 3] => HandType::FullHouse,
|
||||
[1, 1, 3] => HandType::ThreeOfAKind,
|
||||
[1, 2, 2] => HandType::TwoPair,
|
||||
[1, 1, 1, 2] => HandType::OnePair,
|
||||
_ => HandType::HighCard,
|
||||
}
|
||||
}
|
||||
|
||||
fn sort_by_value(hands: &Vec<Hand>) -> Vec<Hand> {
|
||||
let mut hands = hands.to_vec();
|
||||
|
||||
if hands.len() < 2 {
|
||||
return hands;
|
||||
}
|
||||
|
||||
hands.sort_by(|b, a| {
|
||||
get_card_rank(a, 0).cmp(&get_card_rank(b, 0))
|
||||
.then(get_card_rank(a, 1).cmp(&get_card_rank(b, 1)))
|
||||
.then(get_card_rank(a, 2).cmp(&get_card_rank(b, 2)))
|
||||
.then(get_card_rank(a, 3).cmp(&get_card_rank(b, 3)))
|
||||
.then(get_card_rank(a, 4).cmp(&get_card_rank(b, 4)))
|
||||
});
|
||||
|
||||
hands
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let s1 = time::Instant::now();
|
||||
|
||||
let mut hands = load_input();
|
||||
|
||||
let d1 = s1.elapsed();
|
||||
println!("Loading: {:?}", d1);
|
||||
|
||||
let s2 = time::Instant::now();
|
||||
|
||||
let groups = hands.iter().fold(HashMap::new(), |mut acc, hand| {
|
||||
let group = acc.entry(hand.handtype.clone()).or_insert(Vec::new());
|
||||
group.push(hand.clone());
|
||||
acc
|
||||
});
|
||||
|
||||
hands = Vec::new();
|
||||
|
||||
for group_hands in groups.values() {
|
||||
hands.extend(sort_by_value(&group_hands));
|
||||
}
|
||||
|
||||
hands.sort_by(|a, b| a.handtype.cmp(&b.handtype));
|
||||
|
||||
for (i, hand) in hands.iter_mut().rev().enumerate() {
|
||||
hand.rank = (i + 1) as u32;
|
||||
}
|
||||
|
||||
hands.sort_by(|a, b| b.rank.cmp(&a.rank));
|
||||
|
||||
// for hand in hands.clone() {
|
||||
// println!("[{:>4}] Hand: {:?}, Bid: {:>4}, Handtype: {:?} -> Win: {:>5}", hand.rank, hand.cards, hand.bid, hand.handtype, hand.rank * hand.bid);
|
||||
// }
|
||||
|
||||
let winnings = hands.iter().map(|h| h.bid * h.rank as u32).sum::<u32>();
|
||||
|
||||
let d2 = s2.elapsed();
|
||||
println!("Calculating: {:?}", d2);
|
||||
println!("Total: {:?}", d1 + d2);
|
||||
|
||||
println!("Winnings: {}", winnings);
|
||||
}
|
||||
|
||||
fn load_input() -> Vec<Hand> {
|
||||
let data = std::fs::read_to_string("src/bin/part07.txt")
|
||||
.expect("Could not read file")
|
||||
.lines()
|
||||
.map(|l| {
|
||||
let mut cards = l.split_whitespace();
|
||||
let hand = cards.by_ref().next().unwrap().to_string();
|
||||
let bid = cards.by_ref().next().unwrap().parse::<u32>().unwrap();
|
||||
|
||||
Hand::new(hand, bid)
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
data
|
||||
}
|
||||
5
src/bin/part07.sample
Normal file
5
src/bin/part07.sample
Normal file
@@ -0,0 +1,5 @@
|
||||
32T3K 765
|
||||
T55J5 684
|
||||
KK677 28
|
||||
KTJJT 220
|
||||
QQQJA 483
|
||||
1000
src/bin/part07.txt
Normal file
1000
src/bin/part07.txt
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user