stuff
This commit is contained in:
parent
3be4845987
commit
5e42561567
4 changed files with 1167 additions and 44 deletions
|
@ -27,3 +27,7 @@ tokio = { version = "1", features = ["full"] }
|
|||
itertools = "0.12"
|
||||
derive_builder = "0.12.0"
|
||||
rayon = "1.8.0"
|
||||
|
||||
[features]
|
||||
part2 = []
|
||||
default = ["part2"]
|
||||
|
|
1000
aoc_puzzle_cache/day_7
Normal file
1000
aoc_puzzle_cache/day_7
Normal file
File diff suppressed because it is too large
Load diff
206
src/bin/day7.rs
206
src/bin/day7.rs
|
@ -2,52 +2,170 @@ use aoc23::prelude::*;
|
|||
use derive_builder::Builder;
|
||||
use itertools::Itertools;
|
||||
use rayon::prelude::*;
|
||||
use std::{str::FromStr, time::Instant};
|
||||
use std::{
|
||||
cmp::Ordering,
|
||||
str::FromStr,
|
||||
time::Instant,
|
||||
};
|
||||
|
||||
#[derive(Debug, Builder, Clone)]
|
||||
struct Todo {}
|
||||
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)]
|
||||
enum Strength {
|
||||
HighCard,
|
||||
OnePair,
|
||||
TwoPair,
|
||||
ThreeOfAKind,
|
||||
FullHouse,
|
||||
FourOfAKind,
|
||||
FiveOfAKind,
|
||||
}
|
||||
|
||||
impl FromStr for Todo {
|
||||
type Err = BoxE;
|
||||
impl Strength {
|
||||
#[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> {
|
||||
Ok(TodoBuilder::default().build()?)
|
||||
// let mut counts = [0; 14]; let mut jokers = 0;
|
||||
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> {
|
||||
// parse
|
||||
let start = Instant::now();
|
||||
let todo: Todo = input.parse()?;
|
||||
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)
|
||||
#[derive(Debug, Builder, Clone, PartialEq, Eq)]
|
||||
struct Hand {
|
||||
cards: Vec<u32>,
|
||||
bid: usize,
|
||||
}
|
||||
|
||||
fn part2(input: String) -> Result<usize> {
|
||||
// parse
|
||||
let start = Instant::now();
|
||||
let todo: Todo = input.parse()?;
|
||||
let parsed_time = start.elapsed();
|
||||
impl Ord for Hand {
|
||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||
let self_strength = Strength::for_hand(self);
|
||||
let other_strength = Strength::for_hand(other);
|
||||
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 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();
|
||||
|
||||
// ```
|
||||
// for i in answer {
|
||||
// println!("{:?}: {:?}", i, Strength::for_hand(&i.1));
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// output
|
||||
println!("Day 5, part 2: {answer}");
|
||||
println!("\tparse: {parsed_time:?}");
|
||||
println!("\talgo: {algo_time:?}");
|
||||
println!("Day 5: {answer}");
|
||||
println!("\t{algo_time:?}");
|
||||
Ok(answer)
|
||||
}
|
||||
|
||||
|
@ -57,8 +175,7 @@ async fn main() -> Result<()> {
|
|||
println!("Day {DAY}");
|
||||
println!("=====");
|
||||
let input = utils::aoc::get_puzzle_input(DAY).await?;
|
||||
part1(input.clone())?;
|
||||
part2(input.clone())?;
|
||||
calculate(input.clone())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -68,17 +185,18 @@ static DAY: u8 = 7;
|
|||
mod tests {
|
||||
use super::*;
|
||||
|
||||
static DATA: &'static str = "TODO_REPLACE";
|
||||
static DATA: &'static str = "32T3K 765
|
||||
T55J5 684
|
||||
KK677 28
|
||||
KTJJT 220
|
||||
QQQJA 483";
|
||||
|
||||
#[test]
|
||||
fn test_part_1() -> Result<()> {
|
||||
assert_eq!(part1(DATA.to_owned())?, 0);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part_2() -> Result<()> {
|
||||
assert_eq!(part2(DATA.to_owned())?, 0);
|
||||
fn test() -> Result<()> {
|
||||
#[cfg(not(feature = "part2"))]
|
||||
assert_eq!(calculate(DATA.to_owned())?, 6440);
|
||||
#[cfg(feature = "part2")]
|
||||
assert_eq!(calculate(DATA.to_owned())?, 5905);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
1
src/bin/test.rs
Normal file
1
src/bin/test.rs
Normal file
|
@ -0,0 +1 @@
|
|||
|
Loading…
Add table
Add a link
Reference in a new issue