Rust
use itertools::Itertools;
type Fishbone = Vec<(i64, Option<i64>, Option<i64>)>;
fn parse_fishbone(quality_str: &str) -> Fishbone {
let mut fishbone: Fishbone = vec![];
'outer: for num in quality_str.split(",").map(|x| x.parse().unwrap()) {
for e in fishbone.iter_mut() {
if num < e.0 && e.1.is_none() {
e.1 = Some(num);
continue 'outer;
}
if num > e.0 && e.2.is_none() {
e.2 = Some(num);
continue 'outer;
}
}
fishbone.push((num, None, None));
}
fishbone
}
fn compute_quality(fishbone: &Fishbone) -> i64 {
fishbone
.iter()
.map(|(c, _, _)| c.to_string())
.join("")
.parse()
.unwrap()
}
pub fn solve_part_1(input: &str) -> String {
let (_, data) = input.split_once(":").unwrap();
compute_quality(&parse_fishbone(data)).to_string()
}
pub fn solve_part_2(input: &str) -> String {
let mut worst_quality = i64::MAX;
let mut best_quality = i64::MIN;
for sword in input.lines() {
let (_, data) = sword.split_once(":").unwrap();
let quality = compute_quality(&parse_fishbone(data));
worst_quality = worst_quality.min(quality);
best_quality = best_quality.max(quality);
}
(best_quality - worst_quality).to_string()
}
pub fn solve_part_3(input: &str) -> String {
let mut swords: Vec<_> = input
.lines()
.map(|def| {
let (id, data) = def.split_once(":").unwrap();
let fishbone = parse_fishbone(data);
(id.parse::<i64>().unwrap(), fishbone)
})
.collect();
swords.sort_by(|a, b| {
let cmp = compute_quality(&a.1).cmp(&compute_quality(&b.1));
if !matches!(cmp, std::cmp::Ordering::Equal) {
return cmp;
}
for (a_seg, b_seg) in a.1.iter().zip(b.1.iter()) {
let a_val = match a_seg {
(a, Some(b), Some(c)) => format!("{b}{a}{c}"),
(a, Some(b), None) => format!("{b}{a}"),
(a, None, Some(c)) => format!("{a}{c}"),
(a, None, None) => format!("{a}"),
};
let b_val = match b_seg {
(a, Some(b), Some(c)) => format!("{b}{a}{c}"),
(a, Some(b), None) => format!("{b}{a}"),
(a, None, Some(c)) => format!("{a}{c}"),
(a, None, None) => format!("{a}"),
};
let cmp = a_val.parse::<i64>().unwrap().cmp(&b_val.parse().unwrap());
if !matches!(cmp, std::cmp::Ordering::Equal) {
return cmp;
}
}
a.0.cmp(&b.0)
});
swords.reverse();
swords
.into_iter()
.enumerate()
.map(|(pos, (id, _))| id * (pos as i64 + 1))
.sum::<i64>()
.to_string()
}
Rust