@@ 1,1 1,120 @@
-fn main() {}
+//static INPUT: &str = "data/day12";
+
+static INPUT: &[u8] = b"#.......##.###.#.#..##..##..#.#.###..###..##.#.#..##....#####..##.#.....########....#....##.#..##...";
+
+fn rule(m: &[u8]) -> u8 {
+ match m {
+ b"#####" => b'#',
+ b"####." => b'#',
+ b"###.#" => b'#',
+ b"###.." => b'.',
+ b"##.##" => b'.',
+ b"##.#." => b'#',
+ b"##..#" => b'#',
+ b"##..." => b'#',
+ b"#.###" => b'.',
+ b"#.##." => b'.',
+ b"#.#.#" => b'#',
+ b"#.#.." => b'.',
+ b"#..##" => b'.',
+ b"#..#." => b'#',
+ b"#...#" => b'#',
+ b"#...." => b'.',
+ b".####" => b'.',
+ b".###." => b'#',
+ b".##.#" => b'#',
+ b".##.." => b'.',
+ b".#.##" => b'#',
+ b".#.#." => b'.',
+ b".#..#" => b'.',
+ b".#..." => b'#',
+ b"..###" => b'.',
+ b"..##." => b'.',
+ b"..#.#" => b'#',
+ b"..#.." => b'.',
+ b"...##" => b'.',
+ b"...#." => b'#',
+ b"....#" => b'.',
+ b"....." => b'.',
+ _ => panic!("invalid input"),
+ }
+}
+
+fn last(l: &[u8]) -> [u8; 4] {
+ let n = l.len();
+ [rule(&[l[n - 4], l[n - 3], l[n - 2], l[n - 1], b'.']),
+ rule(&[l[n - 3], l[n - 2], l[n - 1], b'.', b'.']),
+ rule(&[l[n - 2], l[n - 1], b'.', b'.', b'.']),
+ rule(&[l[n - 1], b'.', b'.', b'.', b'.'])]
+}
+
+fn generation(line: Vec<u8>, zero: usize) -> (Vec<u8>, usize) {
+ let first = [rule(&[b'.', b'.', b'.', b'.', line[0]]),
+ rule(&[b'.', b'.', b'.', line[0], line[1]]),
+ rule(&[b'.', b'.', line[0], line[1], line[2]]),
+ rule(&[b'.', line[0], line[1], line[2], line[3]])];
+ let first = if first[0] == b'.' {
+ if first[1] == b'.' {
+ &first[2..]
+ } else {
+ &first[1..]
+ }
+ } else {
+ &first[..]
+ };
+
+ let next = line.windows(5).map(rule);
+ let last = last(&line);
+ let last = if let Some(p) = last.iter().rposition(|&b| b == b'#') {
+ &last[0..p+1]
+ } else {
+ &[]
+ };
+ (first.iter().cloned().chain(next).chain(last.iter().cloned()).collect::<Vec<_>>(),
+ zero + first.len() - 2)
+}
+
+fn plant_sum(line: &[u8], zero: usize) -> isize {
+ line.iter().enumerate().map(|(i, &e)| if e == b'#' {
+ (i as isize - zero as isize)
+ } else {
+ 0
+ }).sum()
+}
+
+fn main() {
+ let mut line = Vec::from(INPUT);
+ let mut zero = 0;
+
+ for _ in 0..20 {
+ let gen = generation(line, zero);
+ line = gen.0;
+ zero = gen.1;
+ }
+
+ let mut sum = plant_sum(&line, zero);
+ println!(" 1: {}", sum);
+
+ // Assumption, difference stabilizes eventually
+ let mut heuristic = 0;
+ let mut diff = 0;
+ let mut end_gen = 20;
+ loop {
+ end_gen += 1;
+ let gen = generation(line, zero);
+ line = gen.0;
+ zero = gen.1;
+ let prev = sum;
+ sum = plant_sum(&line, zero);
+ if diff == sum-prev {
+ heuristic += 1;
+ } else {
+ heuristic = 0;
+ }
+ if heuristic > 1000 {
+ break;
+ }
+ diff = sum - prev;
+ };
+ println!(" 2: {}", sum + (50_000_000_000 - end_gen) * diff);
+}