Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions 2018/06a/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "advent-of-code-2018-06a"
edition.workspace = true
rust-version.workspace = true
description = "Solution to Advent of Code 2018, problem 06a"
authors.workspace = true
repository.workspace = true
license.workspace = true
keywords = ["taxicab-metric"]

[dependencies]
adventutil = { path = "../../adventutil" }

[lints]
workspace = true
181 changes: 181 additions & 0 deletions 2018/06a/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
use adventutil::Input;
use adventutil::counter::Counter;
use adventutil::gridgeom::{Point, PointBounds};

fn parse_point(s: &str) -> Point {
let (x, y) = s.split_once(',').unwrap();
let x = x.trim().parse::<i32>().unwrap();
let y = y.trim().parse::<i32>().unwrap();
Point { x, y }
}

fn solve(input: Input) -> u64 {
let coords = input.lines().map(|s| parse_point(&s)).collect::<Vec<_>>();
let mut bounds = PointBounds::for_points(coords.iter().copied()).unwrap();

'minx: loop {
let mut points_outside = Vec::new();
let mut points_inside = Vec::new();
for &p in &coords {
if bounds.contains(p) {
points_inside.push(p);
} else {
points_outside.push(p);
}
}
let x = bounds.min_x;
for y in bounds.min_y..=bounds.max_y {
let p = Point { x, y };
if let Some(closest_dist_outside) = points_outside
.iter()
.map(|&p2| (p - p2).taxicab_len())
.min()
{
let closest_dist_inside = points_inside
.iter()
.map(|&p2| (p - p2).taxicab_len())
.min()
.unwrap();
if closest_dist_inside < closest_dist_outside {
break 'minx;
}
}
}
bounds.min_x += 1;
}

'maxx: loop {
let mut points_outside = Vec::new();
let mut points_inside = Vec::new();
for &p in &coords {
if bounds.contains(p) {
points_inside.push(p);
} else {
points_outside.push(p);
}
}
let x = bounds.max_x;
for y in bounds.min_y..=bounds.max_y {
let p = Point { x, y };
if let Some(closest_dist_outside) = points_outside
.iter()
.map(|&p2| (p - p2).taxicab_len())
.min()
{
let closest_dist_inside = points_inside
.iter()
.map(|&p2| (p - p2).taxicab_len())
.min()
.unwrap();
if closest_dist_inside < closest_dist_outside {
break 'maxx;
}
}
}
bounds.max_x -= 1;
}

'miny: loop {
let mut points_outside = Vec::new();
let mut points_inside = Vec::new();
for &p in &coords {
if bounds.contains(p) {
points_inside.push(p);
} else {
points_outside.push(p);
}
}
let y = bounds.min_y;
for x in bounds.min_x..=bounds.max_x {
let p = Point { x, y };
if let Some(closest_dist_outside) = points_outside
.iter()
.map(|&p2| (p - p2).taxicab_len())
.min()
{
let closest_dist_inside = points_inside
.iter()
.map(|&p2| (p - p2).taxicab_len())
.min()
.unwrap();
if closest_dist_inside < closest_dist_outside {
break 'miny;
}
}
}
bounds.min_y += 1;
}

'maxy: loop {
let mut points_outside = Vec::new();
let mut points_inside = Vec::new();
for &p in &coords {
if bounds.contains(p) {
points_inside.push(p);
} else {
points_outside.push(p);
}
}
let y = bounds.max_y;
for x in bounds.min_x..=bounds.max_x {
let p = Point { x, y };
if let Some(closest_dist_outside) = points_outside
.iter()
.map(|&p2| (p - p2).taxicab_len())
.min()
{
let closest_dist_inside = points_inside
.iter()
.map(|&p2| (p - p2).taxicab_len())
.min()
.unwrap();
if closest_dist_inside < closest_dist_outside {
break 'maxy;
}
}
}
bounds.max_y -= 1;
}

let mut counter = Counter::new();
for y in bounds.min_y..=bounds.max_y {
for x in bounds.min_x..=bounds.max_x {
let p = Point { x, y };
let mut min_dist = None;
let mut nearest = Vec::new();
for &c in &coords {
let d = (p - c).taxicab_len();
if min_dist.is_none_or(|md| d < md) {
min_dist = Some(d);
nearest.clear();
nearest.push(c);
} else if min_dist == Some(d) {
nearest.push(c);
}
}
if nearest.len() == 1 {
counter.add(nearest.pop().unwrap());
}
}
}
counter
.into_iter()
.filter_map(|(c, qty)| bounds.contains(c).then_some(qty))
.max()
.unwrap()
}

fn main() {
println!("{}", solve(Input::from_env()));
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn example1() {
let input = Input::from("1, 1\n1, 6\n8, 3\n3, 4\n5, 5\n8, 9\n");
assert_eq!(solve(input), 17);
}
}
15 changes: 15 additions & 0 deletions 2018/06b/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "advent-of-code-2018-06b"
edition.workspace = true
rust-version.workspace = true
description = "Solution to Advent of Code 2018, problem 06b"
authors.workspace = true
repository.workspace = true
license.workspace = true
keywords = ["taxicab-metric"]

[dependencies]
adventutil = { path = "../../adventutil" }

[lints]
workspace = true
40 changes: 40 additions & 0 deletions 2018/06b/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use adventutil::Input;
use adventutil::gridgeom::{Point, PointBounds};

fn parse_point(s: &str) -> Point {
let (x, y) = s.split_once(',').unwrap();
let x = x.trim().parse::<i32>().unwrap();
let y = y.trim().parse::<i32>().unwrap();
Point { x, y }
}

fn solve(input: Input, max_sum: i32) -> usize {
let coords = input.lines().map(|s| parse_point(&s)).collect::<Vec<_>>();
let bounds = PointBounds::for_points(coords.iter().copied()).unwrap();
let mut qty = 0;
for y in bounds.min_y..=bounds.max_y {
for x in bounds.min_x..=bounds.max_x {
let p = Point { x, y };
let dist_sum: i32 = coords.iter().map(|&c| (p - c).taxicab_len()).sum();
if dist_sum < max_sum {
qty += 1;
}
}
}
qty
}

fn main() {
println!("{}", solve(Input::from_env(), 10000));
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn example1() {
let input = Input::from("1, 1\n1, 6\n8, 3\n3, 4\n5, 5\n8, 9\n");
assert_eq!(solve(input, 32), 16);
}
}
Binary file modified 2018/answers.csv
Binary file not shown.
Binary file added 2018/inputs/06.txt
Binary file not shown.
14 changes: 14 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.