my solutions to advent of code
aoc advent-of-code

day 18 2015 rust without if check

aylac.top cd0edfa9 2f792f59

verified
Changed files
+30 -25
2015
18
rust
src
+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();