Files
adventofcode/2018/06/src/main.rs
2018-12-17 14:03:08 +01:00

121 lines
3.1 KiB
Rust

use std::collections::HashMap;
use std::io::{self, BufRead};
fn distance(a: (i32, i32), b: (i32, i32)) -> i32 {
(a.0 - b.0).abs() + (a.1 - b.1).abs()
}
#[derive(Clone, Copy, Debug)]
enum State {
Empty,
Owner(usize, i32),
Equal(i32),
}
#[derive(Clone, Copy, Debug)]
enum Area {
Infinite,
Finite(usize),
}
fn main() {
let coordinates = io::stdin()
.lock()
.lines()
.filter_map(Result::ok)
.map(|line| {
let coords = line
.split(", ")
.map(|coord| coord.parse::<i32>().unwrap())
.collect::<Vec<_>>();
(coords[0], coords[1])
})
.collect::<Vec<_>>();
let width = coordinates
.iter()
.map(|(x, _)| *x as usize)
.max()
.expect("failed to find max x")
+ 1;
let height = coordinates
.iter()
.map(|(_, y)| *y as usize)
.max()
.expect("failed to find max y")
+ 1;
let mut grid_view = vec![State::Empty; width * height].into_boxed_slice();
for x in 0..width {
for y in 0..height {
for (i, c) in coordinates.iter().enumerate() {
let distance = distance(*c, (x as i32, y as i32));
let state = &mut grid_view[x + (y * width)];
*state = match state {
State::Empty => State::Owner(i, distance),
State::Owner(_, d) if *d > distance => State::Owner(i, distance),
State::Owner(o, d) if *d == distance && *o != i => State::Equal(distance),
State::Equal(d) if *d > distance => State::Owner(i, distance),
_ => *state,
};
}
}
}
let mut areas = HashMap::new();
for x in 0..width {
for y in 0..height {
if let State::Owner(o, _) = grid_view[x + (y * width)] {
let a = areas.entry(o).or_insert(Area::Finite(0));
if x == 0 || x == width - 1 || y == 0 || y == height - 1 {
*a = Area::Infinite;
} else {
match a {
Area::Infinite => (),
Area::Finite(area) => *area += 1,
}
}
}
}
}
let (_, area) = areas
.iter()
.filter_map(|(i, area)| {
if let Area::Finite(area) = area {
Some((i, area))
} else {
None
}
})
.max_by_key(|(_, area)| *area)
.expect("failed to find max area");
println!("part.one={}", area);
let mut grid_view = vec!['.'; width * height].into_boxed_slice();
for y in 0..height {
for x in 0..width {
let total = coordinates
.iter()
.map(|c| distance(*c, (x as i32, y as i32)))
.sum::<i32>();
if total < 10_000 {
grid_view[x + (y * width)] = '#';
}
}
}
let area = grid_view.iter().filter(|r| **r == '#').count();
println!("part.two={}", area);
}