rust(day17): Optimize to run in 34 ms

This commit is contained in:
Sijmen 2020-12-23 15:53:25 +01:00
parent 7b6e8f05e0
commit 90e0a3060e
Signed by: vijfhoek
GPG Key ID: DAF7821E067D9C48
3 changed files with 73 additions and 123 deletions

50
rust/Cargo.lock generated
View File

@ -1,56 +1,6 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "aho-corasick"
version = "0.7.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
dependencies = [
"memchr",
]
[[package]]
name = "aoc"
version = "0.1.0"
dependencies = [
"regex",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "memchr"
version = "2.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
[[package]]
name = "regex"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
"thread_local",
]
[[package]]
name = "regex-syntax"
version = "0.6.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189"
[[package]]
name = "thread_local"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
dependencies = [
"lazy_static",
]

View File

@ -7,4 +7,3 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
regex = "1.4.2"

View File

@ -1,99 +1,100 @@
use std::time::{Duration, Instant};
const SIZE: usize = 50;
const SIZE: usize = 20;
const OFFSET: usize = SIZE / 2;
type Field = Vec<Vec<Vec<bool>>>;
type Field = Vec<[[[bool; SIZE]; SIZE]; SIZE]>;
pub fn step(field: &mut Field) {
pub fn step(hypercube: &mut Field) {
let mut changes = Vec::new();
for (z, slice) in field.iter().enumerate() {
for (y, row) in slice.iter().enumerate() {
for (x, cell) in row.iter().enumerate() {
let mut neighbors = 0;
for dz in -1..=1 {
for dy in -1..=1 {
for dx in -1..=1 {
let nx = dx + x as i64;
let ny = dy + y as i64;
let nz = dz + z as i64;
for w in 0..hypercube.len() as i64 {
for z in 0..SIZE as i64 {
for y in 0..SIZE as i64 {
for x in 0..SIZE as i64 {
let mut neighbors = 0;
for dw in -1..=1 {
for dz in -1..=1 {
for dy in -1..=1 {
for dx in -1..=1 {
let nx = dx + x;
let ny = dy + y;
let nz = dz + z;
let nw = dw + w;
if (nx == x as i64 && ny == y as i64 && nz == z as i64)
|| (nx < 0 || nx >= SIZE as i64)
|| (ny < 0 || ny >= SIZE as i64)
|| (nz < 0 || nz >= SIZE as i64)
{
continue;
}
if field[nz as usize][ny as usize][nx as usize] {
neighbors += 1;
if !(nx == x && ny == y && nz == z && nw == w)
&& !(nx < 0 || nx >= SIZE as i64)
&& !(ny < 0 || ny >= SIZE as i64)
&& !(nz < 0 || nz >= SIZE as i64)
&& !(nw < 0 || nw >= hypercube.len() as i64)
&& hypercube[nw as usize][nz as usize][ny as usize]
[nx as usize]
{
neighbors += 1;
}
}
}
}
}
}
if *cell && neighbors != 2 && neighbors != 3 {
changes.push((x, y, z, false));
}
if !cell && neighbors == 3 {
changes.push((x, y, z, true));
let cell = hypercube[w as usize][z as usize][y as usize][x as usize];
if cell && neighbors != 2 && neighbors != 3 {
changes.push((x, y, z, w, false));
}
if !cell && neighbors == 3 {
changes.push((x, y, z, w, true));
}
}
}
}
}
for (x, y, z, state) in changes {
field[z][y][x] = state;
for (x, y, z, w, state) in changes {
hypercube[w as usize][z as usize][y as usize][x as usize] = state;
}
}
pub fn run(_: bool) -> Duration {
pub fn simulate(input: &str, n: usize) -> usize {
assert!(n == 3 || n == 4);
let w_size = if n == 3 { 1 } else { SIZE };
let w_offset = if n == 3 { 0 } else { OFFSET };
let mut field = vec![[[[false; SIZE]; SIZE]; SIZE]; w_size];
for (y, line) in input.lines().enumerate() {
for (x, cell) in line.chars().enumerate() {
field[w_offset][OFFSET][y + OFFSET - 2][x + OFFSET - 2] = cell == '#';
}
}
for _ in 0..6 {
step(&mut field);
}
let mut alive = 0;
for cube in field {
for slice in &cube {
for row in slice {
for &cell in row {
if cell {
alive += 1;
}
}
}
}
}
alive
}
pub fn run(print: bool) -> Duration {
let input = std::fs::read_to_string("../inputs/17").unwrap();
let instant = Instant::now();
let mut field = vec![vec![vec![false; SIZE]; SIZE]; SIZE];
for (y, line) in input.lines().enumerate() {
for (x, cell) in line.chars().enumerate() {
field[OFFSET][y + OFFSET - 1][x + OFFSET - 1] = cell == '#';
}
let part1 = simulate(&input, 3);
let part2 = simulate(&input, 4);
if print {
dbg!(part1, part2);
}
// for y in 0..SIZE {
// for x in 0..SIZE {
// print!("{}", if field[OFFSET][y][x] { '#' } else { '.' });
// }
// println!();
// }
for i in 0..6 {
step(&mut field);
println!("step {}:", i + 1);
// for z in (OFFSET - 1)..=(OFFSET + 1) {
// println!("z = {}", z as i64 - OFFSET as i64);
// for y in 0..SIZE {
// for x in 0..SIZE {
// print!("{}", if field[z][y][x] { '#' } else { '.' });
// }
// println!();
// }
// println!();
// }
}
let mut alive = 0;
for slice in field {
for row in slice {
for cell in row {
if cell {
alive += 1;
}
}
}
}
dbg!(alive);
instant.elapsed()
}