1
0

Added optimized versions of day 15

This commit is contained in:
Ishan Jain 2022-12-15 22:24:57 +05:30
parent ab213c672a
commit f1ab5a68e4
Signed by: ishan
GPG Key ID: 0506DB2A1CC75C27
2 changed files with 110 additions and 104 deletions

View File

@ -4,9 +4,12 @@ use std::collections::HashSet;
extern crate test; extern crate test;
const INPUTS: [&str; 2] = [include_str!("./sample.txt"), include_str!("./input.txt")]; const INPUTS: [&[u8]; 2] = [
include_bytes!("./sample.txt"),
include_bytes!("./input.txt"),
];
#[derive(Debug)] #[derive(Copy, Clone, Debug, Ord, PartialEq, PartialOrd, Eq)]
struct Sensor { struct Sensor {
sx: i32, sx: i32,
sy: i32, sy: i32,
@ -14,77 +17,91 @@ struct Sensor {
by: i32, by: i32,
} }
fn parse(input: &str) -> Vec<Sensor> { fn parse(input: &[u8]) -> Vec<Sensor> {
input input
.lines() .split(|&c| c == b'\n')
.filter(|c| !c.is_empty()) .map(|line| {
.filter_map(|line| { let mut out = [0; 4];
line.split_once(':').map(|(sensor, beacon)| { let mut i = 0;
let (sx, sy) = sensor let mut num = 0;
.split_once(',') let mut is_neg = false;
.map(|(x, y)| {
let xneg = x.contains('-');
let yneg = y.contains('-');
let x = x
.bytes()
.filter(|c| (b'0'..=b'9').contains(c))
.fold(0, |a, x| (a * 10) + (x - b'0') as i32);
let y = y
.bytes()
.filter(|c| (b'0'..=b'9').contains(c))
.fold(0, |a, x| (a * 10) + (x - b'0') as i32);
(if xneg { -x } else { x }, if yneg { -y } else { y }) for c in line
}) .iter()
.unwrap(); .filter(|&c| (b'0'..=b'9').contains(c) || *c == b',' || *c == b'-' || *c == b':')
let (bx, by) = beacon {
.split_once(',') match c {
.map(|(x, y)| { b'-' => is_neg = true,
let xneg = x.contains('-'); b',' | b':' => {
let yneg = y.contains('-'); out[i] = if is_neg { -num } else { num };
let x = x
.bytes()
.filter(|c| (b'0'..=b'9').contains(c))
.fold(0, |a, x| (a * 10) + (x - b'0') as i32);
let y = y
.bytes()
.filter(|c| (b'0'..=b'9').contains(c))
.fold(0, |a, x| (a * 10) + (x - b'0') as i32);
(if xneg { -x } else { x }, if yneg { -y } else { y }) num = 0;
}) is_neg = false;
.unwrap(); i += 1;
Sensor { sx, sy, bx, by } }
}) v => num = num * 10 + (v - b'0') as i32,
}
}
out[i] = if is_neg { -num } else { num };
Sensor {
sx: out[0],
sy: out[1],
bx: out[2],
by: out[3],
}
}) })
.collect() .collect()
} }
fn solution(mut input: Vec<Sensor>, line: i32) -> usize { fn solution(input: Vec<Sensor>, line: i32) -> usize {
let mut beacons = HashSet::new(); let mut ranges = Vec::with_capacity(500);
let mut set = HashSet::new();
input.sort_unstable_by_key(|c| c.sx); let mut nranges: Vec<(i32, i32)> = input
.iter()
.filter_map(|sensor| {
let distance = (sensor.sx - sensor.bx).abs() + (sensor.sy - sensor.by).abs();
// Covered area reduces as it moves further away from the center
// The covered area at line will be the manhatten distance - (distance between sensor
// and line)
let dy = distance - (sensor.sy - line).abs();
for Sensor { sx, sy, bx, by } in input { if dy < 0 {
if by == line { None
beacons.insert(bx); } else {
Some((sensor.sx - dy, sensor.sx + dy))
} }
})
.collect();
let area = (bx - sx).abs() + (by - sy).abs(); nranges.sort_unstable();
for ix in sx - area..=sx + area {
if inside((sx, sy), (ix, line)) <= area { for (start, end) in nranges {
set.insert(ix); if let Some((_, le)) = ranges.last_mut() {
}; if start <= *le {
// If ranges overlap, Edit the last range to extend till the limit of last range or
// the current range
*le = std::cmp::max(*le, end);
} else {
ranges.push((start, end));
}
} else {
ranges.push((start, end));
} }
} }
set.len() - beacons.len() let mut answer = 0;
} for (s, e) in ranges {
answer += (e - s + 1) as usize;
}
#[inline] answer
const fn inside((sx, sy): (i32, i32), (px, py): (i32, i32)) -> i32 { - input
(sx - px).abs() + (sy - py).abs() .into_iter()
.filter(|x| x.by == line)
.map(|x| x.bx)
.collect::<HashSet<i32>>()
.len()
} }
fn main() { fn main() {

View File

@ -1,7 +1,10 @@
#![feature(test)] #![feature(test)]
extern crate test; extern crate test;
const INPUTS: [&str; 2] = [include_str!("./sample.txt"), include_str!("./input.txt")]; const INPUTS: [&[u8]; 2] = [
include_bytes!("./sample.txt"),
include_bytes!("./input.txt"),
];
#[derive(Debug)] #[derive(Debug)]
struct Sensor { struct Sensor {
@ -11,52 +14,38 @@ struct Sensor {
area: i64, area: i64,
} }
fn parse(input: &str) -> Vec<Sensor> { fn parse(input: &[u8]) -> Vec<Sensor> {
input input
.lines() .split(|&c| c == b'\n')
.filter(|c| !c.is_empty()) .map(|line| {
.filter_map(|line| { let mut out = [0; 4];
line.split_once(':').map(|(sensor, beacon)| { let mut i = 0;
let (sx, sy) = sensor let mut num = 0;
.split_once(',') let mut is_neg = false;
.map(|(x, y)| {
let xneg = x.contains('-');
let yneg = y.contains('-');
let x = x
.bytes()
.filter(|c| (b'0'..=b'9').contains(c))
.fold(0, |a, x| (a * 10) + (x - b'0') as i64);
let y = y
.bytes()
.filter(|c| (b'0'..=b'9').contains(c))
.fold(0, |a, x| (a * 10) + (x - b'0') as i64);
(if xneg { -x } else { x }, if yneg { -y } else { y }) for c in line
}) .iter()
.unwrap(); .filter(|&c| (b'0'..=b'9').contains(c) || *c == b',' || *c == b'-' || *c == b':')
let (bx, by) = beacon {
.split_once(',') match c {
.map(|(x, y)| { b'-' => is_neg = true,
let xneg = x.contains('-'); b',' | b':' => {
let yneg = y.contains('-'); out[i] = if is_neg { -num } else { num };
let x = x
.bytes()
.filter(|c| (b'0'..=b'9').contains(c))
.fold(0, |a, x| (a * 10) + (x - b'0') as i64);
let y = y
.bytes()
.filter(|c| (b'0'..=b'9').contains(c))
.fold(0, |a, x| (a * 10) + (x - b'0') as i64);
(if xneg { -x } else { x }, if yneg { -y } else { y }) num = 0;
}) is_neg = false;
.unwrap(); i += 1;
Sensor { }
sx, v => num = num * 10 + (v - b'0') as i64,
sy, }
area: (sx - bx).abs() + (sy - by).abs(), }
out[i] = if is_neg { -num } else { num };
Sensor {
sx: out[0],
sy: out[1],
area: (out[0] - out[2]).abs() + (out[1] - out[3]).abs(),
} }
})
}) })
.collect() .collect()
} }
@ -68,8 +57,8 @@ fn solution(input: Vec<Sensor>, line: i64) -> i64 {
'out: while i <= line { 'out: while i <= line {
for beacon in input.iter() { for beacon in input.iter() {
if inside((beacon.sx, beacon.sy), (i, j)) <= beacon.area { if inside((beacon.sx, beacon.sy), (i, j)) <= beacon.area {
let dy = (j - beacon.sy).abs(); let vgap = (j - beacon.sy).abs();
let dx = (beacon.sx - i) + (beacon.area - dy) + 1; let dx = (beacon.sx - i) + (beacon.area - vgap) + 1;
i += dx; i += dx;
continue 'out; continue 'out;