optimized day07.
This commit is contained in:
parent
46c164c2d8
commit
6ce20d7c69
16
Cargo.lock
generated
16
Cargo.lock
generated
|
@ -68,6 +68,7 @@ name = "day07"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aoc_libs",
|
"aoc_libs",
|
||||||
|
"itertools",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"regex",
|
"regex",
|
||||||
]
|
]
|
||||||
|
@ -82,6 +83,21 @@ dependencies = [
|
||||||
"regex",
|
"regex",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.6.4"
|
version = "2.6.4"
|
||||||
|
|
|
@ -20,3 +20,4 @@ once_cell = "1.16"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
nom = "7.1"
|
nom = "7.1"
|
||||||
collection_literals = "1.0.1"
|
collection_literals = "1.0.1"
|
||||||
|
itertools = "0.12.0"
|
||||||
|
|
|
@ -9,3 +9,4 @@ edition.workspace = true
|
||||||
aoc_libs.workspace = true
|
aoc_libs.workspace = true
|
||||||
regex.workspace = true
|
regex.workspace = true
|
||||||
once_cell.workspace = true
|
once_cell.workspace = true
|
||||||
|
itertools.workspace = true
|
||||||
|
|
|
@ -10,5 +10,5 @@ fn main() {
|
||||||
println!("Result: {}", part1::part1(&mut structured_input));
|
println!("Result: {}", part1::part1(&mut structured_input));
|
||||||
|
|
||||||
println!("Part Two");
|
println!("Part Two");
|
||||||
println!("Result: {}", part2::part2(&structured_input));
|
println!("Result: {}", part2::part2(&mut structured_input));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
|
use itertools::Itertools;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
|
||||||
pub enum Card {
|
pub enum Card {
|
||||||
Ace = 14,
|
Ace = 14,
|
||||||
King = 13,
|
King = 13,
|
||||||
|
@ -19,7 +20,7 @@ pub enum Card {
|
||||||
Joker = 1,
|
Joker = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
|
||||||
pub enum Formation {
|
pub enum Formation {
|
||||||
FiveOfKind = 7,
|
FiveOfKind = 7,
|
||||||
FourOfKind = 6,
|
FourOfKind = 6,
|
||||||
|
@ -30,29 +31,24 @@ pub enum Formation {
|
||||||
HighCard = 1,
|
HighCard = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Default)]
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
struct UnorderedHand {
|
pub struct Hand {
|
||||||
ace: u8,
|
formation: Formation,
|
||||||
king: u8,
|
cards: [Card; 5],
|
||||||
queen: u8,
|
|
||||||
jack: u8,
|
|
||||||
tim: u8,
|
|
||||||
nine: u8,
|
|
||||||
eight: u8,
|
|
||||||
seven: u8,
|
|
||||||
six: u8,
|
|
||||||
five: u8,
|
|
||||||
four: u8,
|
|
||||||
three: u8,
|
|
||||||
two: u8,
|
|
||||||
joker: u8,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UnorderedHand {
|
impl Hand {
|
||||||
fn determine_formation(&self) -> Formation {
|
pub fn new(cards: [Card; 5]) -> Hand {
|
||||||
let amounts = self.get_vec_of_amounts();
|
Hand {
|
||||||
let types = amounts.len();
|
formation: Self::determine_formation(&cards),
|
||||||
let max_of_type = *amounts.iter().max().unwrap_or(&0) + self.joker;
|
cards,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn determine_formation(cards: &[Card; 5]) -> Formation {
|
||||||
|
let mut counts = cards.iter().counts();
|
||||||
|
let jokers = counts.remove(&Card::Joker).unwrap_or(0);
|
||||||
|
let types = counts.len();
|
||||||
|
let max_of_type = counts.into_values().max().unwrap_or(0) + jokers;
|
||||||
match types {
|
match types {
|
||||||
// if 0 types, they are all joker.
|
// if 0 types, they are all joker.
|
||||||
0 => Formation::FiveOfKind,
|
0 => Formation::FiveOfKind,
|
||||||
|
@ -63,7 +59,7 @@ impl UnorderedHand {
|
||||||
match max_of_type {
|
match max_of_type {
|
||||||
4 => Formation::FourOfKind,
|
4 => Formation::FourOfKind,
|
||||||
3 => Formation::FullHouse,
|
3 => Formation::FullHouse,
|
||||||
_ => panic!("idk what type of hand this is: {:?}", self),
|
_ => panic!("idk what type of hand this is: {:?}", cards),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
3 => {
|
3 => {
|
||||||
|
@ -71,7 +67,7 @@ impl UnorderedHand {
|
||||||
match max_of_type {
|
match max_of_type {
|
||||||
3 => Formation::ThreeOfKind,
|
3 => Formation::ThreeOfKind,
|
||||||
2 => Formation::TwoPair,
|
2 => Formation::TwoPair,
|
||||||
_ => panic!("idk what type of hand this is: {:?}", self),
|
_ => panic!("idk what type of hand this is: {:?}", cards),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
4 => Formation::OnePair,
|
4 => Formation::OnePair,
|
||||||
|
@ -79,114 +75,10 @@ impl UnorderedHand {
|
||||||
_ => panic!("how are there more than 5 types!"),
|
_ => panic!("how are there more than 5 types!"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// just to make iteration easier
|
pub fn turn_jacks_to_jokers(&mut self) {
|
||||||
fn get_vec_of_amounts(&self) -> Vec<u8> {
|
self.cards = self
|
||||||
let mut ret = Vec::new();
|
.cards
|
||||||
if self.ace > 0 {
|
.map(|c| if c == Card::Jack { Card::Joker } else { c });
|
||||||
ret.push(self.ace);
|
|
||||||
}
|
|
||||||
if self.king > 0 {
|
|
||||||
ret.push(self.king);
|
|
||||||
}
|
|
||||||
if self.queen > 0 {
|
|
||||||
ret.push(self.queen);
|
|
||||||
}
|
|
||||||
if self.jack > 0 {
|
|
||||||
ret.push(self.jack);
|
|
||||||
}
|
|
||||||
if self.tim > 0 {
|
|
||||||
ret.push(self.tim);
|
|
||||||
}
|
|
||||||
if self.nine > 0 {
|
|
||||||
ret.push(self.nine);
|
|
||||||
}
|
|
||||||
if self.eight > 0 {
|
|
||||||
ret.push(self.eight);
|
|
||||||
}
|
|
||||||
if self.seven > 0 {
|
|
||||||
ret.push(self.seven);
|
|
||||||
}
|
|
||||||
if self.six > 0 {
|
|
||||||
ret.push(self.six);
|
|
||||||
}
|
|
||||||
if self.five > 0 {
|
|
||||||
ret.push(self.five);
|
|
||||||
}
|
|
||||||
if self.four > 0 {
|
|
||||||
ret.push(self.four);
|
|
||||||
}
|
|
||||||
if self.three > 0 {
|
|
||||||
ret.push(self.three);
|
|
||||||
}
|
|
||||||
if self.two > 0 {
|
|
||||||
ret.push(self.two);
|
|
||||||
}
|
|
||||||
ret
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
|
||||||
pub struct Hand {
|
|
||||||
pub cards: [Card; 5],
|
|
||||||
unordered_hand: UnorderedHand,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Hand {
|
|
||||||
pub fn new(cards: [Card; 5]) -> Hand {
|
|
||||||
Hand {
|
|
||||||
unordered_hand: Self::get_unordered_hand(&cards),
|
|
||||||
cards,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn determine_formation(&self) -> Formation {
|
|
||||||
self.unordered_hand.determine_formation()
|
|
||||||
}
|
|
||||||
fn get_unordered_hand(cards: &[Card]) -> UnorderedHand {
|
|
||||||
cards
|
|
||||||
.iter()
|
|
||||||
.fold(UnorderedHand::default(), |mut acc, card| {
|
|
||||||
match card {
|
|
||||||
Card::Ace => acc.ace += 1,
|
|
||||||
Card::King => acc.king += 1,
|
|
||||||
Card::Queen => acc.queen += 1,
|
|
||||||
Card::Jack => acc.jack += 1,
|
|
||||||
Card::Tim => acc.tim += 1,
|
|
||||||
Card::Nine => acc.nine += 1,
|
|
||||||
Card::Eight => acc.eight += 1,
|
|
||||||
Card::Seven => acc.seven += 1,
|
|
||||||
Card::Six => acc.six += 1,
|
|
||||||
Card::Five => acc.five += 1,
|
|
||||||
Card::Four => acc.four += 1,
|
|
||||||
Card::Three => acc.three += 1,
|
|
||||||
Card::Two => acc.two += 1,
|
|
||||||
Card::Joker => acc.joker += 1,
|
|
||||||
};
|
|
||||||
acc
|
|
||||||
})
|
|
||||||
}
|
|
||||||
pub fn turn_jacks_to_jokers(&self) -> Hand {
|
|
||||||
Hand::new(
|
|
||||||
self.cards
|
|
||||||
.map(|c| if c == Card::Jack { Card::Joker } else { c }),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Ord for Hand {
|
|
||||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
|
||||||
let self_formation = self.determine_formation();
|
|
||||||
let other_formation = other.determine_formation();
|
|
||||||
if self_formation != other_formation {
|
|
||||||
self_formation.cmp(&other_formation)
|
|
||||||
} else {
|
|
||||||
self.cards.cmp(&other.cards)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialOrd for Hand {
|
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
|
||||||
Some(self.cmp(other))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -339,10 +231,7 @@ mod tests {
|
||||||
41,
|
41,
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
input = input
|
input.iter_mut().for_each(|i| i.0.turn_jacks_to_jokers());
|
||||||
.into_iter()
|
|
||||||
.map(|c| (c.0.turn_jacks_to_jokers(), c.1))
|
|
||||||
.collect();
|
|
||||||
input.sort_by(|a, b| a.0.cmp(&b.0));
|
input.sort_by(|a, b| a.0.cmp(&b.0));
|
||||||
println!("{:#?}", input);
|
println!("{:#?}", input);
|
||||||
//check that the bids are sorted (the input is curated to ensure that the bids are sorted
|
//check that the bids are sorted (the input is curated to ensure that the bids are sorted
|
||||||
|
@ -460,12 +349,9 @@ mod tests {
|
||||||
Formation::FiveOfKind,
|
Formation::FiveOfKind,
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
tests = tests
|
tests.iter_mut().for_each(|i| i.0.turn_jacks_to_jokers());
|
||||||
.into_iter()
|
|
||||||
.map(|c| (c.0.turn_jacks_to_jokers(), c.1))
|
|
||||||
.collect();
|
|
||||||
for test in tests {
|
for test in tests {
|
||||||
assert_eq!(test.0.determine_formation(), test.1)
|
assert_eq!(test.0.formation, test.1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -650,7 +536,7 @@ mod tests {
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
for test in tests {
|
for test in tests {
|
||||||
assert_eq!(test.0.determine_formation(), test.1)
|
assert_eq!(test.0.formation, test.1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
use crate::parse::*;
|
use crate::parse::*;
|
||||||
|
|
||||||
pub fn part2(input: &[(Hand, u32)]) -> usize {
|
pub fn part2(input: &mut [(Hand, u32)]) -> usize {
|
||||||
let mut input: Vec<(Hand, u32)> = input
|
input.iter_mut().for_each(|i| i.0.turn_jacks_to_jokers());
|
||||||
.iter()
|
|
||||||
.map(|c| (c.0.turn_jacks_to_jokers(), c.1))
|
|
||||||
.collect();
|
|
||||||
input.sort_by(|a, b| a.0.cmp(&b.0) );
|
input.sort_by(|a, b| a.0.cmp(&b.0) );
|
||||||
input
|
input
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -19,7 +16,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_part2() {
|
fn test_part2() {
|
||||||
let input = vec![
|
let mut input = vec![
|
||||||
(
|
(
|
||||||
Hand::new([Card::Two, Card::Three, Card::Four, Card::Five, Card::Ace]),
|
Hand::new([Card::Two, Card::Three, Card::Four, Card::Five, Card::Ace]),
|
||||||
1,
|
1,
|
||||||
|
@ -127,6 +124,6 @@ mod tests {
|
||||||
41,
|
41,
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
assert_eq!(part2(&input), 6839);
|
assert_eq!(part2(&mut input), 6839);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue