2022 rust day 15 part 1

This commit is contained in:
Maciej Jur 2022-12-15 14:27:29 +01:00
parent 5aa8c83a30
commit f85f9ae14a
2 changed files with 52 additions and 36 deletions

View file

@ -1,26 +1,25 @@
use std::collections::HashMap; use std::collections::{HashMap, HashSet};
use regex::Regex; use regex::{CaptureMatches, Regex};
use crate::utils; use crate::utils;
use crate::utils::matrix::Matrix;
pub fn run() -> () { pub fn run() -> () {
let data = parse_data(&utils::read_lines(utils::Source::Day(15))); let data = parse_data(&utils::read_lines(utils::Source::Day(15)));
println!("Day 15"); println!("Day 15");
println!("Part 1: {}", solve1(&data)); println!("Part 1: {}", solve1(&data, 2000000));
println!("Part 2: {}", solve2(&data)); println!("Part 2: {}", solve2(&data));
} }
type Data = [((usize, usize), (isize, isize))]; type Data = [((isize, isize), (isize, isize))];
fn distance(a: (usize, usize), b: (isize, isize)) -> usize { fn distance(a: (isize, isize), b: (isize, isize)) -> usize {
(a.0 as isize).abs_diff(b.0) + (a.1 as isize).abs_diff(b.1) a.0.abs_diff(b.0) + a.1.abs_diff(b.1)
} }
fn find_ranges(data: &Data) -> HashMap<(usize, usize), usize> { fn find_ranges(data: &Data) -> HashMap<(isize, isize), usize> {
data.iter() data.iter()
.map(|&(sensor, beacon)| .map(|&(sensor, beacon)|
(sensor, distance(sensor, beacon)) (sensor, distance(sensor, beacon))
@ -29,49 +28,67 @@ fn find_ranges(data: &Data) -> HashMap<(usize, usize), usize> {
} }
fn find_bounds(data: &Data) -> (usize, usize) { fn find_bounds(data: &Data) -> (isize, isize) {
data.iter() data.iter()
.fold((0, 0), |acc, &(sensor, beacon)| { .fold((0, 0), |acc, &(sensor, beacon)| {
( (
acc.0.max(sensor.0.max(beacon.0.max(0) as usize)), acc.0.max(sensor.0.max(beacon.0)),
acc.1.max(sensor.0.max(beacon.1.max(0) as usize)), acc.1.max(sensor.0.max(beacon.1)),
) )
}) })
} }
fn solve1(data: &Data) -> usize { fn solve1(data: &Data, row: isize) -> usize {
let ranges = find_ranges(data); let ranges = find_ranges(data);
let (rows, cols) = find_bounds(data); let (_, cols) = find_bounds(data);
let max_range = *ranges.values().max().unwrap(); let max_range = *ranges.values().max().unwrap();
1 let buffer = (2 * max_range + 1) as isize;
let occupied = data.iter()
.fold(HashSet::new(), |mut acc, (a, b)| {
acc.insert(a);
acc.insert(b);
acc
});
let mut count = 0;
for col in (0 - buffer)..(cols + buffer) {
let index = (row, col);
if occupied.contains(&index) {
continue;
} }
fn solve2(data: &Data) -> i32 { let in_range = ranges.iter()
.any(|(&sensor, &max_dist)|
sensor != index && distance(sensor, index) <= max_dist
);
if in_range { count += 1; }
}
count
}
fn solve2(_data: &Data) -> i32 {
2 2
} }
fn parse_data<T: AsRef<str>>(data: &[T]) -> Vec<((usize, usize), (isize, isize))> { fn extract_coord(iter: &mut CaptureMatches) -> (isize, isize) {
let re = Regex::new(r#"x=(-?\d+), y=(-?\d+)"#).unwrap(); iter.next()
data.iter()
.map(|line| {
let mut iter = re.captures_iter(line.as_ref());
let sensor = iter.next()
.map(|c| {
let mut cap = c.iter();
let x = cap.nth(1).unwrap().unwrap().as_str().parse::<usize>().unwrap();
let y = cap.next().unwrap().unwrap().as_str().parse::<usize>().unwrap();
(y, x)
})
.unwrap();
let beacon = iter.next()
.map(|c| { .map(|c| {
let mut cap = c.iter(); let mut cap = c.iter();
let x = cap.nth(1).unwrap().unwrap().as_str().parse::<isize>().unwrap(); let x = cap.nth(1).unwrap().unwrap().as_str().parse::<isize>().unwrap();
let y = cap.next().unwrap().unwrap().as_str().parse::<isize>().unwrap(); let y = cap.next().unwrap().unwrap().as_str().parse::<isize>().unwrap();
(y, x) (y, x)
}) })
.unwrap(); .unwrap()
}
fn parse_data<T: AsRef<str>>(data: &[T]) -> Vec<((isize, isize), (isize, isize))> {
let re = Regex::new(r#"x=(-?\d+), y=(-?\d+)"#).unwrap();
data.iter()
.map(|line| {
let mut iter = re.captures_iter(line.as_ref());
let sensor = extract_coord(&mut iter);
let beacon = extract_coord(&mut iter);
(sensor, beacon) (sensor, beacon)
}) })
.collect() .collect()
@ -101,12 +118,12 @@ mod tests {
#[test] #[test]
fn part1() { fn part1() {
assert_eq!(26, solve1(&parse_data(DATA))); assert_eq!(26, solve1(&parse_data(DATA), 10));
} }
#[test] #[test]
fn part2() { fn part2() {
let data = parse_data(DATA); let data = parse_data(DATA);
assert_eq!(2, solve2(&data)); assert_eq!(56000011, solve2(&data));
} }
} }

View file

@ -1,7 +1,6 @@
#![allow(dead_code)] #![allow(dead_code)]
use std::fmt; use std::fmt;
use std::ops::{Index, IndexMut}; use std::ops::{Index, IndexMut};
use std::ptr::write;
use std::slice::{ChunksExact, Iter}; use std::slice::{ChunksExact, Iter};
@ -195,7 +194,7 @@ impl<'a, T> TranslatedViewMut<'a, T> {
pub fn slice_row(&self, row: isize) -> &[T] { pub fn slice_row(&self, row: isize) -> &[T] {
let row = row - self.tl_row; let row = row - self.tl_row;
self.slice_row(row) self.matrix.slice_row(row as usize)
} }
pub fn get_tl(&self) -> (isize, isize) { pub fn get_tl(&self) -> (isize, isize) {