diff --git a/2023/src/bin/day13.rs b/2023/src/bin/day13.rs index 0459120..90e4420 100644 --- a/2023/src/bin/day13.rs +++ b/2023/src/bin/day13.rs @@ -3,13 +3,16 @@ extern crate test; use aoc2023::{boilerplate, common::*}; const DAY: usize = 13; -type Parsed = Vec>>; +type Parsed = Vec>; +type I = u32; fn parse_input(raw: &str) -> Parsed { - raw.split("\n\n").map(|block| block.lines().map(|l| l.bytes().map(|b| b == b'#').collect()).collect()).collect() + raw.split("\n\n") + .map(|block| block.lines().map(|l| l.bytes().map(|b| b == b'#').fold(0, |acc, n| (acc << 1) | n as I)).collect()) + .collect() } -fn find_reflection(block: &[Vec], blacklist: Option) -> Option { +fn find_reflection(block: &[I], blacklist: Option) -> Option { 'outer: for i in 0..block.len() - 1 { let mut offset = 0; loop { @@ -30,12 +33,15 @@ fn part1(blocks: &Parsed) -> usize { .sum() } -fn transpose(orig: &[Vec]) -> Vec> { - let mut out = vec![vec![false; orig.len()]; orig[0].len()]; - for i in 0..orig.len() { - #[allow(clippy::needless_range_loop)] - for j in 0..orig[0].len() { - out[j][i] = orig[i][j]; +fn transpose(orig: &[I]) -> Vec { + let max = orig.iter().max().unwrap(); + let len = (I::BITS - max.leading_zeros()) as usize; + let mut out = vec![0; len]; + for j in 0..len { + for (i, &value) in orig.iter().enumerate() { + if (value & (1 << j)) != 0 { + out[len - 1 - j] |= 1 << (orig.len() - 1) >> i; + } } } out @@ -49,17 +55,19 @@ fn part2(blocks: &Parsed) -> usize { let mut transposed = transpose(&block); let p1 = find_reflection(&block, None).map(|n| n - 1); let p1_transposed = find_reflection(&transposed, None).map(|n| n - 1); + let max = block.iter().max().unwrap(); + let len = (I::BITS - max.leading_zeros()) as usize; for i in 0..block.len() { - for j in 0..block[0].len() { - block[i][j] ^= true; - transposed[j][i] ^= true; + for j in 0..len { + block[i] ^= 1 << j; + transposed[j] ^= 1 << i; if let Some(reflection) = find_reflection(&block, p1).map(|n| n * 100).or_else(|| find_reflection(&transposed, p1_transposed)) { return reflection; } - block[i][j] ^= true; - transposed[j][i] ^= true; + block[i] ^= 1 << j; + transposed[j] ^= 1 << i; } } unreachable!() @@ -94,7 +102,24 @@ boilerplate! { TEST_INPUT_VERTICAL => 300, }, }, + unittests: { + transpose: { + &[ + 0b100, + 0b010, + ] => TRANSPOSE_42, + &[ + 0b101, + 0b010, + ] => TRANSPOSE_52, + }, + }, bench1 == 37561, bench2 == 31108, bench_parse: Vec::len => 100, } + +#[cfg(test)] +const TRANSPOSE_52: &[I] = &[0b10, 0b01, 0b10]; +#[cfg(test)] +const TRANSPOSE_42: &[I] = &[0b10, 0b01, 0b00];