use std::env; use std::io::BufReader; use std::io::BufRead; use std::fs::File; use std::process; use std::collections::HashMap; type State = HashMap; type RuleKey = (char, char, char, char, char); type Rules = HashMap; static ITERATIONS: usize = 150; fn parse_initial_state(line: &String) -> (State, i64, i64) { let initial: Vec = line[15..].chars().collect(); let mut state: State = State::new(); for (i, &ch) in initial.iter().enumerate() { state.insert(i as i64, ch); } let c = initial.len() as i64; state.insert(-1, '.'); state.insert(-2, '.'); state.insert(c, '.'); state.insert(c + 1, '.'); (state, 0, c + 1) } fn parse_rule(rules: &mut Rules, line: &String) { let chs: Vec = line.chars().collect(); let res: char = chs[chs.len() - 1]; let p = chs[0..6].to_vec(); let rule_key = (p[0], p[1], p[2], p[3], p[4]); rules.insert(rule_key, res); } fn eval_rules(state: &State, rules: &Rules, i: i64) -> char { let prev2 = if state.contains_key(&(i - 2)) { state[&(i - 2)] } else { '.' }; let prev1 = if state.contains_key(&(i - 1)) { state[&(i - 1)] } else { '.' }; let cur = if state.contains_key(&i) { state[&i] } else { '.' }; let next1 = if state.contains_key(&(i + 1)) { state[&(i + 1)] } else { '.' }; let next2 = if state.contains_key(&(i + 2)) { state[&(i + 2)] } else { '.' }; rules[&(prev2, prev1, cur, next1, next2)] } fn draw_state(state: &State, iteration: usize) { let mut keys: Vec = state.keys().map(|&k| k).collect(); keys.sort(); print!("{}: ", iteration); for k in &keys { print!("{} ", state[k]); } print!("\n"); } fn sum_state(state: &State) -> i64 { let mut total = 0; for (i, &ch) in state { if ch == '#' { total += i; } } total } fn main() { let args: Vec = env::args().collect(); if args.len() != 2 { println!("Wrong number of arguments. Provide a file name and worker count."); process::exit(1); } let filename = &args[1]; println!("Using file {} as input.", filename); let f = match File::open(filename) { Ok(file) => file, Err(e) => { println!("Failed to open file {}. {:?}", filename, e); process::exit(1); } }; let file = BufReader::new(&f); let lines: Vec = file.lines() .map(|line| line.expect("Could not parse line.")) .collect(); let mut initial_state: State = State::new(); let (mut i1, mut i2): (i64, i64) = (0, 0); let mut rules: Rules = HashMap::new(); for (i, line) in lines.iter().enumerate() { match i { 0 => { let tuple = parse_initial_state(&line); initial_state = tuple.0; i1 = tuple.1; i2 = tuple.2; } 1 => { } _ => { parse_rule(&mut rules, &line); } } } assert_ne!(initial_state.len(), 0); let mut prev_state = initial_state; let mut prev_sum = 0; // draw_state(&prev_state, 0); for iteration in 0..ITERATIONS { let mut new_state = prev_state.clone(); if prev_state[&(i1 + 1)] == '#' { new_state.insert(i1 - 1, '.'); new_state.insert(i1 - 2, '.'); i1 -= 2; } if prev_state[&(i2 - 1)] == '#' { new_state.insert(i2 + 1, '.'); new_state.insert(i2 + 2, '.'); i2 += 2; } let keys: Vec = new_state.keys().map(|&k| k).collect(); for key in keys { let val = eval_rules(&prev_state, &rules, key); new_state.insert(key, val); } // if iteration % 1000 == 0 { // println!("Iteration: {}", iteration); // } let sum = sum_state(&new_state); let diff = sum - prev_sum; println!("It: {}, sum: {}, diff: {}", iteration + 1, sum, diff); prev_sum = sum; // draw_state(&new_state, iteration); prev_state = new_state; } let last_state = prev_state; let total = sum_state(&last_state); println!("Result: {}", total); let iters2 = 50000000000u64; let result2 = 9152 + (iters2 - 140) * 52; println!("Result 2: {}", result2); }