cargo fmt

main
Usmann Khan 2022-12-16 23:55:32 +00:00
parent 224ed7e7c4
commit 4fd8a76698
1 changed files with 126 additions and 74 deletions

View File

@ -1,20 +1,20 @@
use std::collections::HashMap;
use std::thread;
use std::ops::RangeInclusive;
use std::panic;
use std::str;
use std::cmp; use std::cmp;
use std::ops::Sub; use std::collections::HashMap;
use std::ops::{Deref};
use std::fs;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::fs;
use std::ops::Deref;
use std::ops::RangeInclusive;
use std::ops::Sub;
use std::panic;
use std::process; use std::process;
use std::str;
use std::sync::Arc; use std::sync::Arc;
use std::thread;
#[derive(Default,Debug,PartialEq)] #[derive(Default, Debug, PartialEq)]
struct Location { struct Location {
x: isize, x: isize,
y: isize y: isize,
} }
impl<'a> Sub for &'a Location { impl<'a> Sub for &'a Location {
type Output = isize; type Output = isize;
@ -23,29 +23,29 @@ impl<'a> Sub for &'a Location {
(self.x - other.x).abs() + (self.y - other.y).abs() (self.x - other.x).abs() + (self.y - other.y).abs()
} }
} }
#[derive(Default,PartialEq)] #[derive(Default, PartialEq)]
struct Sensor { struct Sensor {
loc: Location, loc: Location,
visibility: usize, visibility: usize,
} }
#[derive(Default,Debug,PartialEq)] #[derive(Default, Debug, PartialEq)]
struct Beacon { struct Beacon {
loc: Location loc: Location,
} }
struct ComparableRange(RangeInclusive<isize>); struct ComparableRange(RangeInclusive<isize>);
impl ComparableRange { impl ComparableRange {
pub fn intersects(&self, other:&ComparableRange) -> bool { pub fn intersects(&self, other: &ComparableRange) -> bool {
self.contains(other.start()) || self.contains(other.start()) || other.contains(self.start())
other.contains(self.start())
} }
pub fn intersection(&self, other:&ComparableRange) -> ComparableRange { pub fn intersection(&self, other: &ComparableRange) -> ComparableRange {
match self.intersects(other) { match self.intersects(other) {
false => panic!("Ranges do not intersect"), false => panic!("Ranges do not intersect"),
true => ComparableRange(cmp::min(*self.start(), *other.start())..=cmp::max(*self.end(),*other.end())) true => ComparableRange(
cmp::min(*self.start(), *other.start())..=cmp::max(*self.end(), *other.end()),
),
} }
} }
} }
@ -58,8 +58,8 @@ impl Deref for ComparableRange {
} }
} }
const PART_1_CONST:isize = 2000000; const PART_1_CONST: isize = 2000000;
const PART_2_CONST:isize = 4000000; const PART_2_CONST: isize = 4000000;
fn main() { fn main() {
run(); run();
@ -71,7 +71,10 @@ fn run() {
process_part_2(contents.lines()); process_part_2(contents.lines());
} }
fn process_part_2<'a, T>(lines: T) where T: IntoIterator<Item = &'a str> { fn process_part_2<'a, T>(lines: T)
where
T: IntoIterator<Item = &'a str>,
{
let (sensors, worker_bundles) = prep_work(lines); let (sensors, worker_bundles) = prep_work(lines);
let mut handles = Vec::new(); let mut handles = Vec::new();
@ -81,13 +84,18 @@ fn process_part_2<'a, T>(lines: T) where T: IntoIterator<Item = &'a str> {
let worker_bundles = Arc::clone(&bundle_storage); let worker_bundles = Arc::clone(&bundle_storage);
let sensors = Arc::clone(&sensor_storage); let sensors = Arc::clone(&sensor_storage);
let bounds = 0..=PART_2_CONST; let bounds = 0..=PART_2_CONST;
let handle = thread::spawn(move || {do_part2_work(worker_bundles, worker, &bounds, sensors)} ); let handle = thread::spawn(move || do_part2_work(worker_bundles, worker, &bounds, sensors));
handles.push(handle); handles.push(handle);
} }
handles.into_iter().for_each(|handle|{ handle.join();}); handles.into_iter().for_each(|handle| {
handle.join();
});
} }
fn prep_work<'a, T>(lines: T) -> (Vec<Sensor>, HashMap<isize, Vec<usize>>) where T: IntoIterator<Item = &'a str> { fn prep_work<'a, T>(lines: T) -> (Vec<Sensor>, HashMap<isize, Vec<usize>>)
where
T: IntoIterator<Item = &'a str>,
{
let (sensors, _) = parse(lines); let (sensors, _) = parse(lines);
let mut worker_bundles = HashMap::new(); let mut worker_bundles = HashMap::new();
for worker in 0..99 { for worker in 0..99 {
@ -97,38 +105,56 @@ fn prep_work<'a, T>(lines: T) -> (Vec<Sensor>, HashMap<isize, Vec<usize>>) where
work_item.push(chunk_s); work_item.push(chunk_s);
} }
worker_bundles.insert(worker, work_item); worker_bundles.insert(worker, work_item);
}; }
// remainder worker // remainder worker
let worker = 99; let worker = 99;
let mut work_item = Vec::new(); let mut work_item = Vec::new();
for sensor in &sensors { for sensor in &sensors {
let chunk_s = sensor.visibility / 100; let chunk_s = sensor.visibility / 100;
let remainder = sensor.visibility - (99*chunk_s); let remainder = sensor.visibility - (99 * chunk_s);
work_item.push(remainder); work_item.push(remainder);
} }
worker_bundles.insert(worker, work_item); worker_bundles.insert(worker, work_item);
(sensors, worker_bundles) (sensors, worker_bundles)
} }
fn do_part2_work(worker_bundles: Arc<HashMap<isize, Vec<usize>>>, worker: isize, bounds: &RangeInclusive<isize>, sensors: Arc<Vec<Sensor>>) { fn do_part2_work(
worker_bundles.get(&worker).and_then( worker_bundles: Arc<HashMap<isize, Vec<usize>>>,
|x| { worker: isize,
bounds: &RangeInclusive<isize>,
sensors: Arc<Vec<Sensor>>,
) {
worker_bundles.get(&worker).and_then(|x| {
for (work_idx, work_item) in x.into_iter().enumerate() { for (work_idx, work_item) in x.into_iter().enumerate() {
for idx in 0..*work_item { for idx in 0..*work_item {
let dist = isize::try_from(idx).unwrap() + worker*isize::try_from(*work_item).unwrap(); let dist =
isize::try_from(idx).unwrap() + worker * isize::try_from(*work_item).unwrap();
let sensor = &sensors[work_idx]; let sensor = &sensors[work_idx];
let visibility = isize::try_from(sensor.visibility).unwrap(); let visibility = isize::try_from(sensor.visibility).unwrap();
let x_left = sensor.loc.x-dist; let x_left = sensor.loc.x - dist;
let x_right = sensor.loc.x+dist; let x_right = sensor.loc.x + dist;
let y_lower = sensor.loc.y + (visibility-dist) + 1; let y_lower = sensor.loc.y + (visibility - dist) + 1;
let y_upper = sensor.loc.y - (visibility-dist) - 1; let y_upper = sensor.loc.y - (visibility - dist) - 1;
[(x_left, y_upper), (x_right, y_upper), (x_left, y_lower), (x_right, y_lower)].into_iter().for_each(|coord| { [
if !(bounds).contains(&coord.0) || !(bounds).contains(&coord.1) { return } (x_left, y_upper),
if (sensors).iter().all(|tgt_sensor| { (x_right, y_upper),
&tgt_sensor.loc - &Location{x:coord.0, y:coord.1} > isize::try_from(tgt_sensor.visibility).unwrap() (x_left, y_lower),
(x_right, y_lower),
]
.into_iter()
.for_each(|coord| {
if !(bounds).contains(&coord.0) || !(bounds).contains(&coord.1) {
return;
}
if sensors.iter().all(|tgt_sensor| {
&tgt_sensor.loc
- &Location {
x: coord.0,
y: coord.1,
}
> isize::try_from(tgt_sensor.visibility).unwrap()
}) { }) {
println!("{:?}", coord.0*4000000+coord.1); println!("{:?}", coord.0 * 4000000 + coord.1);
process::exit(0); process::exit(0);
} }
}) })
@ -138,40 +164,61 @@ fn do_part2_work(worker_bundles: Arc<HashMap<isize, Vec<usize>>>, worker: isize,
}); });
} }
fn process_part_1<'a, T>(lines: T) where T: IntoIterator<Item = &'a str> { fn process_part_1<'a, T>(lines: T)
where
T: IntoIterator<Item = &'a str>,
{
let (sensors, beacons) = parse(lines); let (sensors, beacons) = parse(lines);
let target_row = PART_1_CONST; let target_row = PART_1_CONST;
let mut impossible_ranges:Vec<ComparableRange> = Vec::new(); let mut impossible_ranges: Vec<ComparableRange> = Vec::new();
for sensor in (&sensors).into_iter() { for sensor in (&sensors).into_iter() {
let visibility = isize::try_from(sensor.visibility).unwrap(); let visibility = isize::try_from(sensor.visibility).unwrap();
let dist_to_target = &sensor.loc - &(Location {x:sensor.loc.x, y:target_row}); let dist_to_target = &sensor.loc
if dist_to_target > visibility { continue } - &(Location {
x: sensor.loc.x,
y: target_row,
});
if dist_to_target > visibility {
continue;
}
let impossible_width = visibility - dist_to_target; let impossible_width = visibility - dist_to_target;
let impossible_range = sensor.loc.x-impossible_width..=sensor.loc.x+impossible_width; let impossible_range = sensor.loc.x - impossible_width..=sensor.loc.x + impossible_width;
impossible_ranges.push(ComparableRange(impossible_range)); impossible_ranges.push(ComparableRange(impossible_range));
}; }
impossible_ranges.sort_by(|a,b| a.start().cmp(b.start())); impossible_ranges.sort_by(|a, b| a.start().cmp(b.start()));
merge(&mut impossible_ranges); merge(&mut impossible_ranges);
let beacons_in_row = beacons.into_iter().filter(|b| { let beacons_in_row = beacons
.into_iter()
.filter(|b| {
if b.loc.y != target_row { if b.loc.y != target_row {
return false return false;
} }
(&impossible_ranges).into_iter().any(|r| r.contains(&b.loc.x)) (&impossible_ranges)
}).count(); .into_iter()
println!("{}", impossible_ranges.into_iter().map(|r| r.end()-r.start()+1).sum::<isize>()-isize::try_from(beacons_in_row).unwrap()); .any(|r| r.contains(&b.loc.x))
})
.count();
println!(
"{}",
impossible_ranges
.into_iter()
.map(|r| r.end() - r.start() + 1)
.sum::<isize>()
- isize::try_from(beacons_in_row).unwrap()
);
} }
fn merge(impossible_ranges: &mut Vec<ComparableRange>) { fn merge(impossible_ranges: &mut Vec<ComparableRange>) {
let mut merge_idx = 0; let mut merge_idx = 0;
while merge_idx < impossible_ranges.len()-1 { while merge_idx < impossible_ranges.len() - 1 {
if (*impossible_ranges)[merge_idx].intersects(&impossible_ranges[merge_idx+1]) { if (*impossible_ranges)[merge_idx].intersects(&impossible_ranges[merge_idx + 1]) {
let r1 = &impossible_ranges[merge_idx]; let r1 = &impossible_ranges[merge_idx];
let r2 = &impossible_ranges[merge_idx+1]; let r2 = &impossible_ranges[merge_idx + 1];
impossible_ranges.insert(merge_idx+2,r1.intersection(&r2)); impossible_ranges.insert(merge_idx + 2, r1.intersection(&r2));
impossible_ranges.remove(merge_idx+1); impossible_ranges.remove(merge_idx + 1);
impossible_ranges.remove(merge_idx); impossible_ranges.remove(merge_idx);
} else { } else {
merge_idx += 1; merge_idx += 1;
@ -180,27 +227,32 @@ fn merge(impossible_ranges: &mut Vec<ComparableRange>) {
} }
fn parse<'a, T>(lines: T) -> (Vec<Sensor>, Vec<Beacon>) fn parse<'a, T>(lines: T) -> (Vec<Sensor>, Vec<Beacon>)
where T: IntoIterator<Item = &'a str> { where
T: IntoIterator<Item = &'a str>,
{
let mut sensors = Vec::new(); let mut sensors = Vec::new();
let mut beacons = Vec::new(); let mut beacons = Vec::new();
let extract_ints = |s: &str| { let extract_ints = |s: &str| {
s s.split(&['=', ',', ':'][..])
.split(&['=',',',':'][..])
.filter_map(|s| s.parse::<isize>().ok()) .filter_map(|s| s.parse::<isize>().ok())
.collect::<Vec<isize>>() .collect::<Vec<isize>>()
}; };
let loc_sets = lines.into_iter().map(extract_ints); let loc_sets = lines.into_iter().map(extract_ints);
loc_sets.for_each(|loc_set| { loc_sets.for_each(|loc_set| {
let sensor_loc = Location {x:loc_set[0], y:loc_set[1]}; let sensor_loc = Location {
let beacon_loc = Location {x:loc_set[2], y:loc_set[3]}; x: loc_set[0],
let visibility = usize::try_from(&sensor_loc-&beacon_loc).unwrap(); y: loc_set[1],
sensors.push(Sensor{
loc: sensor_loc,
visibility: visibility
});
let beacon = Beacon{
loc: beacon_loc
}; };
let beacon_loc = Location {
x: loc_set[2],
y: loc_set[3],
};
let visibility = usize::try_from(&sensor_loc - &beacon_loc).unwrap();
sensors.push(Sensor {
loc: sensor_loc,
visibility: visibility,
});
let beacon = Beacon { loc: beacon_loc };
if !beacons.contains(&beacon) { if !beacons.contains(&beacon) {
beacons.push(beacon); beacons.push(beacon);
} }