85 lines
1.9 KiB
Rust
85 lines
1.9 KiB
Rust
use crate::prelude::*;
|
|
|
|
pub type T = (String, M<char, usize>, Vec<char>, u32);
|
|
pub type I = Vec<T>;
|
|
pub type O = u32;
|
|
|
|
fn _parse (data: &str) -> I {
|
|
data.lines().map(|line| {
|
|
let mut parts = line.split('-').collect_vec();
|
|
let last = parts.pop().unwrap();
|
|
let rest = parts.join(" ");
|
|
let m = parts.into_iter().map(|p| p.chars()).flatten().counts();
|
|
|
|
let (number, checksum) = last.split_once('[').unwrap();
|
|
|
|
let number = number.parse().unwrap();
|
|
let checksum = checksum.trim_matches(']').chars().collect();
|
|
|
|
(rest, m, checksum, number)
|
|
}).collect()
|
|
}
|
|
|
|
fn _solve <'a> (data: &'a I) -> impl Iterator<Item = (&'a String, &'a u32)> {
|
|
data.into_iter().filter_map(|(st, m, checksum, num)| {
|
|
let mut m = m.into_iter().collect_vec();
|
|
|
|
m.sort_by(|a, b| match b.1.cmp(&a.1) {
|
|
Or::Equal => a.0.cmp(&b.0),
|
|
e => e
|
|
});
|
|
|
|
if checksum.into_iter().zip(m.into_iter()).all(|(&l, (&r, _))| l == r) {
|
|
Some((st, num))
|
|
} else {
|
|
None
|
|
}
|
|
})
|
|
}
|
|
|
|
fn _silver (data: &I) -> O {
|
|
_solve(data).map(|(_, num)| num).sum()
|
|
}
|
|
|
|
fn _gold (data: &I) -> O {
|
|
*_solve(data).find(|(s, num)| {
|
|
let mut s = s.chars().collect_vec();
|
|
for c in s.iter_mut() {
|
|
match *c {
|
|
' ' => (),
|
|
a => {
|
|
*c = ((((a as u8 - b'a') as u32 + *num) % 26) + b'a' as u32) as u8 as char;
|
|
}
|
|
}
|
|
}
|
|
let s = s.into_iter().collect::<String>();
|
|
s.contains("north")
|
|
}).unwrap().1
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use super::*;
|
|
|
|
fn read () -> I {
|
|
let data = inc!(4);
|
|
_parse(data)
|
|
}
|
|
|
|
#[test]
|
|
fn silver () {
|
|
let data = read();
|
|
let ans = _silver(&data);
|
|
|
|
assert_eq!(ans, 278221)
|
|
}
|
|
|
|
#[test]
|
|
fn gold () {
|
|
let data = read();
|
|
let ans = _gold(&data);
|
|
|
|
assert_eq!(ans, 267)
|
|
}
|
|
}
|