make p2 linear time
This commit is contained in:
parent
8e36759477
commit
1338681cf4
@ -12,13 +12,23 @@ fn parse_input(raw: &str) -> Parsed {
|
|||||||
.collect()
|
.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 {
|
'outer: for i in 0..block.len() - 1 {
|
||||||
let mut offset = 0;
|
let mut offset = 0;
|
||||||
|
let mut deviations = DEVIATIONS;
|
||||||
loop {
|
loop {
|
||||||
match try { (block.get(i.checked_sub(offset)?)?, block.get(i + 1 + offset)?) } {
|
match try { block.get(i.checked_sub(offset)?)? ^ block.get(i + 1 + offset)? } {
|
||||||
None if Some(i) != blacklist => return Some(i + 1),
|
None if deviations == 0 => return Some(i + 1),
|
||||||
Some((a, b)) if a == b => offset += 1,
|
Some(0) => offset += 1,
|
||||||
|
Some(diff) => {
|
||||||
|
let diff = diff.count_ones();
|
||||||
|
if diff > deviations {
|
||||||
|
continue 'outer;
|
||||||
|
} else {
|
||||||
|
offset += 1;
|
||||||
|
deviations -= diff;
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => continue 'outer,
|
_ => continue 'outer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -26,13 +36,6 @@ fn find_reflection(block: &[I], blacklist: Option<usize>) -> Option<usize> {
|
|||||||
None
|
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> {
|
fn transpose(orig: &[I]) -> Vec<I> {
|
||||||
let max = orig.iter().max().unwrap();
|
let max = orig.iter().max().unwrap();
|
||||||
let len = (I::BITS - max.leading_zeros()) as usize;
|
let len = (I::BITS - max.leading_zeros()) as usize;
|
||||||
@ -47,31 +50,17 @@ fn transpose(orig: &[I]) -> Vec<I> {
|
|||||||
out
|
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 {
|
fn part2(blocks: &Parsed) -> usize {
|
||||||
blocks
|
blocks
|
||||||
.iter()
|
.iter()
|
||||||
.map(|block| {
|
.map(|block| find_reflection::<1>(&block).map(|n| n * 100).or_else(|| find_reflection::<1>(&transpose(&block))).unwrap())
|
||||||
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!()
|
|
||||||
})
|
|
||||||
.sum()
|
.sum()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,15 +80,35 @@ boilerplate! {
|
|||||||
##......#
|
##......#
|
||||||
..#.##.#.
|
..#.##.#.
|
||||||
..##..##.
|
..##..##.
|
||||||
#.#.##.#."
|
#.#.##.#.",
|
||||||
|
TEST_INPUT_475 == "\
|
||||||
|
#..##....
|
||||||
|
.#.##....
|
||||||
|
##....##.
|
||||||
|
#.#.#.##.
|
||||||
|
.####.##.
|
||||||
|
###..#..#
|
||||||
|
#.#.#.##.
|
||||||
|
.#.#.####
|
||||||
|
..#.#.##.
|
||||||
|
.##..####
|
||||||
|
#####.##.
|
||||||
|
.#.#.####
|
||||||
|
.#...####
|
||||||
|
.#.#.####
|
||||||
|
.#.#.####
|
||||||
|
#####.##.
|
||||||
|
.##..####"
|
||||||
for tests: {
|
for tests: {
|
||||||
part1: {
|
part1: {
|
||||||
TEST_INPUT_HORIZONTAL => 400,
|
TEST_INPUT_HORIZONTAL => 400,
|
||||||
TEST_INPUT_VERTICAL => 5,
|
TEST_INPUT_VERTICAL => 5,
|
||||||
|
TEST_INPUT_475 => 7,
|
||||||
},
|
},
|
||||||
part2: {
|
part2: {
|
||||||
TEST_INPUT_HORIZONTAL => 100,
|
TEST_INPUT_HORIZONTAL => 100,
|
||||||
TEST_INPUT_VERTICAL => 300,
|
TEST_INPUT_VERTICAL => 300,
|
||||||
|
TEST_INPUT_475 => 1300,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
unittests: {
|
unittests: {
|
||||||
|
Loading…
Reference in New Issue
Block a user