fn is_safe(l: char, c: char, r: char) -> bool { // Rule #1. if l == '^' && c == '^' && r == '.' { return false; } // Rule #2. if l == '.' && c == '^' && r == '^' { return false; } // Rule #3. if l == '^' && c == '.' && r == '.' { return false; } // Rule #4. if l == '.' && c == '.' && r == '^' { return false; } true } pub fn evaluate(input: &str) -> String { let input = input.chars().collect::>(); let mut output = String::new(); for i in 0..input.len() { let c = if i == 0 { if is_safe('.', input[i], input[i + 1]) { '.' } else { '^' } } else if i == input.len() - 1 { if is_safe(input[i - 1], input[i], '.') { '.' } else { '^' } } else { if is_safe(input[i - 1], input[i], input[i + 1]) { '.' } else { '^' } }; output.push(c); } output } fn main() { let mut map = Vec::new(); map.push(".^^^^^.^^.^^^.^...^..^^.^.^..^^^^^^^^^^..^...^^.^..^^^^..^^^^...^.^.^^^^^^^^....^..^^^^^^.^^^.^^^.^^".to_owned()); while map.len() < 400000 { let next = { let last = map.last().unwrap(); evaluate(last) }; map.push(next); } let count: usize = map.iter() .map(|row| { row.chars() .filter(|c| *c == '.') .count() }) .sum(); println!("safe_tiles={}", count); } #[cfg(test)] mod tests { use super::*; #[test] fn example_01() { assert_eq!(".^^^^".to_owned(), evaluate("..^^.")); } #[test] fn example_02() { assert_eq!("^^..^".to_owned(), evaluate(".^^^^")); } #[test] fn example_03() { assert_eq!("^^^...^..^".to_owned(), evaluate(".^^.^.^^^^")); } }