[2018][rust][06.0]

sorbet
Alpha Chen 6 years ago
parent 27577d0647
commit 230a368660

@ -0,0 +1,227 @@
use std::collections::{HashMap, HashSet};
use std::error::Error;
use std::hash::Hash;
use std::io::{self, Read};
use std::str::FromStr;
fn main() -> Result<(), Box<Error>> {
let mut input = String::new();
io::stdin().read_to_string(&mut input)?;
let output = solve(&input)?;
println!("{}", output);
Ok(())
}
fn solve(input: &str) -> Result<String, Box<Error>> {
let coords = Coords::from_str(input)?;
let min_x = coords.0.iter().map(|c| c.x).min().unwrap();
let max_x = coords.0.iter().map(|c| c.x).max().unwrap();
let min_y = coords.0.iter().map(|c| c.y).min().unwrap();
let max_y = coords.0.iter().map(|c| c.y).max().unwrap();
let top_left = Coord { x: min_x, y: min_y };
let bottom_right = Coord { x: max_x, y: max_y };
let coord_names: HashMap<_, _> = coords
.0
.iter()
.enumerate()
.map(|(i, c)| (c, (i + 65) as u8 as char))
.collect();
let grid = Grid::new(top_left, bottom_right, |coord| {
coords
.closest(*coord)
.and_then(|closest| coord_names.get(&closest))
});
let edges: HashSet<_> = grid.edges().iter().flat_map(|&x| x).collect();
let mut area_sizes = HashMap::new();
grid.locations
.values()
.flat_map(|x| x)
.filter(|x| !edges.contains(x))
.for_each(|x| {
let count = area_sizes.entry(x).or_insert(0);
*count += 1;
});
let max_area = area_sizes.iter().map(|(_, v)| v).max().unwrap();
Ok(max_area.to_string())
}
#[test]
fn test_solve() {
let input = r"
1, 1
1, 6
8, 3
3, 4
5, 5
8, 9
";
let output = solve(&input).unwrap();
assert_eq!(output, "17".to_string());
}
#[derive(Debug)]
struct Grid<T> {
top_left: Coord,
bottom_right: Coord,
locations: HashMap<Coord, T>,
}
impl<T> Grid<T> {
fn new<C: Into<Coord>, F: Fn(&Coord) -> T>(top_left: C, bottom_right: C, f: F) -> Self {
let top_left = top_left.into();
let bottom_right = bottom_right.into();
let mut locations = HashMap::new();
for coord in top_left.grid(&bottom_right) {
locations.insert(coord, f(&coord));
}
Grid {
top_left,
bottom_right,
locations,
}
}
}
impl<T: Eq + Hash> Grid<T> {
fn edges(&self) -> HashSet<&T> {
let mut edges = HashSet::new();
for x in self.top_left.x..=self.bottom_right.x {
for &y in &[self.top_left.y, self.bottom_right.y] {
if let Some(t) = self.locations.get(&Coord { x, y }) {
edges.insert(t);
}
}
}
for y in self.top_left.y..=self.bottom_right.y {
for &x in &[self.top_left.x, self.bottom_right.x] {
if let Some(t) = self.locations.get(&Coord { x, y }) {
edges.insert(t);
}
}
}
edges
}
}
#[test]
fn test_edges() {
let top_left = Coord { x: 0, y: 0 };
let bottom_right = Coord { x: 2, y: 2 };
let grid = Grid::new(top_left, bottom_right, |coord| coord.y * 3 + coord.x);
let expected: HashSet<_> = vec![0, 1, 2, 3, 5, 6, 7, 8]
.iter()
.map(|&x| x as isize)
.collect();
assert_eq!(grid.edges(), expected.iter().collect());
}
#[derive(Debug)]
struct Coords(Vec<Coord>);
impl Coords {
fn closest<C: Into<Coord>>(&self, c: C) -> Option<Coord> {
let c = c.into();
let mut distances = HashMap::new();
for coord in &self.0 {
let distance = coord.distance(c);
let v = distances.entry(distance).or_insert_with(Vec::new);
v.push(coord);
}
let (_, closest_coords) = distances.iter().min_by_key(|(&k, _)| k)?;
if closest_coords.len() == 1 {
Some(*closest_coords[0])
} else {
None
}
}
}
#[test]
fn test_closest() {
let coords = Coords::from_str(
r"
1, 1
1, 6
8, 3
3, 4
5, 5
8, 9
",
)
.unwrap();
assert_eq!(coords.closest((0, 0)), Some(Coord::from((1, 1))));
assert_eq!(coords.closest((3, 2)), Some(Coord::from((3, 4))));
assert_eq!(coords.closest((5, 0)), None);
assert_eq!(coords.closest((0, 4)), None);
}
impl FromStr for Coords {
type Err = Box<Error>;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let coords = s
.trim()
.lines()
.map(Coord::from_str)
.collect::<Result<_, _>>()?;
Ok(Coords(coords))
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
struct Coord {
x: isize,
y: isize,
}
impl Coord {
fn distance<C: Into<Self>>(&self, other: C) -> isize {
let other = other.into();
(self.x - other.x).abs() + (self.y - other.y).abs()
}
fn grid(&self, to: &Self) -> impl Iterator<Item = Coord> + '_ {
let to = *to;
(self.x..=to.x).flat_map(move |x| (self.y..=to.y).map(move |y| (x, y).into()))
}
}
#[test]
fn test_distance() {
let coord = Coord { x: 4, y: 3 };
assert_eq!(coord.distance((1, 1)), 5);
assert_eq!(coord.distance((8, 9)), 10);
}
impl From<(isize, isize)> for Coord {
fn from((x, y): (isize, isize)) -> Self {
Coord { x, y }
}
}
impl FromStr for Coord {
type Err = Box<Error>;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut xy = s.split(", ");
let x = xy.next().unwrap().parse()?;
let y = xy.next().unwrap().parse()?;
Ok(Coord { x, y })
}
}
Loading…
Cancel
Save