+30
-25
2015/18/rust/src/main.rs
+30
-25
2015/18/rust/src/main.rs
···
1
-
use std::{iter::once, mem::swap};
1
+
use std::mem::swap;
2
2
3
3
fn generations(times: u32, mut world: Vec<u8>, size: usize, stuck: bool) -> Vec<u8> {
4
+
#[inline]
5
+
fn pos(x: usize, y: usize, size: usize) -> usize {
6
+
(1 + y) * (size + 2) + (1 + x)
7
+
}
8
+
4
9
#[inline]
5
10
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
11
// this is in known bounds
11
-
unsafe { *world.get_unchecked(y * size + x) }
12
+
unsafe { *world.get_unchecked(pos(x, y, size)) }
12
13
}
13
14
14
-
let mut new_world = vec![0_u8; size * size];
15
15
let sizem = size - 1;
16
+
17
+
let mut new_world = vec![0_u8; (size + 2).pow(2)];
18
+
16
19
if stuck {
17
-
world[0] = 1;
18
-
world[sizem] = 1;
19
-
world[(size * size) - 1] = 1;
20
-
world[size * sizem] = 1;
20
+
world[pos(0, 0, size)] = 1;
21
+
world[pos(sizem, 0, size)] = 1;
22
+
world[pos(0, sizem, size)] = 1;
23
+
world[pos(sizem, sizem, size)] = 1;
21
24
}
22
25
23
26
for _ in 0..times {
24
-
for yo in 1..=size {
27
+
for yo in 0..size {
25
28
let ym = yo - 1;
26
29
let yp = yo + 1;
27
-
for xo in 1..=size {
30
+
for xo in 0..size {
28
31
let xm = xo - 1;
29
32
let xp = xo + 1;
30
33
···
37
40
+ get_at(&world, size, xm, yp)
38
41
+ get_at(&world, size, xo, yp)
39
42
+ get_at(&world, size, xp, yp);
40
-
new_world[yo * size + xo] = (neighbours == 3 || (neighbours == 2 && was)) as u8;
43
+
new_world[pos(xo, yo, size)] = (neighbours == 3 || (neighbours == 2 && was)) as u8;
41
44
}
42
45
}
43
46
···
45
48
46
49
// i hate the duplication here :(
47
50
if stuck {
48
-
world[0] = 1;
49
-
world[sizem] = 1;
50
-
world[(size * size) - 1] = 1;
51
-
world[size * sizem] = 1;
51
+
world[pos(0, 0, size)] = 1;
52
+
world[pos(sizem, 0, size)] = 1;
53
+
world[pos(0, sizem, size)] = 1;
54
+
world[pos(sizem, sizem, size)] = 1;
52
55
}
53
56
}
54
57
world
···
57
60
fn main() {
58
61
let input = include_str!("../../input.txt").trim();
59
62
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))
63
+
// reads the input but adds a line of buffer on the sides
64
+
let buffer_line = ".".repeat(size);
65
+
let input: Vec<u8> = format!("{buffer_line}\n{input}\n{buffer_line}")
66
+
.split("\n")
67
+
.map(|line| -> Vec<u8> {
68
+
format!(".{}.", line)
69
+
.chars()
70
+
.map(|v| (v == '#') as u8)
71
+
.collect()
67
72
})
68
73
.flatten()
69
74
.collect();