Skip to content

Commit

Permalink
Day 07b
Browse files Browse the repository at this point in the history
  • Loading branch information
lpenz committed Dec 9, 2023
1 parent c037d9b commit 4539165
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 19 deletions.
2 changes: 1 addition & 1 deletion day07/src/bin/day07a.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fn process(bufin: impl BufRead) -> Result<i64> {
let input = parser::parse(bufin)?;
Ok(input
.into_iter()
.map(|(hand, bid)| (hand.value(), bid))
.map(|(hand, bid)| (hand.value(false), bid))
.sorted()
.enumerate()
.map(|(i, (_hand, bid))| (i as i64 + 1) * bid)
Expand Down
31 changes: 31 additions & 0 deletions day07/src/bin/day07b.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright (C) 2023 Leandro Lisboa Penz <lpenz@lpenz.org>
// This file is subject to the terms and conditions defined in
// file 'LICENSE', which is part of this source code package.

use itertools::Itertools;
use std::io::{stdin, BufRead};

use day07::*;

fn process(bufin: impl BufRead) -> Result<i64> {
let input = parser::parse(bufin)?;
Ok(input
.into_iter()
.map(|(hand, bid)| (hand.value(true), bid))
.sorted()
.enumerate()
.map(|(i, (_hand, bid))| (i as i64 + 1) * bid)
.sum())
}

#[test]
fn test() -> Result<()> {
assert_eq!(process(EXAMPLE.as_bytes())?, 5905);
Ok(())
}

fn main() -> Result<()> {
color_eyre::install()?;
println!("{}", process(stdin().lock())?);
Ok(())
}
106 changes: 88 additions & 18 deletions day07/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
pub use color_eyre::{eyre::eyre, Report, Result};
use itertools::Itertools;
use std::collections::BTreeMap;
use std::fmt;
use std::str::FromStr;

pub const EXAMPLE: &str = "32T3K 765
Expand All @@ -14,23 +15,35 @@ KTJJT 220
QQQJA 483
";

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Card(pub char);

impl From<&Card> for i64 {
fn from(value: &Card) -> i64 {
match value {
Card('A') => 12,
Card('K') => 11,
Card('Q') => 10,
Card('J') => 9,
Card('T') => 8,
Card(n) => n.to_digit(10).expect("invalid card") as i64 - 2,
impl Card {
pub fn value(&self, joker: bool) -> i64 {
match self {
Card('A') => 13,
Card('K') => 12,
Card('Q') => 11,
Card('J') => {
if joker {
0
} else {
10
}
}
Card('T') => 9,
Card(n) => n.to_digit(10).expect("invalid card") as i64 - 1,
}
}
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
impl fmt::Display for Card {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
pub enum Type {
Highest = 0,
OnePair,
Expand All @@ -41,6 +54,7 @@ pub enum Type {
FiveOfKind,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct Hand(pub [Card; 5]);

impl Hand {
Expand Down Expand Up @@ -76,18 +90,48 @@ impl Hand {
}
}

pub fn value(&self) -> i64 {
self.htype() as i64 * 13_i64.pow(6) + i64::from(self)
pub fn iter_jokers(&self) -> impl Iterator<Item = Hand> + '_ {
std::iter::once(*self)
.chain(
self.0
.iter()
.filter(|&c| c != &Card('J'))
.unique()
.map(|c| {
let mut hand = *self;
for pos in hand.0.iter_mut() {
if *pos == Card('J') {
*pos = *c;
}
}
hand
}),
)
.unique()
}

pub fn best_type(&self) -> Type {
self.iter_jokers()
.map(|hand| hand.htype())
.max_by_key(|&t| t as i64)
.unwrap()
}

pub fn value(&self, joker: bool) -> i64 {
let cards_value = self.cards_value(joker);
if joker {
self.best_type() as i64 * 14_i64.pow(6) + cards_value
} else {
self.htype() as i64 * 14_i64.pow(6) + cards_value
}
}
}

impl From<&Hand> for i64 {
fn from(hand: &Hand) -> i64 {
hand.0
pub fn cards_value(&self, joker: bool) -> i64 {
self.0
.iter()
.rev()
.enumerate()
.map(|(i, c)| i64::from(c) * 13_i64.pow(i as u32))
.map(|(i, c)| c.value(joker) * 14_i64.pow(i as u32))
.sum()
}
}
Expand All @@ -110,6 +154,32 @@ impl FromStr for Hand {
}
}

impl fmt::Display for Hand {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for c in self.0 {
write!(f, "{}", c)?;
}
Ok(())
}
}

#[test]
fn test_iter_jokers() -> Result<()> {
assert_eq!(
Hand::from_str("AAAAA")?.iter_jokers().collect::<Vec<_>>(),
vec![Hand::from_str("AAAAA")?]
);
assert_eq!(
Hand::from_str("JAAAA")?.iter_jokers().collect::<Vec<_>>(),
vec![Hand::from_str("JAAAA")?, Hand::from_str("AAAAA")?,]
);
assert_eq!(
Hand::from_str("JJAAA")?.iter_jokers().collect::<Vec<_>>(),
vec![Hand::from_str("JJAAA")?, Hand::from_str("AAAAA")?,]
);
Ok(())
}

#[test]
fn test_hand_type() -> Result<()> {
assert_eq!(Hand::from_str("AAAAA")?.htype(), Type::FiveOfKind);
Expand Down

0 comments on commit 4539165

Please sign in to comment.