Added optimized versions of day 15
This commit is contained in:
parent
ab213c672a
commit
f1ab5a68e4
131
src/day15/1.rs
131
src/day15/1.rs
|
@ -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() {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user