This commit is contained in:
MaxJa4
2023-12-08 20:12:32 +01:00
parent 4b55f4524e
commit f3b87802c4
4 changed files with 1179 additions and 0 deletions

18
.vscode/launch.json vendored
View File

@@ -188,6 +188,24 @@
}, },
"args": [], "args": [],
"cwd": "${workspaceFolder}" "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
View 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
View File

@@ -0,0 +1,5 @@
32T3K 765
T55J5 684
KK677 28
KTJJT 220
QQQJA 483

1000
src/bin/part07.txt Normal file

File diff suppressed because it is too large Load Diff