From 3b825ac9330cb96d481ddd3a25b4a3be41fcc53c Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sat, 22 Dec 2018 09:40:09 +0100 Subject: [PATCH] Move manhattan metric function to trait. --- 2018/loc.svg | 36 ++++++++++++++++++------------------ 2018/src/common.rs | 39 +++++++++++++++++++++++++++------------ 2018/src/day06.rs | 6 +++--- 2018/src/day15.rs | 4 ++-- 2018/src/day22.rs | 6 +++--- 5 files changed, 53 insertions(+), 38 deletions(-) diff --git a/2018/loc.svg b/2018/loc.svg index 67599d4..5cf04f8 100644 --- a/2018/loc.svg +++ b/2018/loc.svg @@ -32,10 +32,10 @@ z +" id="me9ddb36467" style="stroke:#000000;stroke-width:0.8;"/> - + @@ -71,7 +71,7 @@ z - + @@ -110,7 +110,7 @@ z - + @@ -139,7 +139,7 @@ z - + @@ -153,7 +153,7 @@ z - + @@ -193,7 +193,7 @@ z - + @@ -286,10 +286,10 @@ z +" id="mb89a9b780e" style="stroke:#000000;stroke-width:0.8;"/> - + @@ -302,7 +302,7 @@ L -3.5 0 - + @@ -316,7 +316,7 @@ L -3.5 0 - + @@ -331,7 +331,7 @@ L -3.5 0 - + @@ -346,7 +346,7 @@ L -3.5 0 - + @@ -361,7 +361,7 @@ L -3.5 0 - + @@ -577,7 +577,7 @@ z - - - + diff --git a/2018/src/common.rs b/2018/src/common.rs index 38be760..cccba75 100644 --- a/2018/src/common.rs +++ b/2018/src/common.rs @@ -1,11 +1,36 @@ use std::collections::HashMap; +use std::fmt::Debug; use std::hash::Hash; use std::io; use std::io::Read; -use std::str::FromStr; use std::ops::Add; use std::ops::Sub; -use std::fmt::Debug; +use std::str::FromStr; + +/// Utility trait for things representing coordinates. +/// +/// This is implemented by default for any simple pair-tuple +pub trait Point { + type CoordType; + + /// Compute the manhattan distance between this and another. + /// + /// The distance will always be >= 0. + fn manhattan(self, other: Self) -> Self::CoordType; +} + +impl Point for (T, T) + where T: Add + Sub + Copy + Ord +{ + type CoordType = T; + + fn manhattan(self, other: Self) -> T { + let (xa, ya) = self; + let (xb, yb) = other; + xa.max(xb) + ya.max(yb) - xa.min(xb) - ya.min(yb) + } +} + /// Apply Erathostenes's sieve to the supplied array /// @@ -68,16 +93,6 @@ pub fn read_single_input(input: &mut Read) -> T buf.trim().parse().unwrap() } -/// Compute the manhattan distance between two points of arbitrary type. -pub fn manhattan_distance(a: (T, T), b: (T, T)) -> T -where T: Copy + Add + Sub + Ord -{ - let (xa, ya) = a; - let (xb, yb) = b; - xa.max(xb) + ya.max(yb) - xa.min(xb) - ya.min(yb) -} - - /// An interface to count elements in particular categories. pub trait GroupingCount { /// The type of the categories under inspection diff --git a/2018/src/day06.rs b/2018/src/day06.rs index d288822..0e50ced 100644 --- a/2018/src/day06.rs +++ b/2018/src/day06.rs @@ -4,7 +4,7 @@ use std::io::BufReader; use std::io::Read; use common::GroupingCount; -use common::manhattan_distance; +use common::Point; use common::Solution; type Coordinate = (usize, usize); @@ -61,7 +61,7 @@ impl Day06 { let mut cur_best = None; for (i, point) in self.points.iter().enumerate() { - let dist = manhattan_distance(*point, (x, y)); + let dist = point.manhattan((x, y)); if dist < cur_dist { cur_dist = dist; cur_best = Some(i); @@ -82,7 +82,7 @@ impl Day06 { self.read_points(input); self.range() - .map(|x| self.points.iter().map(|y| manhattan_distance(x, *y)).sum::()) + .map(|x| self.points.iter().map(|y| y.manhattan(x)).sum::()) .filter(|&x| x < limit) .count() } diff --git a/2018/src/day15.rs b/2018/src/day15.rs index 41fba57..41812fa 100644 --- a/2018/src/day15.rs +++ b/2018/src/day15.rs @@ -6,7 +6,7 @@ use std::io::BufRead; use std::io::BufReader; use std::io::Read; -use common::manhattan_distance; +use common::Point; use common::Solution; type Coordinate = (usize, usize); @@ -122,7 +122,7 @@ impl Day15 { let to_attack = self.units.iter() .enumerate() .filter(|(_, x)| x.faction != faction && x.is_alive()) - .filter(|(_, x)| manhattan_distance(x.pos, initial) == 1) + .filter(|(_, x)| x.pos.manhattan(initial) == 1) .min_by(|&(_, a), &(_, b)| a.hp.cmp(&b.hp).then(a.pos.cmp(&b.pos))); if let Some((index, _)) = to_attack { diff --git a/2018/src/day22.rs b/2018/src/day22.rs index 26911c3..7c356ca 100644 --- a/2018/src/day22.rs +++ b/2018/src/day22.rs @@ -5,7 +5,7 @@ use std::io::BufRead; use std::io::BufReader; use std::io::Read; -use common::manhattan_distance; +use common::Point; use common::Solution; type Coordinate = (usize, usize); @@ -107,7 +107,7 @@ impl Solution for Day22 { let mut visited: HashSet = HashSet::new(); let target_state = State { pos: target, climbing: false, torch: true }; - todo.push((Reverse(manhattan_distance((0, 0), target)), Reverse(0), State { pos: (0, 0), climbing: false, torch: true })); + todo.push((Reverse((0, 0).manhattan(target)), Reverse(0), State { pos: (0, 0), climbing: false, torch: true })); while let Some((Reverse(approx), Reverse(dist), state)) = todo.pop() { if visited.contains(&state) { @@ -147,7 +147,7 @@ impl Solution for Day22 { }; if !visited.contains(&new_state) && new_state.is_valid(table[yn][xn]) && (x == xn || y == yn) { - todo.push((Reverse(dist + 1 + manhattan_distance(target, new_state.pos)), Reverse(dist + 1), new_state)); + todo.push((Reverse(dist + 1 + target.manhattan(new_state.pos)), Reverse(dist + 1), new_state)); } } }