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"
|
name = "advent-of-code"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Wesley Moore <wes@wezm.net>"]
|
authors = ["Wesley Moore <wes@wezm.net>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
chrono = "0.4.6"
|
chrono = "0.4.6"
|
||||||
|
|
|
@ -2,12 +2,112 @@
|
||||||
extern crate lazy_static;
|
extern crate lazy_static;
|
||||||
extern crate regex;
|
extern crate regex;
|
||||||
|
|
||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[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() {
|
fn main() {
|
||||||
let input = fs::read_to_string("input/day6.txt").expect("input");
|
let input = fs::read_to_string("input/day6.txt").expect("input");
|
||||||
|
@ -23,22 +123,28 @@ fn main() {
|
||||||
|
|
||||||
fn part1(coordinates: &[Coordinate]) {
|
fn part1(coordinates: &[Coordinate]) {
|
||||||
let max = furthest_coord(coordinates);
|
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 {
|
fn furthest_coord(coordinates: &[Coordinate]) -> Coordinate {
|
||||||
// There are no negative coords, so assume origin at 0,0
|
// There are no negative coords, so assume origin at 0,0
|
||||||
let mut max = Coordinate(0, 0);
|
let mut max = Coordinate { x: 0, y: 0 };
|
||||||
for Coordinate(x, y) in coordinates {
|
for Coordinate { x, y } in coordinates {
|
||||||
if *x > max.0 {
|
if *x > max.x {
|
||||||
max.0= *x;
|
max.x = *x;
|
||||||
}
|
}
|
||||||
|
|
||||||
if *y > max.1 {
|
if *y > max.y {
|
||||||
max.1 = *y;
|
max.y = *y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,5 +157,14 @@ fn parse_coord(line: &str) -> Option<Coordinate> {
|
||||||
}
|
}
|
||||||
let captures = RE.captures(line)?;
|
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