Skip to content

Commit

Permalink
Merge pull request #219 from paulcacheux/day7-2023
Browse files Browse the repository at this point in the history
Day7 2023
  • Loading branch information
paulcacheux authored Dec 7, 2023
2 parents 401ede3 + 6b73ad4 commit 1407d45
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 0 deletions.
5 changes: 5 additions & 0 deletions inputs/2023/day7_test.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
32T3K 765
T55J5 684
KK677 28
KTJJT 220
QQQJA 483
5 changes: 5 additions & 0 deletions results/2023.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,10 @@
"day": 6,
"part1": "227850",
"part2": "42948149"
},
{
"day": 7,
"part1": "250254244",
"part2": "250087440"
}
]
173 changes: 173 additions & 0 deletions src/aoc2023/day7.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
use std::collections::HashMap;

use crate::aoc2023::Aoc2023;
use crate::traits::days::Day7;
use crate::traits::ParseInput;
use crate::traits::Solution;

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct Hand {
cards: [u8; 5],
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct ComputedHand {
sig: [u8; 5],
zvalues: [u8; 5],
}

#[inline]
fn shift_signature(sig: &mut [u8]) {
for i in 1..sig.len() {
if sig[i] > 0 {
sig[i - 1] += 1;
sig[i] -= 1;
return;
}
}
sig[sig.len() - 1] += 1;
}

impl Hand {
fn compute(&self, joker_mode: bool) -> ComputedHand {
ComputedHand {
sig: self.signature(joker_mode),
zvalues: self.zvalues(joker_mode),
}
}

fn signature(&self, joker_mode: bool) -> [u8; 5] {
let mut values = HashMap::with_capacity(5);
let mut joker = 0;
for &card in &self.cards {
if joker_mode && card == b'J' {
joker += 1;
} else {
*values.entry(card).or_insert(0) += 1;
}
}
let mut signature = [0; 5];
for value in values.values() {
signature[5 - value] += 1;
}

if joker_mode && joker != 0 {
for _ in 0..joker {
shift_signature(&mut signature);
}
}

signature
}

fn zvalues(&self, joker_mode: bool) -> [u8; 5] {
let mut zvalues = [0; 5];
for (v, z) in self.cards.iter().zip(zvalues.iter_mut()) {
*z = match *v {
b'A' => 14,
b'K' => 13,
b'Q' => 12,
b'J' => {
if joker_mode {
1
} else {
11
}
}
b'T' => 10,
b'9' => 9,
b'8' => 8,
b'7' => 7,
b'6' => 6,
b'5' => 5,
b'4' => 4,
b'3' => 3,
b'2' => 2,
_ => unreachable!(),
};
}
zvalues
}
}

impl Ord for ComputedHand {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
match self.sig.cmp(&other.sig) {
std::cmp::Ordering::Equal => self.zvalues.cmp(&other.zvalues),
other => other,
}
}
}

impl PartialOrd for ComputedHand {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}

#[derive(Debug, Clone)]
pub struct Entry<H> {
hand: H,
bet: u64,
}

impl Entry<Hand> {
fn compute(&self, joker_mode: bool) -> Entry<ComputedHand> {
Entry {
hand: self.hand.compute(joker_mode),
bet: self.bet,
}
}
}

impl ParseInput<Day7> for Aoc2023 {
type Parsed = Vec<Entry<Hand>>;

fn parse_input(input: &str) -> Self::Parsed {
input
.lines()
.map(|line| {
let mut iter = line.split_ascii_whitespace();
let hand = iter
.next()
.unwrap()
.bytes()
.take(5)
.collect::<Vec<_>>()
.try_into()
.unwrap();
let bet = iter.next().unwrap().parse().unwrap();
Entry {
hand: Hand { cards: hand },
bet,
}
})
.collect()
}
}

impl Solution<Day7> for Aoc2023 {
type Part1Output = u64;
type Part2Output = u64;

fn part1(input: &Vec<Entry<Hand>>) -> u64 {
solve(input, false)
}

fn part2(input: &Vec<Entry<Hand>>) -> u64 {
solve(input, true)
}
}

fn solve(input: &[Entry<Hand>], joker_mode: bool) -> u64 {
let mut input: Vec<_> = input
.iter()
.map(|entry| entry.compute(joker_mode))
.collect();
input.sort_by_key(|entry| entry.hand);
input
.into_iter()
.enumerate()
.map(|(i, entry)| (i as u64 + 1) * entry.bet)
.sum()
}
2 changes: 2 additions & 0 deletions src/aoc2023/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub mod day3;
pub mod day4;
pub mod day5;
pub mod day6;
pub mod day7;

pub fn run_solution_for_day(day: u32, input: &str, results: Option<Results>) -> Option<TimingData> {
let r = results
Expand All @@ -22,6 +23,7 @@ pub fn run_solution_for_day(day: u32, input: &str, results: Option<Results>) ->
4 => run::<Aoc2023, Day4>(input, r),
5 => run::<Aoc2023, Day5>(input, r),
6 => run::<Aoc2023, Day6>(input, r),
7 => run::<Aoc2023, Day7>(input, r),
_ => return None,
};
Some(elapsed)
Expand Down

0 comments on commit 1407d45

Please sign in to comment.