diff --git a/2021/src/day14.rs b/2021/src/day14.rs index 3797fad..39bd26b 100644 --- a/2021/src/day14.rs +++ b/2021/src/day14.rs @@ -1,14 +1,152 @@ -use std::{ - collections::HashMap, - fmt::{Debug, Error, Formatter}, - num::ParseIntError, - ops::{Index, IndexMut}, - str::FromStr, -}; +use std::collections::HashMap; use anyhow::Result; -use aoc_runner_derive::{aoc, aoc_generator}; -use thiserror::Error; +use aoc_runner_derive::aoc; + +struct TupleWindow +where + I: Iterator, +{ + iter: I, + prev: Option, + next: Option, +} + +impl TupleWindow +where + I: Iterator, +{ + fn new(iter: I, rules: &HashMap<&[u8], u8>) -> Self { + TupleWindow { + iter, + prev: None, + next: None, + } + } +} + +impl Iterator for TupleWindow +where + I: Iterator, +{ + type Item = T; + + fn next(&mut self) -> Option { + if self.prev.is_none() { + self.prev = self.iter.next(); + } + /* + template.next() { + template.flat_map(|y| + let z = rules[xy]; + res[i * 2] = xy[0]; + res[i * 2 + 1] = z; + res[i * 2 + 2] = xy[1]; + }); + //dbg!(String::from_utf8_lossy(&res)); + res + */ + + if let Some(next) = self.iter.next() { + let prev = self.prev.take(); + self.prev = Some(next); + return prev; + } + None + } +} + +fn expand_it<'a, I: 'a + Iterator>( + template: I, + rules: &HashMap<&[u8], u8>, +) -> impl Iterator { + TupleWindow::new(template, rules) +} + +fn forty_steps<'a, I: 'a + Iterator>(it: I, rules: &HashMap<&[u8], u8>) -> usize { + //let it = (1..40).fold(it, |acc, _| expand_it(acc, &rules)); + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it( + expand_it(it, &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules), + &rules, + ) + .count() +} fn expand(template: &[u8], rules: &HashMap<&[u8], u8>) -> Vec { let mut res = vec![0u8; template.len() * 2 - 1]; @@ -29,6 +167,13 @@ fn count(template: &[u8]) -> (usize, usize) { *m.entry(*v).or_insert(0) += 1; m }); + let mut keys: Vec<_> = m.keys().collect(); + keys.sort_unstable(); + let mut s = "".to_string(); + for k in keys { + s.push_str(&format!("{}: {} ", String::from_utf8_lossy(&[*k]), m[k])); + } + println!("Counts: {}", s); m.values() .fold((usize::MAX, 0), |(min, max), v| (min.min(*v), max.max(*v))) } @@ -46,19 +191,31 @@ fn part1(input: &str) -> Result { let mut template = template.as_bytes().to_vec(); for i in 1..11 { template = expand(&template, &rules); - //println!("After step {}: {}", i, String::from_utf8_lossy(&template)); + let s = String::from_utf8_lossy(&template); + println!("After step {}: ({}) {}", i, s.len(), s); + count(&template); } let (min, max) = count(&template); Ok(max - min) } -/* #[aoc(day14, part2)] -fn part2(input: &[u64]) -> Result { -todo!("part2"); -Ok(0) +fn part2(input: &str) -> Result { + let (template, rules) = input.split_once("\n\n").unwrap(); + let rules: HashMap<&[u8], u8> = rules + .lines() + .map(|l| { + let (pair, insert) = l.split_once(" -> ").unwrap(); + (pair.as_bytes(), insert.as_bytes()[0]) + }) + .collect(); + let cnt = forty_steps(template.as_bytes().iter(), &rules); + dbg!(cnt); + //println!("After step {}: {}", i, String::from_utf8_lossy(&template)); + //let (min, max) = count(template); + //Ok(max - min) + Ok(0) } -*/ #[cfg(test)] mod tests { @@ -67,38 +224,74 @@ mod tests { #[test] fn test_part1() -> Result<()> { let input = r#" -NNCB + NNCB -CH -> B -HH -> N -CB -> H -NH -> C -HB -> C -HC -> B -HN -> C -NN -> C -BH -> H -NC -> B -NB -> B -BN -> B -BB -> N -BC -> B -CC -> N -CN -> C -"# + CH -> B + HH -> N + CB -> H + NH -> C + HB -> C + HC -> B + HN -> C + NN -> C + BH -> H + NC -> B + NB -> B + BN -> B + BB -> N + BC -> B + CC -> N + CN -> C + "# .trim(); assert_eq!(part1(input)?, 1588); Ok(()) } - /* #[test] - fn test_part2()->Result<()> { - let input = r#" - "# - .trim(); - assert_eq!(part2(&parse(input)?)?, u64::MAX); - Ok(()) + fn test_part2() -> Result<()> { + let input = r#" + NNCB + + CH -> B + HH -> N + CB -> H + NH -> C + HB -> C + HC -> B + HN -> C + NN -> C + BH -> H + NC -> B + NB -> B + BN -> B + BB -> N + BC -> B + CC -> N + CN -> C + "# + .trim(); + assert_eq!(part2(input)?, 2188189693529); + Ok(()) } - */ } + +// BB -> N BN NB BB NB NB BB +// BC -> B BB BC BN NB BB BC +// BH -> H BH HH BH HH HN NH +// BN -> B BB NB BN NB NB BB +// CB -> H CH HB \ +// CC -> N CN NC +// CH -> B CB BH +// CN -> C CC CN +// HB -> C HC CB +// HC -> B HB BC +// HH -> N HN NH +// HN -> C HC CN +// NB -> B NB BB +// NC -> B NC BC +// NH -> C NC CH +// NN -> C NC CN +// +// +//