Last active
December 2, 2023 15:50
-
-
Save koivunej/cbc9274574da7273c2bb94be8544018e to your computer and use it in GitHub Desktop.
aoc 2023 day 01, spider "dfa"
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
fn main() { | |
let stdin = std::io::stdin(); | |
let stdin = stdin.lock(); | |
let mut phases = (Phase1::default(), Phase2::default()); | |
ingest(stdin, &mut phases); | |
println!("{phases:?}"); | |
} | |
trait Ingest { | |
fn ingest(&mut self, buf: &str); | |
} | |
#[derive(Default, Debug)] | |
struct Phase1(u64); | |
impl Ingest for Phase1 { | |
fn ingest(&mut self, buf: &str) { | |
let mut chars = buf | |
.char_indices() | |
.filter_map(|(i, ch)| { | |
if ch.is_digit(10) { | |
Some((i, ch as u8 - '0' as u8)) | |
} else { | |
None | |
} | |
}) | |
.fuse(); | |
let first = chars.next(); | |
let last = chars.last(); | |
let val = [first, last] | |
.into_iter() | |
.filter_map(|x| x) | |
.cycle() | |
.take(2) | |
.fold(0u64, |acc, (_, digit)| acc * 10 + digit as u64); | |
self.0 += val; | |
} | |
} | |
#[derive(Default, Debug)] | |
struct Phase2(u64); | |
impl Ingest for Phase2 { | |
fn ingest(&mut self, mut buf: &str) { | |
let mut first = None; | |
let mut last = None; | |
'outer: while !buf.is_empty() { | |
let mut rem = buf.chars().peekable(); | |
while let Some(next) = rem.next() { | |
let (consume_more, value) = match next { | |
'o' => ("ne", Some(1)), | |
't' => match rem.peek() { | |
Some('w') => ("wo", Some(2)), | |
Some('h') => ("hree", Some(3)), | |
_ => ("", None), | |
}, | |
'f' => match rem.peek() { | |
Some('o') => ("our", Some(4)), | |
Some('i') => ("ive", Some(5)), | |
_ => ("", None), | |
}, | |
's' => match rem.peek() { | |
Some('i') => ("ix", Some(6)), | |
Some('e') => ("even", Some(7)), | |
_ => ("", None), | |
}, | |
'e' => ("ight", Some(8)), | |
'n' => ("ine", Some(9)), | |
// 'z' => ("ero", Some(0)), | |
x @ '0'..='9' => ("", Some(x as u8 - '0' as u8)), | |
_ => ("", None), | |
}; | |
for ch in consume_more.chars() { | |
if rem.next() == Some(ch) { | |
// good | |
} else { | |
// println!("mismatch"); | |
let mut rem = buf.chars(); | |
rem.next(); | |
buf = rem.as_str(); | |
continue 'outer; | |
} | |
} | |
let value = value.map(|x| x as u64); | |
if first.is_none() { | |
first = value; | |
} | |
if value.is_some() { | |
last = value; | |
} | |
let mut rem = buf.chars(); | |
rem.next(); | |
// leave the last value unconsumed, so sevenine is 79 | |
if !consume_more.is_empty() { | |
for _ in 0..(consume_more.len() - 1) { | |
rem.next().unwrap(); | |
} | |
} | |
buf = rem.as_str(); | |
continue 'outer; | |
} | |
} | |
let value = first.unwrap() * 10 + last.unwrap(); | |
self.0 += value; | |
} | |
} | |
impl<A: Ingest, B: Ingest> Ingest for (A, B) { | |
fn ingest(&mut self, buf: &str) { | |
self.0.ingest(buf); | |
self.1.ingest(buf); | |
} | |
} | |
fn ingest(mut input: impl std::io::BufRead, phase: &mut impl Ingest) { | |
let mut buf = String::new(); | |
loop { | |
buf.clear(); | |
let read = input.read_line(&mut buf).unwrap(); | |
if read == 0 { | |
break; | |
} | |
let buf = buf.trim(); | |
phase.ingest(buf); | |
} | |
} | |
#[cfg(test)] | |
fn phase1(input: impl std::io::BufRead) -> u64 { | |
let mut phase = Phase1::default(); | |
ingest(input, &mut phase); | |
phase.0 | |
} | |
#[cfg(test)] | |
fn phase2(input: impl std::io::BufRead) -> u64 { | |
let mut phase = Phase2::default(); | |
ingest(input, &mut phase); | |
phase.0 | |
} | |
#[test] | |
fn example1() { | |
let input = "1abc2 | |
pqr3stu8vwx | |
a1b2c3d4e5f | |
treb7uchet"; | |
assert_eq!(phase1(std::io::Cursor::new(input)), 142); | |
} | |
#[test] | |
fn example2() { | |
let input = "two1nine | |
eightwothree | |
abcone2threexyz | |
xtwone3four | |
4nineeightseven2 | |
zoneight234 | |
7pqrstsixteen"; | |
assert_eq!(phase2(std::io::Cursor::new(input)), 281); | |
} | |
#[test] | |
fn reddit_hint() { | |
let input = "eighthree | |
sevenine"; | |
assert_eq!(phase2(std::io::Cursor::new(input)), 83 + 79); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment