From 1338681cf48e11f34fb73cba25b20ab74dffc713 Mon Sep 17 00:00:00 2001 From: kageru Date: Wed, 13 Dec 2023 12:30:51 +0100 Subject: [PATCH] make p2 linear time --- 2023/src/bin/day13.rs | 77 ++++++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 34 deletions(-) diff --git a/2023/src/bin/day13.rs b/2023/src/bin/day13.rs index 90e4420..a74cac9 100644 --- a/2023/src/bin/day13.rs +++ b/2023/src/bin/day13.rs @@ -12,13 +12,23 @@ fn parse_input(raw: &str) -> Parsed { .collect() } -fn find_reflection(block: &[I], blacklist: Option) -> Option { +fn find_reflection(block: &[I]) -> Option { 'outer: for i in 0..block.len() - 1 { let mut offset = 0; + let mut deviations = DEVIATIONS; loop { - match try { (block.get(i.checked_sub(offset)?)?, block.get(i + 1 + offset)?) } { - None if Some(i) != blacklist => return Some(i + 1), - Some((a, b)) if a == b => offset += 1, + match try { block.get(i.checked_sub(offset)?)? ^ block.get(i + 1 + offset)? } { + None if deviations == 0 => return Some(i + 1), + Some(0) => offset += 1, + Some(diff) => { + let diff = diff.count_ones(); + if diff > deviations { + continue 'outer; + } else { + offset += 1; + deviations -= diff; + } + } _ => continue 'outer, } } @@ -26,13 +36,6 @@ fn find_reflection(block: &[I], blacklist: Option) -> Option { None } -fn part1(blocks: &Parsed) -> usize { - blocks - .iter() - .map(|block| find_reflection(block, None).map(|n| n * 100).or_else(|| find_reflection(&transpose(block), None)).unwrap()) - .sum() -} - fn transpose(orig: &[I]) -> Vec { let max = orig.iter().max().unwrap(); let len = (I::BITS - max.leading_zeros()) as usize; @@ -47,31 +50,17 @@ fn transpose(orig: &[I]) -> Vec { out } +fn part1(blocks: &Parsed) -> usize { + blocks + .iter() + .map(|block| find_reflection::<0>(block).map(|n| n * 100).or_else(|| find_reflection::<0>(&transpose(block))).unwrap()) + .sum() +} + fn part2(blocks: &Parsed) -> usize { blocks .iter() - .map(|block| { - let mut block = block.to_owned(); - 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..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] ^= 1 << j; - transposed[j] ^= 1 << i; - } - } - unreachable!() - }) + .map(|block| find_reflection::<1>(&block).map(|n| n * 100).or_else(|| find_reflection::<1>(&transpose(&block))).unwrap()) .sum() } @@ -91,15 +80,35 @@ boilerplate! { ##......# ..#.##.#. ..##..##. -#.#.##.#." +#.#.##.#.", + TEST_INPUT_475 == "\ +#..##.... +.#.##.... +##....##. +#.#.#.##. +.####.##. +###..#..# +#.#.#.##. +.#.#.#### +..#.#.##. +.##..#### +#####.##. +.#.#.#### +.#...#### +.#.#.#### +.#.#.#### +#####.##. +.##..####" for tests: { part1: { TEST_INPUT_HORIZONTAL => 400, TEST_INPUT_VERTICAL => 5, + TEST_INPUT_475 => 7, }, part2: { TEST_INPUT_HORIZONTAL => 100, TEST_INPUT_VERTICAL => 300, + TEST_INPUT_475 => 1300, }, }, unittests: {