From 90e0a3060e9b300b008851d2f440e473545ef82b Mon Sep 17 00:00:00 2001 From: Sijmen Schoon Date: Wed, 23 Dec 2020 15:53:25 +0100 Subject: [PATCH] rust(day17): Optimize to run in 34 ms --- rust/Cargo.lock | 50 ---------------- rust/Cargo.toml | 1 - rust/src/day17.rs | 145 +++++++++++++++++++++++----------------------- 3 files changed, 73 insertions(+), 123 deletions(-) diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 3307b0f..45e6dbd 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -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", -] diff --git a/rust/Cargo.toml b/rust/Cargo.toml index fb6f99f..6bf9074 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -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" diff --git a/rust/src/day17.rs b/rust/src/day17.rs index eab4d68..5a36a4e 100644 --- a/rust/src/day17.rs +++ b/rust/src/day17.rs @@ -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>>; +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() }