This commit is contained in:
RingOfStorms (Joshua Bell) 2023-12-07 23:05:38 -06:00
parent 3be4845987
commit 5e42561567
4 changed files with 1167 additions and 44 deletions

View file

@ -27,3 +27,7 @@ tokio = { version = "1", features = ["full"] }
itertools = "0.12" itertools = "0.12"
derive_builder = "0.12.0" derive_builder = "0.12.0"
rayon = "1.8.0" rayon = "1.8.0"
[features]
part2 = []
default = ["part2"]

1000
aoc_puzzle_cache/day_7 Normal file

File diff suppressed because it is too large Load diff

View file

@ -2,52 +2,170 @@ use aoc23::prelude::*;
use derive_builder::Builder; use derive_builder::Builder;
use itertools::Itertools; use itertools::Itertools;
use rayon::prelude::*; use rayon::prelude::*;
use std::{str::FromStr, time::Instant}; use std::{
cmp::Ordering,
str::FromStr,
time::Instant,
};
#[derive(Debug, Builder, Clone)] #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)]
struct Todo {} enum Strength {
HighCard,
OnePair,
TwoPair,
ThreeOfAKind,
FullHouse,
FourOfAKind,
FiveOfAKind,
}
impl FromStr for Todo { impl Strength {
type Err = BoxE; #[cfg(feature = "part2")]
fn for_hand(hand: &Hand) -> Self {
let mut possible_counts: Vec<[i32; 14]> = vec![[0; 14]];
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> { // let mut counts = [0; 14]; let mut jokers = 0;
Ok(TodoBuilder::default().build()?) for card in hand.cards.iter() {
if card == &1 {
for possible_count in possible_counts.iter() { }
jokers += 1;
} else {
counts[*card as usize - 2] += 1;
}
}
// CURRENT BUG is that the jokers are adding to all counts so the counts are "off"
// for possible real hands like full house etc, need to branch off and try all
// combinations...
counts.iter().fold(Strength::HighCard, |strength, &count| {
std::cmp::max(strength.clone(), match count {
5 => Strength::FiveOfAKind,
4 => Strength::FourOfAKind,
3 => match strength {
Strength::TwoPair => Strength::FullHouse,
Strength::OnePair => Strength::FullHouse,
_ => Strength::ThreeOfAKind,
},
2 => match strength {
Strength::ThreeOfAKind => Strength::FullHouse,
Strength::OnePair => Strength::TwoPair,
_ => Strength::OnePair,
},
_ => strength,
})
})
}
#[cfg(not(feature = "part2"))]
fn for_hand(hand: &Hand) -> Self {
let mut counts = [0; 15];
for card in hand.cards.iter() {
counts[*card as usize - 2] += 1;
}
counts.iter().fold(Strength::HighCard, |strength, &count| match count {
5 => Strength::FiveOfAKind,
4 => Strength::FourOfAKind,
3 => match strength {
Strength::TwoPair => Strength::FullHouse,
Strength::OnePair => Strength::FullHouse,
_ => Strength::ThreeOfAKind,
},
2 => match strength {
Strength::ThreeOfAKind => Strength::FullHouse,
Strength::OnePair => Strength::TwoPair,
_ => Strength::OnePair,
},
_ => strength,
})
} }
} }
fn part1(input: String) -> Result<usize> { #[derive(Debug, Builder, Clone, PartialEq, Eq)]
// parse struct Hand {
let start = Instant::now(); cards: Vec<u32>,
let todo: Todo = input.parse()?; bid: usize,
let parsed_time = start.elapsed();
// algo
let start = Instant::now();
let answer = 0;
let algo_time = start.elapsed();
// output
println!("Day 5, part 1: {answer}");
println!("\tparse: {parsed_time:?}");
println!("\talgo: {algo_time:?}");
Ok(answer)
} }
fn part2(input: String) -> Result<usize> { impl Ord for Hand {
// parse fn cmp(&self, other: &Self) -> std::cmp::Ordering {
let start = Instant::now(); let self_strength = Strength::for_hand(self);
let todo: Todo = input.parse()?; let other_strength = Strength::for_hand(other);
let parsed_time = start.elapsed(); match self_strength.cmp(&other_strength) {
Ordering::Equal => self
.cards
.iter()
.zip(other.cards.iter())
.map(|(s, o)| s.cmp(o))
.skip_while(|ord| matches!(ord, Ordering::Equal))
.next()
.unwrap_or(Ordering::Equal),
Ordering::Less => Ordering::Less,
Ordering::Greater => Ordering::Greater,
}
}
}
// algo impl PartialOrd for Hand {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl FromStr for Hand {
type Err = BoxE;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
let mut splits = s.trim().split_whitespace();
Ok(HandBuilder::default().cards(splits.next().unwrap().chars().map(|c| {
if let Some(digit) = c.to_digit(10) {
digit
} else {
match c {
#[cfg(not(feature = "part2"))]
'A' => 14,
#[cfg(feature = "part2")]
'A' => 13,
#[cfg(not(feature = "part2"))]
'K' => 13,
#[cfg(feature = "part2")]
'K' => 12,
#[cfg(not(feature = "part2"))]
'Q' => 12,
#[cfg(feature = "part2")]
'Q' => 11,
#[cfg(not(feature = "part2"))]
'J' => 11,
#[cfg(feature = "part2")]
'J' => 1,
'T' => 10,
_ => panic!("invalid card: {}", c),
}
}
}).collect()).bid(splits.next().unwrap().parse()?).build()?)
}
}
fn calculate(input: String) -> Result<usize> {
let start = Instant::now(); let start = Instant::now();
let answer = 0; let answer =
input
.lines()
.map(|line| line.parse::<Hand>().unwrap())
.sorted()
.enumerate()
.map(|(idx, hand)| hand.bid * (idx + 1))
.sum();
let algo_time = start.elapsed(); let algo_time = start.elapsed();
// ```
// for i in answer {
// println!("{:?}: {:?}", i, Strength::for_hand(&i.1));
// }
// ```
//
// output // output
println!("Day 5, part 2: {answer}"); println!("Day 5: {answer}");
println!("\tparse: {parsed_time:?}"); println!("\t{algo_time:?}");
println!("\talgo: {algo_time:?}");
Ok(answer) Ok(answer)
} }
@ -57,8 +175,7 @@ async fn main() -> Result<()> {
println!("Day {DAY}"); println!("Day {DAY}");
println!("====="); println!("=====");
let input = utils::aoc::get_puzzle_input(DAY).await?; let input = utils::aoc::get_puzzle_input(DAY).await?;
part1(input.clone())?; calculate(input.clone())?;
part2(input.clone())?;
Ok(()) Ok(())
} }
@ -68,17 +185,18 @@ static DAY: u8 = 7;
mod tests { mod tests {
use super::*; use super::*;
static DATA: &'static str = "TODO_REPLACE"; static DATA: &'static str = "32T3K 765
T55J5 684
KK677 28
KTJJT 220
QQQJA 483";
#[test] #[test]
fn test_part_1() -> Result<()> { fn test() -> Result<()> {
assert_eq!(part1(DATA.to_owned())?, 0); #[cfg(not(feature = "part2"))]
Ok(()) assert_eq!(calculate(DATA.to_owned())?, 6440);
} #[cfg(feature = "part2")]
assert_eq!(calculate(DATA.to_owned())?, 5905);
#[test]
fn test_part_2() -> Result<()> {
assert_eq!(part2(DATA.to_owned())?, 0);
Ok(()) Ok(())
} }
} }

1
src/bin/test.rs Normal file
View file

@ -0,0 +1 @@