Compare commits
No commits in common. "adda315684189660f940d2209bfbf8f7f2e6e91b" and "b2bd814c8aef63adf2a57756a0cc46f60032db8c" have entirely different histories.
adda315684
...
b2bd814c8a
5 changed files with 58 additions and 1128 deletions
25
Cargo.lock
generated
25
Cargo.lock
generated
|
@ -22,17 +22,10 @@ name = "aoc2023"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"counter",
|
|
||||||
"fancy-regex",
|
"fancy-regex",
|
||||||
"regex",
|
"regex",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "autocfg"
|
|
||||||
version = "1.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bit-set"
|
name = "bit-set"
|
||||||
version = "0.5.3"
|
version = "0.5.3"
|
||||||
|
@ -48,15 +41,6 @@ version = "0.6.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
|
checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "counter"
|
|
||||||
version = "0.5.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2d458e66999348f56fd3ffcfbb7f7951542075ca8359687c703de6500c1ddccd"
|
|
||||||
dependencies = [
|
|
||||||
"num-traits",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fancy-regex"
|
name = "fancy-regex"
|
||||||
version = "0.12.0"
|
version = "0.12.0"
|
||||||
|
@ -73,15 +57,6 @@ version = "2.6.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
|
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num-traits"
|
|
||||||
version = "0.2.17"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.10.2"
|
version = "1.10.2"
|
||||||
|
|
|
@ -7,6 +7,5 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.75"
|
anyhow = "1.0.75"
|
||||||
counter = "0.5.7"
|
|
||||||
fancy-regex = "0.12.0"
|
fancy-regex = "0.12.0"
|
||||||
regex = "1.10.2"
|
regex = "1.10.2"
|
||||||
|
|
|
@ -1,5 +1,2 @@
|
||||||
32T3K 765
|
Time: 7 15 30
|
||||||
T55J5 684
|
Distance: 9 40 200
|
||||||
KK677 28
|
|
||||||
KTJJT 220
|
|
||||||
QQQJA 483
|
|
||||||
|
|
153
src/main.rs
153
src/main.rs
|
@ -1,119 +1,76 @@
|
||||||
use std::{collections::HashMap, io::stdin};
|
use std::io::stdin;
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use counter::Counter;
|
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
/// solve ax² + bx + c = 0
|
||||||
enum HandType {
|
fn solve_quadratic(a: f64, b: f64, c: f64) -> (f64, f64) {
|
||||||
FiveOfAKind,
|
let r1 = (-b + f64::sqrt(b * b - 4.0 * a * c)) / 2.0 * a;
|
||||||
FourOfAKind,
|
let r2 = (-b - f64::sqrt(b * b - 4.0 * a * c)) / 2.0 * a;
|
||||||
FullHouse,
|
(r1, r2)
|
||||||
ThreeOfAKind,
|
|
||||||
TwoPair,
|
|
||||||
OnePair,
|
|
||||||
HighCard,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hand_type(hand: &str) -> HandType {
|
fn parse_input() -> Result<(Vec<i64>, Vec<i64>)> {
|
||||||
let counter_without_joker: Counter<char> = hand.chars().filter(|c| *c != 'J').collect();
|
let numbers = Regex::new(r"(\d+)")?;
|
||||||
if counter_without_joker.is_empty() {
|
let mut times = vec![];
|
||||||
// it's JJJJJ
|
let mut distances = vec![];
|
||||||
return HandType::FiveOfAKind;
|
for line in stdin().lines().map_while(Result::ok) {
|
||||||
}
|
if line.starts_with("Time:") {
|
||||||
let hand = hand.replace(
|
times = numbers
|
||||||
'J',
|
.captures_iter(&line.replace(' ', ""))
|
||||||
&counter_without_joker
|
.map(|c| c.get(1).unwrap().as_str().parse())
|
||||||
.k_most_common_ordered(1)
|
.map_while(Result::ok)
|
||||||
.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();
|
.collect();
|
||||||
|
} else if line.starts_with("Distance:") {
|
||||||
let mut r = vec![*hand_strength.get(&hand_type(hand)).unwrap()];
|
distances = numbers
|
||||||
r.extend(hand.chars().map(|c| card_strength.get(&c).unwrap()));
|
.captures_iter(&line.replace(' ', ""))
|
||||||
|
.map(|c| c.get(1).unwrap().as_str().parse())
|
||||||
(r[0], r[1], r[2], r[3], r[4], r[5])
|
.map_while(Result::ok)
|
||||||
|
.collect();
|
||||||
|
} else {
|
||||||
|
bail!("unexpected line: {}", line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok((times, distances))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
let mut bids = vec![];
|
let (times, distances) = parse_input()?;
|
||||||
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);
|
|
||||||
|
|
||||||
bids.push((hand.to_owned(), bid));
|
if times.len() != distances.len() {
|
||||||
|
bail!(
|
||||||
|
"times has {} elements, but distances has {} elements",
|
||||||
|
times.len(),
|
||||||
|
distances.len()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
bids.sort_by_key(|(hand, _)| hand_cmp_key(hand));
|
|
||||||
let mut winnings = 0;
|
let mut prod = 1;
|
||||||
for (i, b) in bids.iter().enumerate() {
|
for i in 0..times.len() {
|
||||||
let (_, bid) = b;
|
let t = times[i];
|
||||||
winnings += (i as i64 + 1) * bid;
|
let d = distances[i];
|
||||||
|
|
||||||
|
// the equation to solve is x * (t - x) - d = 0
|
||||||
|
// = t*x - x*x - d = 0
|
||||||
|
// = -1x² + tx - d = 0
|
||||||
|
let (r1, r2) = solve_quadratic(-1.0, t as f64, -d as f64);
|
||||||
|
let r1 = (r1 + 1.0).floor() as i64;
|
||||||
|
let r2 = (r2 - 1.0).ceil() as i64;
|
||||||
|
|
||||||
|
let ways = (r2 - r1) + 1;
|
||||||
|
|
||||||
|
println!("{t} {d}");
|
||||||
|
println!("ways: {ways}");
|
||||||
|
prod *= ways;
|
||||||
}
|
}
|
||||||
println!("{}", winnings);
|
|
||||||
|
println!("{prod}");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_hand_types() {
|
fn test() {}
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue