make p2 linear time
This commit is contained in:
parent
8e36759477
commit
1338681cf4
|
@ -12,13 +12,23 @@ fn parse_input(raw: &str) -> Parsed {
|
|||
.collect()
|
||||
}
|
||||
|
||||
fn find_reflection(block: &[I], blacklist: Option<usize>) -> Option<usize> {
|
||||
fn find_reflection<const DEVIATIONS: u32>(block: &[I]) -> Option<usize> {
|
||||
'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<usize>) -> Option<usize> {
|
|||
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<I> {
|
||||
let max = orig.iter().max().unwrap();
|
||||
let len = (I::BITS - max.leading_zeros()) as usize;
|
||||
|
@ -47,31 +50,17 @@ fn transpose(orig: &[I]) -> Vec<I> {
|
|||
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: {
|
||||
|
|
Loading…
Reference in New Issue
Block a user