use std::env::args; use std::fs::File; use std::io::BufRead; use std::io::BufReader; use std::collections::HashMap; fn get_pos(bytes: &mut Vec, item: T) -> usize { match bytes.iter().position(|x| *x == item) { Some(v) => return v, None => { bytes.push(item); return bytes.len() - 1; }, } } fn get_data(path: &str) -> (Vec, HashMap<(usize, usize), usize>, usize) { let file = File::open(path).unwrap(); let mut state = 0; let mut bytes = vec![]; let mut first_line = vec![]; let mut rules = HashMap::new(); for line in BufReader::new(file).lines() { let l = line.unwrap(); match state { 0 => { for c in l.chars() { first_line.push(get_pos(&mut bytes, c)); } state = 1; }, 2 => { assert_eq!(l.chars().count(), 7); let a = get_pos(&mut bytes, l.chars().nth(0).unwrap()); let b = get_pos(&mut bytes, l.chars().nth(1).unwrap()); let c = get_pos(&mut bytes, l.chars().nth(6).unwrap()); rules.insert((a, b), c); }, _ => { assert_eq!(l, ""); state = 2; }, } } return (first_line, rules, bytes.len()); } fn score(m: &Vec, n: usize, last: usize) -> u64 { let mut scores = vec![0; n]; for row in 0..n { for col in 0..n { scores[row] += m[row * n + col]; } } scores[last] += 1; let min = scores.iter().filter(|x| **x > 0).min().unwrap(); let max = scores.iter().max().unwrap(); return *max - *min; } fn main() { let path = args().nth(1).unwrap(); let steps = args().nth(2).unwrap().parse::().unwrap(); let (first_line, rules, n) = get_data(&path); let mut counts = vec![0; n * n]; let mut prev = None; for i in first_line { match prev { Some(j) => counts[j * n + i] += 1, None => {}, } prev = Some(i); } for _ in 0..steps { let mut new = vec![0; n * n]; for row in 0..n { for col in 0..n { let count = counts[row * n + col]; match rules.get(&(row, col)) { Some(m) => { new[row * n + *m] += count; new[*m * n + col] += count; }, None => { new[row * n + col] += count; }, } } } counts = new; } println!("{}", score(&counts, n, prev.unwrap())); }