use std::io; use std::io::BufRead; pub fn main(reader: T) -> io::Result<(String, String)> { #[derive(PartialEq, Eq)] struct Entry { nch: i32, nmeta: i32, } let mut stk = vec![Entry {nch: 1, nmeta: 0}]; let mut total_meta = 0; let mut vals: Vec> = vec![vec![]]; let mut current_val = 0; for num in reader.lines().next().unwrap().unwrap().split(' ').map(|s| s.parse::().unwrap()) { // Yay non-lexical lifetimes! let l = stk.last_mut().unwrap(); if l.nmeta == -1 { // println!("read nmeta {}", num); l.nmeta = num; continue; } if l.nmeta == 0 && l.nch == 0 { loop { // println!("pop"); stk.pop(); // println!(" node value {}", current_val); vals.pop(); vals.last_mut().unwrap().push(current_val); current_val = 0; let l = stk.last().unwrap(); if l.nmeta != 0 || l.nch != 0 { break; } } } let l = stk.last_mut().unwrap(); if l.nch == 0 { // println!("+meta {}", num); total_meta += num; if vals.last().unwrap().len() == 0 { // println!(" add value"); current_val += num; } else if 1 <= num && num <= vals.last().unwrap().len() as i32 { // println!(" add child value {}", vals.last().unwrap()[num as usize - 1]); current_val += vals.last().unwrap()[num as usize - 1]; } l.nmeta -= 1; } else { // println!("read nch {}", num); l.nch -= 1; stk.push(Entry {nch: num, nmeta: -1}); vals.push(vec![]); } } let part1 = total_meta.to_string(); let part2 = current_val.to_string(); Ok((part1, part2)) }