Part 07
This commit is contained in:
18
.vscode/launch.json
vendored
18
.vscode/launch.json
vendored
@@ -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
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