Skip to content

Instantly share code, notes, and snippets.

@typester
Created December 9, 2023 17:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save typester/d180163848518817b9402ea9b91dac72 to your computer and use it in GitHub Desktop.
Save typester/d180163848518817b9402ea9b91dac72 to your computer and use it in GitHub Desktop.
2023 Advent of Code Day 7
use std::{collections::{HashMap, BinaryHeap}, cmp::Reverse};
const INPUT: &str = "..snip..";
fn main() {
let mut heap: BinaryHeap<Reverse<Cards>> = INPUT.lines()
.map(parse)
.fold(BinaryHeap::new(), |mut acc, cards| {
acc.push(Reverse(cards));
acc
});
let mut sum: u64 = 0;
for i in 1..=heap.len() {
let Reverse(c) = heap.pop().unwrap();
//println!("card {}: {:?}, {:?}, {}", i, c.cards, c.kind, c.power);
sum += i as u64 * c.rank;
}
println!("part1: {}", sum);
let mut heap: BinaryHeap<Reverse<Cards>> = INPUT.lines()
.map(parse2)
.fold(BinaryHeap::new(), |mut acc, cards| {
acc.push(Reverse(cards));
acc
});
let mut sum: u64 = 0;
for i in 1..=heap.len() {
let Reverse(c) = heap.pop().unwrap();
//println!("card {}: {:?}, {:?}, {}", i, c.cards, c.kind, c.power);
sum += i as u64 * c.rank;
}
println!("part2: {}", sum);
}
fn parse(line: &str) -> Cards {
let mut iter = line.split(" ");
let cards: Vec<char> = iter.next().unwrap().chars().collect();
let rank: u64 = iter.next().unwrap().parse::<u64>().unwrap();
let mut map: HashMap<char, usize> = HashMap::new();
for &c in cards.iter() {
map.entry(c).and_modify(|e| *e += 1).or_insert(1);
}
let kind = match map.len() {
1 => Kind::Five,
2 => {
if map.values().find(|v| **v == 4).is_some() {
Kind::Four
} else {
Kind::FullHouse
}
},
3 => {
if map.values().find(|v| **v == 3).is_some() {
Kind::Three
} else {
Kind::Two
}
},
4 => Kind::One,
5 => Kind::High,
_ => panic!("unexpected data"),
};
let power = map_power(&cards);
Cards {
cards,
rank,
kind,
power,
}
}
fn parse2(line: &str) -> Cards {
let mut iter = line.split(" ");
let cards: Vec<char> = iter.next().unwrap().chars().collect();
let rank: u64 = iter.next().unwrap().parse::<u64>().unwrap();
let mut j_count = 0;
let mut map: HashMap<char, usize> = HashMap::new();
for &c in cards.iter() {
if c == 'J' {
j_count += 1;
} else {
map.entry(c).and_modify(|e| *e += 1).or_insert(1);
}
}
if j_count < 5 {
let max_char = map.iter()
.fold((None, 0), |mut acc, (&c, &v)| {
if v > acc.1 {
acc.0 = Some(c);
acc.1 = v;
}
acc
})
.0.unwrap();
map.entry(max_char).and_modify(|v| *v += j_count);
}
let kind = if j_count == 5 {
Kind::Five
} else {
match map.len() {
1 => Kind::Five,
2 => {
if map.values().find(|v| **v == 4).is_some() {
Kind::Four
} else {
Kind::FullHouse
}
},
3 => {
if map.values().find(|v| **v == 3).is_some() {
Kind::Three
} else {
Kind::Two
}
},
4 => Kind::One,
5 => Kind::High,
_ => panic!("unexpected data"),
}
};
let power = map_power2(&cards);
Cards {
cards,
rank,
kind,
power,
}
}
#[derive(Debug, Eq, PartialEq)]
enum Kind {
Five,
Four,
FullHouse,
Three,
Two,
One,
High,
}
impl Kind {
fn to_power(&self) -> u64 {
match self {
Self::Five => 6,
Self::Four => 5,
Self::FullHouse => 4,
Self::Three => 3,
Self::Two => 2,
Self::One => 1,
Self::High => 0,
}
}
}
impl PartialOrd for Kind {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Kind {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.to_power().cmp(&other.to_power())
}
}
#[derive(Debug, Eq)]
struct Cards {
cards: Vec<char>,
kind: Kind,
power: u64,
rank: u64,
}
impl PartialEq for Cards {
fn eq(&self, other: &Self) -> bool {
self.kind == other.kind
&& self.power == other.power
}
}
impl Ord for Cards {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
match self.kind.cmp(&other.kind) {
std::cmp::Ordering::Equal => {
self.power.cmp(&other.power)
},
std::cmp::Ordering::Less => std::cmp::Ordering::Less,
std::cmp::Ordering::Greater => std::cmp::Ordering::Greater,
}
}
}
impl PartialOrd for Cards {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
fn map_power(chars: &Vec<char>) -> u64 {
let mut power: u64 = 0;
for (i, &c) in chars.iter().rev().enumerate() {
let p = match c {
'2' => 0x1,
'3' => 0x2,
'4' => 0x3,
'5' => 0x4,
'6' => 0x5,
'7' => 0x6,
'8' => 0x7,
'9' => 0x8,
'T' => 0x9,
'J' => 0xA,
'Q' => 0xB,
'K' => 0xC,
'A' => 0xD,
_ => panic!("unexpected input: {}", c),
};
power += p << i * 4;
}
power
}
fn map_power2(chars: &Vec<char>) -> u64 {
let mut power: u64 = 0;
for (i, &c) in chars.iter().rev().enumerate() {
let p = match c {
'J' => 0x0,
'2' => 0x1,
'3' => 0x2,
'4' => 0x3,
'5' => 0x4,
'6' => 0x5,
'7' => 0x6,
'8' => 0x7,
'9' => 0x8,
'T' => 0x9,
'Q' => 0xB,
'K' => 0xC,
'A' => 0xD,
_ => panic!("unexpected input: {}", c),
};
power += p << i * 4;
}
power
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment