day 8 part 2
This commit is contained in:
parent
adda315684
commit
5167305a7a
5 changed files with 911 additions and 1104 deletions
14
example.txt
14
example.txt
|
@ -1,5 +1,9 @@
|
|||
32T3K 765
|
||||
T55J5 684
|
||||
KK677 28
|
||||
KTJJT 220
|
||||
QQQJA 483
|
||||
RL
|
||||
|
||||
AAA = (BBB, CCC)
|
||||
BBB = (DDD, EEE)
|
||||
CCC = (ZZZ, GGG)
|
||||
DDD = (DDD, DDD)
|
||||
EEE = (EEE, EEE)
|
||||
GGG = (GGG, GGG)
|
||||
ZZZ = (ZZZ, ZZZ)
|
||||
|
|
5
example2.txt
Normal file
5
example2.txt
Normal file
|
@ -0,0 +1,5 @@
|
|||
LLR
|
||||
|
||||
AAA = (BBB, BBB)
|
||||
BBB = (AAA, ZZZ)
|
||||
ZZZ = (ZZZ, ZZZ)
|
10
example3.txt
Normal file
10
example3.txt
Normal file
|
@ -0,0 +1,10 @@
|
|||
LR
|
||||
|
||||
11A = (11B, XXX)
|
||||
11B = (XXX, 11Z)
|
||||
11Z = (11B, XXX)
|
||||
22A = (22B, XXX)
|
||||
22B = (22C, 22C)
|
||||
22C = (22Z, 22Z)
|
||||
22Z = (22B, 22B)
|
||||
XXX = (XXX, XXX)
|
192
src/main.rs
192
src/main.rs
|
@ -1,119 +1,115 @@
|
|||
use std::{collections::HashMap, io::stdin};
|
||||
use std::{
|
||||
cmp::{max, min},
|
||||
collections::HashMap,
|
||||
io::stdin,
|
||||
};
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
use counter::Counter;
|
||||
use anyhow::Result;
|
||||
use regex::Regex;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||
enum HandType {
|
||||
FiveOfAKind,
|
||||
FourOfAKind,
|
||||
FullHouse,
|
||||
ThreeOfAKind,
|
||||
TwoPair,
|
||||
OnePair,
|
||||
HighCard,
|
||||
// RL
|
||||
//
|
||||
// AAA = (BBB, CCC)
|
||||
// BBB = (DDD, EEE)
|
||||
// CCC = (ZZZ, GGG)
|
||||
// DDD = (DDD, DDD)
|
||||
// EEE = (EEE, EEE)
|
||||
// GGG = (GGG, GGG)
|
||||
// ZZZ = (ZZZ, ZZZ)
|
||||
|
||||
fn gcd(a: i64, b: i64) -> i64 {
|
||||
let mut l = max(a, b);
|
||||
let mut s = min(a, b);
|
||||
loop {
|
||||
let r = l % s;
|
||||
l = s;
|
||||
s = r;
|
||||
if r == 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
l
|
||||
}
|
||||
|
||||
fn hand_type(hand: &str) -> HandType {
|
||||
let counter_without_joker: Counter<char> = hand.chars().filter(|c| *c != 'J').collect();
|
||||
if counter_without_joker.is_empty() {
|
||||
// it's JJJJJ
|
||||
return HandType::FiveOfAKind;
|
||||
}
|
||||
let hand = hand.replace(
|
||||
'J',
|
||||
&counter_without_joker
|
||||
.k_most_common_ordered(1)
|
||||
.first()
|
||||
.unwrap()
|
||||
.0
|
||||
.to_string(),
|
||||
);
|
||||
let counter: Counter<char> = hand.chars().collect();
|
||||
if counter.keys().len() == 1 {
|
||||
return HandType::FiveOfAKind;
|
||||
}
|
||||
if counter.keys().len() == 2 {
|
||||
if counter.k_most_common_ordered(1)[0].1 == 4 {
|
||||
return HandType::FourOfAKind;
|
||||
}
|
||||
if counter.k_most_common_ordered(1)[0].1 == 3 {
|
||||
return HandType::FullHouse;
|
||||
}
|
||||
}
|
||||
if counter.keys().len() == 3 {
|
||||
if counter.k_most_common_ordered(1)[0].1 == 3 {
|
||||
return HandType::ThreeOfAKind;
|
||||
}
|
||||
if counter.k_most_common_ordered(1)[0].1 == 2 {
|
||||
return HandType::TwoPair;
|
||||
}
|
||||
}
|
||||
if counter.keys().len() == 4 {
|
||||
return HandType::OnePair;
|
||||
}
|
||||
HandType::HighCard
|
||||
}
|
||||
|
||||
type CmpKey = (u8, u8, u8, u8, u8, u8);
|
||||
|
||||
fn hand_cmp_key(hand: &str) -> CmpKey {
|
||||
let hand_strength = HashMap::from([
|
||||
(HandType::FiveOfAKind, 7u8),
|
||||
(HandType::FourOfAKind, 6u8),
|
||||
(HandType::FullHouse, 5u8),
|
||||
(HandType::ThreeOfAKind, 4u8),
|
||||
(HandType::TwoPair, 3u8),
|
||||
(HandType::OnePair, 2u8),
|
||||
(HandType::HighCard, 1u8),
|
||||
]);
|
||||
let card_strength: HashMap<char, u8> = "AKQT98765432J"
|
||||
.chars()
|
||||
.enumerate()
|
||||
.map(|(i, c)| (c, (14 - i) as u8))
|
||||
.collect();
|
||||
|
||||
let mut r = vec![*hand_strength.get(&hand_type(hand)).unwrap()];
|
||||
r.extend(hand.chars().map(|c| card_strength.get(&c).unwrap()));
|
||||
|
||||
(r[0], r[1], r[2], r[3], r[4], r[5])
|
||||
fn lcm(a: i64, b: i64) -> i64 {
|
||||
a * b / gcd(a, b)
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let mut bids = vec![];
|
||||
let nodes_re = Regex::new(r"([0-9A-Z]{3}) = \(([0-9A-Z]{3}), ([0-9A-Z]{3})\)")?;
|
||||
let mut nodes_map = HashMap::new();
|
||||
let mut first = true;
|
||||
let mut instructions = "".to_string();
|
||||
for line in stdin().lines().map_while(Result::ok) {
|
||||
let parts: Vec<&str> = line.split_whitespace().collect();
|
||||
let hand = parts[0];
|
||||
let bid: i64 = parts[1].parse().unwrap();
|
||||
println!("{} {:?} {}", hand, hand_type(hand), bid);
|
||||
if first {
|
||||
instructions = line.clone();
|
||||
first = false;
|
||||
}
|
||||
for m in nodes_re.captures_iter(&line) {
|
||||
nodes_map.insert(
|
||||
m.get(1).unwrap().as_str().to_string(),
|
||||
(
|
||||
m.get(2).unwrap().as_str().to_string(),
|
||||
m.get(3).unwrap().as_str().to_string(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
bids.push((hand.to_owned(), bid));
|
||||
let mut cursors: Vec<String> = nodes_map
|
||||
.keys()
|
||||
.filter(|n| n.ends_with('A'))
|
||||
.cloned()
|
||||
.collect();
|
||||
println!("starting cursors: {:?}", cursors);
|
||||
|
||||
// by inspecting the input, we know that the distance from A - Z is
|
||||
// equal to the size of the Z - Z loops for all ghosts
|
||||
// so we just need to save those and do LCM for all
|
||||
//
|
||||
// honestly, I'm a bit disappointed because of this
|
||||
let mut loop_lengths = vec![];
|
||||
for cursor in cursors.iter_mut() {
|
||||
let mut steps = 0;
|
||||
// let mut zeds = HashSet::new();
|
||||
println!("cursor {cursor:?}:");
|
||||
'outer: loop {
|
||||
for instruction in instructions.chars() {
|
||||
match instruction {
|
||||
'L' => *cursor = nodes_map.get(cursor).unwrap().0.clone(),
|
||||
'R' => *cursor = nodes_map.get(cursor).unwrap().1.clone(),
|
||||
_ => {}
|
||||
}
|
||||
bids.sort_by_key(|(hand, _)| hand_cmp_key(hand));
|
||||
let mut winnings = 0;
|
||||
for (i, b) in bids.iter().enumerate() {
|
||||
let (_, bid) = b;
|
||||
winnings += (i as i64 + 1) * bid;
|
||||
// println!("after going {} cursors are {:?}", instructions, cursors);
|
||||
steps += 1;
|
||||
// if cursors.iter().all(|c| c.ends_with('Z')) {
|
||||
if cursor.ends_with('Z') {
|
||||
loop_lengths.push(steps);
|
||||
break 'outer;
|
||||
// if zeds.contains(cursor) {
|
||||
// println!(" looped on {cursor} at {steps} steps");
|
||||
// break 'outer;
|
||||
// }
|
||||
//
|
||||
// println!(" found {cursor} at {steps} steps");
|
||||
// zeds.insert(cursor.clone());
|
||||
}
|
||||
println!("{}", winnings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let result = loop_lengths.into_iter().fold(1i64, lcm);
|
||||
println!("{result}");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn test_hand_types() {}
|
||||
|
||||
#[test]
|
||||
fn test_hand_types() {
|
||||
assert_eq!(hand_type("AAAAJ"), HandType::FiveOfAKind);
|
||||
assert_eq!(hand_type("AAAJJ"), HandType::FiveOfAKind);
|
||||
assert_eq!(hand_type("AAJJJ"), HandType::FiveOfAKind);
|
||||
assert_eq!(hand_type("T55J5"), HandType::FourOfAKind);
|
||||
assert_eq!(hand_type("KTJJT"), HandType::FourOfAKind);
|
||||
assert_eq!(hand_type("QQQJA"), HandType::FourOfAKind);
|
||||
assert_eq!(hand_type("2J432"), HandType::ThreeOfAKind);
|
||||
assert_eq!(hand_type("A23J4"), HandType::OnePair);
|
||||
assert_eq!(hand_type("23456"), HandType::HighCard);
|
||||
fn name() {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue