make it a bitmask

This commit is contained in:
kageru 2023-12-13 12:08:26 +01:00
parent 22cf7c40b1
commit 8e36759477

View File

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