mirror of
https://github.com/wezm/advent-of-code.git
synced 2024-12-18 10:19:55 +00:00
Add day 6 2018 part 1 solution
This commit is contained in:
parent
79a0c3c76b
commit
7b04f00291
2 changed files with 126 additions and 10 deletions
|
@ -2,6 +2,7 @@
|
|||
name = "advent-of-code"
|
||||
version = "0.1.0"
|
||||
authors = ["Wesley Moore <wes@wezm.net>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
chrono = "0.4.6"
|
||||
|
|
|
@ -2,12 +2,112 @@
|
|||
extern crate lazy_static;
|
||||
extern crate regex;
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fs;
|
||||
|
||||
use regex::Regex;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Coordinate(i32, i32);
|
||||
struct Coordinate {
|
||||
x: u32,
|
||||
y: u32,
|
||||
}
|
||||
|
||||
impl Coordinate {
|
||||
fn distance_to(&self, other: &Coordinate) -> u32 {
|
||||
((other.x as i32 - self.x as i32).abs() + (other.y as i32 - self.y as i32).abs()) as u32
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
enum Claim {
|
||||
Unclaimed,
|
||||
Claimed { index: usize, distance: u32 },
|
||||
Tied { distance: u32 },
|
||||
}
|
||||
|
||||
struct Grid {
|
||||
grid: Vec<Claim>,
|
||||
width: usize,
|
||||
height: usize,
|
||||
}
|
||||
|
||||
impl Grid {
|
||||
fn new(width: usize, height: usize) -> Self {
|
||||
Self {
|
||||
grid: vec![Claim::Unclaimed; width * height],
|
||||
width,
|
||||
height,
|
||||
}
|
||||
}
|
||||
|
||||
fn claim(&mut self, index: usize, coord: &Coordinate) {
|
||||
// loop through the grid, calculate the distance to each point, if it's unclaimed or the
|
||||
// distance is shorter then claim it.
|
||||
for (current_index, claim) in self.grid.iter_mut().enumerate() {
|
||||
let current_coord = index_to_coord(current_index, self.width);
|
||||
let distance = coord.distance_to(¤t_coord);
|
||||
|
||||
match claim {
|
||||
Claim::Unclaimed => *claim = Claim::Claimed { index, distance },
|
||||
Claim::Claimed {
|
||||
distance: claimed_distance,
|
||||
..
|
||||
} if *claimed_distance > distance => *claim = Claim::Claimed { index, distance },
|
||||
Claim::Claimed {
|
||||
distance: claimed_distance,
|
||||
..
|
||||
} if *claimed_distance == distance => *claim = Claim::Tied { distance },
|
||||
Claim::Tied {
|
||||
distance: tied_distance,
|
||||
} if distance < *tied_distance => *claim = Claim::Claimed { index, distance },
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn largest_claimed_area(&self) -> u32 {
|
||||
let areas = self.grid.iter().fold(HashMap::new(), |mut areas, claim| {
|
||||
if let Claim::Claimed { index, .. } = claim {
|
||||
let area = areas.entry(index).or_insert(0u32);
|
||||
*area += 1
|
||||
}
|
||||
|
||||
areas
|
||||
});
|
||||
|
||||
// Exclude indexes that touch the edges as they will be infinite
|
||||
let mut exclude = HashSet::new();
|
||||
for x in 0..self.width {
|
||||
if let Claim::Claimed { index, .. } = self.grid[x] {
|
||||
exclude.insert(index);
|
||||
}
|
||||
if let Claim::Claimed { index, .. } = self.grid[self.width * (self.height - 1) + x] {
|
||||
exclude.insert(index);
|
||||
}
|
||||
}
|
||||
for y in 1..self.height - 1 {
|
||||
if let Claim::Claimed { index, .. } = self.grid[y * self.width] {
|
||||
exclude.insert(index);
|
||||
}
|
||||
if let Claim::Claimed { index, .. } = self.grid[y * self.width + self.width - 1] {
|
||||
exclude.insert(index);
|
||||
}
|
||||
}
|
||||
|
||||
*areas
|
||||
.iter()
|
||||
.filter_map(|(index, area)| {
|
||||
if exclude.contains(index) {
|
||||
None
|
||||
} else {
|
||||
Some(area)
|
||||
}
|
||||
})
|
||||
.max()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let input = fs::read_to_string("input/day6.txt").expect("input");
|
||||
|
@ -23,22 +123,28 @@ fn main() {
|
|||
|
||||
fn part1(coordinates: &[Coordinate]) {
|
||||
let max = furthest_coord(coordinates);
|
||||
let grid = vec![None, max.0 * max.1];
|
||||
let mut grid = Grid::new(max.x as usize, max.y as usize);
|
||||
|
||||
// Now fill the grid with the coords...
|
||||
// Claim closest locations for each coord
|
||||
for (index, coord) in coordinates.iter().enumerate() {
|
||||
grid.claim(index, &coord);
|
||||
}
|
||||
|
||||
// Find the one with the most claimed area
|
||||
let area = grid.largest_claimed_area();
|
||||
println!("Part 1 = {}", area);
|
||||
}
|
||||
|
||||
fn furthest_coord(coordinates: &[Coordinate]) -> Coordinate {
|
||||
// There are no negative coords, so assume origin at 0,0
|
||||
let mut max = Coordinate(0, 0);
|
||||
for Coordinate(x, y) in coordinates {
|
||||
if *x > max.0 {
|
||||
max.0= *x;
|
||||
let mut max = Coordinate { x: 0, y: 0 };
|
||||
for Coordinate { x, y } in coordinates {
|
||||
if *x > max.x {
|
||||
max.x = *x;
|
||||
}
|
||||
|
||||
if *y > max.1 {
|
||||
max.1 = *y;
|
||||
if *y > max.y {
|
||||
max.y = *y;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,5 +157,14 @@ fn parse_coord(line: &str) -> Option<Coordinate> {
|
|||
}
|
||||
let captures = RE.captures(line)?;
|
||||
|
||||
Some(Coordinate(captures[1].parse().ok()?, captures[2].parse().ok()?))
|
||||
Some(Coordinate {
|
||||
x: captures[1].parse().ok()?,
|
||||
y: captures[2].parse().ok()?,
|
||||
})
|
||||
}
|
||||
|
||||
fn index_to_coord(index: usize, width: usize) -> Coordinate {
|
||||
let x = (index % width) as u32;
|
||||
let y = (index / width) as u32;
|
||||
Coordinate { x, y }
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue