generated from janezicmatej/aoc-template
solution: day 7 clean
This commit is contained in:
parent
0000015082
commit
00000160a1
|
@ -0,0 +1,5 @@
|
||||||
|
32T3K 765
|
||||||
|
T55J5 684
|
||||||
|
KK677 28
|
||||||
|
KTJJT 220
|
||||||
|
QQQJA 483
|
|
@ -0,0 +1,191 @@
|
||||||
|
use std::{cmp::Ordering, collections::HashMap, str::FromStr};
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
|
||||||
|
enum Label {
|
||||||
|
Ace = 14,
|
||||||
|
King = 13,
|
||||||
|
Queen = 12,
|
||||||
|
Jack = 11,
|
||||||
|
Ten = 10,
|
||||||
|
Nine = 9,
|
||||||
|
Eight = 8,
|
||||||
|
Seven = 7,
|
||||||
|
Six = 6,
|
||||||
|
Five = 5,
|
||||||
|
Four = 4,
|
||||||
|
Three = 3,
|
||||||
|
Two = 2,
|
||||||
|
Joker = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<char> for Label {
|
||||||
|
fn from(value: char) -> Self {
|
||||||
|
use Label::*;
|
||||||
|
match value {
|
||||||
|
'A' => Ace,
|
||||||
|
'K' => King,
|
||||||
|
'Q' => Queen,
|
||||||
|
'J' => Jack,
|
||||||
|
'T' => Ten,
|
||||||
|
'9' => Nine,
|
||||||
|
'8' => Eight,
|
||||||
|
'7' => Seven,
|
||||||
|
'6' => Six,
|
||||||
|
'5' => Five,
|
||||||
|
'4' => Four,
|
||||||
|
'3' => Three,
|
||||||
|
'2' => Two,
|
||||||
|
'X' => Joker,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct ParseHandError;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
|
struct Hand {
|
||||||
|
labels: [Label; 5],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for Hand {
|
||||||
|
type Err = ParseHandError;
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
let labels = s
|
||||||
|
.chars()
|
||||||
|
.map(Label::from)
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.try_into()
|
||||||
|
.map_err(|_| ParseHandError)?;
|
||||||
|
Ok(Hand { labels })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for Hand {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
Some(self.cmp(other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for Hand {
|
||||||
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
|
let sf = HandType::from(*self);
|
||||||
|
let so = HandType::from(*other);
|
||||||
|
|
||||||
|
sf.cmp(&so).then({
|
||||||
|
let mut c = Ordering::Equal;
|
||||||
|
for i in 0..5 {
|
||||||
|
c = self.labels[i].cmp(&other.labels[i]);
|
||||||
|
if c != Ordering::Equal {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
enum HandType {
|
||||||
|
Five = 6,
|
||||||
|
Four = 5,
|
||||||
|
FullHouse = 4,
|
||||||
|
Three = 3,
|
||||||
|
TwoPair = 2,
|
||||||
|
Pair = 1,
|
||||||
|
HighCard = 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Hand> for HandType {
|
||||||
|
fn from(value: Hand) -> Self {
|
||||||
|
let mut map = HashMap::new();
|
||||||
|
|
||||||
|
for c in value.labels {
|
||||||
|
*map.entry(c).or_insert(0) += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let joker = map.remove(&Label::Joker).unwrap_or(0);
|
||||||
|
|
||||||
|
let is_n_k = |n| joker == n || map.values().filter(|&x| *x == n - joker).count() > 0;
|
||||||
|
|
||||||
|
if is_n_k(5) {
|
||||||
|
return Self::Five;
|
||||||
|
}
|
||||||
|
if is_n_k(4) {
|
||||||
|
return Self::Four;
|
||||||
|
}
|
||||||
|
// full house
|
||||||
|
if map.values().count() <= 2 {
|
||||||
|
return Self::FullHouse;
|
||||||
|
}
|
||||||
|
if is_n_k(3) {
|
||||||
|
return Self::Three;
|
||||||
|
}
|
||||||
|
// two pair
|
||||||
|
if map.values().count() <= 3 {
|
||||||
|
return Self::TwoPair;
|
||||||
|
}
|
||||||
|
if is_n_k(2) {
|
||||||
|
return Self::Pair;
|
||||||
|
}
|
||||||
|
|
||||||
|
Self::HighCard
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part_one(input: &str) -> Option<u32> {
|
||||||
|
let mut v = input
|
||||||
|
.lines()
|
||||||
|
.filter_map(|l| l.split_once(' '))
|
||||||
|
.map(|(f, s)| (f.parse::<Hand>().unwrap(), s.parse::<u32>().unwrap()))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
v.sort_by(|f, o| f.0.cmp(&o.0));
|
||||||
|
|
||||||
|
Some(
|
||||||
|
v.into_iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, x)| (i as u32 + 1) * x.1)
|
||||||
|
.sum::<u32>(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part_two(input: &str) -> Option<u32> {
|
||||||
|
let mut v = input
|
||||||
|
.replace('J', "X")
|
||||||
|
.lines()
|
||||||
|
.filter_map(|l| l.split_once(' '))
|
||||||
|
.map(|(f, s)| (f.parse::<Hand>().unwrap(), s.parse::<u32>().unwrap()))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
v.sort_by(|f, o| f.0.cmp(&o.0));
|
||||||
|
|
||||||
|
Some(
|
||||||
|
v.into_iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, x)| (i as u32 + 1) * x.1)
|
||||||
|
.sum::<u32>(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
aoc::solution!(7);
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
#[test]
|
||||||
|
fn test_part_one() {
|
||||||
|
assert_eq!(
|
||||||
|
part_one(&aoc::template::read_file("examples", 7)),
|
||||||
|
Some(6440)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_part_two() {
|
||||||
|
assert_eq!(
|
||||||
|
part_two(&aoc::template::read_file("examples", 7)),
|
||||||
|
Some(5905)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue