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"
|
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
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 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
1
src/bin/test.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue