my solutions to advent of code
aoc
advent-of-code
1use std::{iter::once, mem::swap};
2
3fn generations(times: u32, mut world: Vec<u8>, size: usize, stuck: bool) -> Vec<u8> {
4 #[inline]
5 fn get_at(world: &Vec<u8>, size: usize, x: usize, y: usize) -> u8 {
6 // benefits from the integer overflow to simplify code
7 if x >= size || y >= size {
8 return 0;
9 };
10 // this is in known bounds
11 unsafe { *world.get_unchecked(y * size + x) }
12 }
13
14 let mut new_world = vec![0_u8; size * size];
15 let sizem = size - 1;
16 if stuck {
17 world[0] = 1;
18 world[sizem] = 1;
19 world[(size * size) - 1] = 1;
20 world[size * sizem] = 1;
21 }
22
23 for _ in 0..times {
24 for yo in 1..=size {
25 let ym = yo - 1;
26 let yp = yo + 1;
27 for xo in 1..=size {
28 let xm = xo - 1;
29 let xp = xo + 1;
30
31 let was = get_at(&world, size, xo, yo) == 1;
32 let neighbours = get_at(&world, size, xm, ym)
33 + get_at(&world, size, xo, ym)
34 + get_at(&world, size, xp, ym)
35 + get_at(&world, size, xm, yo)
36 + get_at(&world, size, xp, yo)
37 + get_at(&world, size, xm, yp)
38 + get_at(&world, size, xo, yp)
39 + get_at(&world, size, xp, yp);
40 new_world[yo * size + xo] = (neighbours == 3 || (neighbours == 2 && was)) as u8;
41 }
42 }
43
44 swap(&mut world, &mut new_world);
45
46 // i hate the duplication here :(
47 if stuck {
48 world[0] = 1;
49 world[sizem] = 1;
50 world[(size * size) - 1] = 1;
51 world[size * sizem] = 1;
52 }
53 }
54 world
55}
56
57fn main() {
58 let input = include_str!("../../input.txt").trim();
59 let size = input.split_once("\n").expect("invalid input").0.len();
60 let input: Vec<u8> = once(".".repeat(size))
61 .chain(input.split("\n"))
62 .chain(".".repeat(size))
63 .map(|line| {
64 once(0)
65 .chain(line.chars().map(|v| (v == '#') as u8))
66 .chain(once(0))
67 })
68 .flatten()
69 .collect();
70
71 let part_1 = generations(100, input.clone(), size, false)
72 .iter()
73 .filter(|v| **v == 1)
74 .count();
75 println!("Part 1: {}", part_1);
76
77 let part_2 = generations(100, input.clone(), size, true)
78 .iter()
79 .filter(|v| **v == 1)
80 .count();
81 println!("Part 2: {}", part_2);
82}