finish the station example
This commit is contained in:
184
src/station.rs
184
src/station.rs
@@ -1,4 +1,7 @@
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
use std::ops::Rem;
|
||||
use std::str;
|
||||
|
||||
struct StationMap {
|
||||
@@ -103,6 +106,58 @@ impl StationMap {
|
||||
(most_found, best_x, best_y)
|
||||
}
|
||||
|
||||
fn marvinize(&mut self, from_x: usize, from_y: usize) -> Vec<(usize, usize)> {
|
||||
/* step 1, find all the data points by rise/run */
|
||||
let mut mapmap = HashMap::new();
|
||||
|
||||
for x in 0..self.width {
|
||||
for y in 0..self.height {
|
||||
if x == from_x && y == from_y {
|
||||
continue;
|
||||
}
|
||||
|
||||
if self.get(x, y) {
|
||||
let deltax = (x as isize) - (from_x as isize);
|
||||
let deltay = (y as isize) - (from_y as isize);
|
||||
let gcd = gcd(deltax.abs(), deltay.abs());
|
||||
let rise = deltay / gcd;
|
||||
let run = deltax / gcd;
|
||||
let key = (rise, run);
|
||||
let deltax2 = (deltax.abs() * deltax.abs()) as f64;
|
||||
let deltay2 = (deltay.abs() * deltay.abs()) as f64;
|
||||
let distance = (deltax2 + deltay2).sqrt();
|
||||
|
||||
match mapmap.get_mut(&key) {
|
||||
None => {
|
||||
mapmap.insert( (rise, run), vec![(distance, x, y)] );
|
||||
}
|
||||
Some(existing) =>
|
||||
existing.push((distance, x, y)),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut all_keys: Vec<(isize, isize)> = mapmap.keys().map(|(a,b)| (*a, *b)).collect();
|
||||
all_keys.sort_by(compare_slopes);
|
||||
|
||||
let mut res = vec![];
|
||||
while !mapmap.is_empty() {
|
||||
for key in all_keys.iter() {
|
||||
if let Some(curvec) = mapmap.get_mut(&key) {
|
||||
println!("Current slope: {:?}", key);
|
||||
let (x, y) = remove_lowest(curvec);
|
||||
res.push((x, y));
|
||||
if curvec.len() == 0 {
|
||||
mapmap.remove(&key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
fn print(&self) {
|
||||
for y in 0..self.height {
|
||||
for x in 0..self.width {
|
||||
@@ -125,8 +180,8 @@ fn diff(a: usize, b: usize) -> usize {
|
||||
}
|
||||
}
|
||||
|
||||
fn gcd(mut x: usize, mut y: usize) -> usize {
|
||||
while y != 0 {
|
||||
fn gcd<T: Copy + Default + PartialEq + Rem<Output=T>>(mut x: T, mut y: T) -> T {
|
||||
while y != T::default() {
|
||||
let t = x % y;
|
||||
x = y;
|
||||
y = t;
|
||||
@@ -134,6 +189,80 @@ fn gcd(mut x: usize, mut y: usize) -> usize {
|
||||
x
|
||||
}
|
||||
|
||||
fn quadrant(slope: &(isize, isize)) -> u8 {
|
||||
let (rise, run) = slope;
|
||||
|
||||
if run >= &0 && rise < &0 {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if run > &0 && rise >= &0 {
|
||||
return 2;
|
||||
}
|
||||
|
||||
if run <= &0 && rise > &0 {
|
||||
return 3;
|
||||
}
|
||||
|
||||
4
|
||||
}
|
||||
|
||||
fn compare_slopes(a: &(isize, isize), b: &(isize, isize)) -> Ordering {
|
||||
let aquad = quadrant(a);
|
||||
let bquad = quadrant(b);
|
||||
|
||||
if aquad < bquad {
|
||||
return Ordering::Less;
|
||||
}
|
||||
|
||||
if aquad > bquad {
|
||||
return Ordering::Greater;
|
||||
}
|
||||
|
||||
let (arise, arun) = a;
|
||||
let (brise, brun) = b;
|
||||
|
||||
match (*arun == 0, *brun == 0) {
|
||||
(false, false) => {}
|
||||
(false, true) if [1,3].contains(&aquad) => return Ordering::Greater,
|
||||
(false, true) => return Ordering::Less,
|
||||
(true, false) if [1,3].contains(&aquad) => return Ordering::Less,
|
||||
(true, false) => return Ordering::Greater,
|
||||
(true, true) => return Ordering::Equal,
|
||||
}
|
||||
|
||||
let aslope = arise.abs() as f64 / arun.abs() as f64;
|
||||
let bslope = brise.abs() as f64 / brun.abs() as f64;
|
||||
|
||||
if [1,3].contains(&aquad) {
|
||||
aslope.partial_cmp(&bslope).unwrap_or(Ordering::Equal).reverse()
|
||||
} else {
|
||||
aslope.partial_cmp(&bslope).unwrap_or(Ordering::Equal)
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_lowest(v: &mut Vec<(f64, usize, usize)>) -> (usize, usize) {
|
||||
assert!(v.len() > 0);
|
||||
|
||||
let (dist0, x0, y0) = v[0];
|
||||
let mut found_idx = 0;
|
||||
let mut lowest = dist0;
|
||||
let mut retval = (x0, y0);
|
||||
|
||||
println!("Remove lowest: {:?}", v);
|
||||
for (idx, (distance, x, y)) in v.iter().enumerate().skip(1) {
|
||||
if distance <= &lowest {
|
||||
found_idx = idx;
|
||||
lowest = *distance;
|
||||
retval = (*x, *y);
|
||||
}
|
||||
}
|
||||
v.remove(found_idx);
|
||||
println!("Chose {:?}", retval);
|
||||
|
||||
retval
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn day10() {
|
||||
let example1 = StationMap::new(".#..#\n.....\n#####\n....#\n...##\n");
|
||||
@@ -146,9 +275,54 @@ fn day10() {
|
||||
assert_eq!((41,6,3), example4.place_station());
|
||||
let example5 = StationMap::new(".#..##.###...#######\n##.############..##.\n.#.######.########.#\n.###.#######.####.#.\n#####.##.#.##.###.##\n..#####..#.#########\n####################\n#.####....###.#.#.##\n##.#################\n#####.##.###..####..\n..######..##.#######\n####.##.####...##..#\n.#####..#.######.###\n##...#.##########...\n#.##########.#######\n.####.#.###.###.#.##\n....##.##.###..#####\n.#.#.###########.###\n#.#.#.#####.####.###\n###.##.####.##.#..##\n");
|
||||
assert_eq!((210,11,13), example5.place_station());
|
||||
let mut example6 = StationMap::new(".#....#####...#..\n##...##.#####..##\n##...#...#.#####.\n..#.....#...###..\n..#.#.....#....##\n");
|
||||
let (_, ex6x, ex6y) = example6.place_station();
|
||||
assert_eq!((8, 3), (ex6x, ex6y));
|
||||
let example6_destroyed = example6.marvinize(8, 3);
|
||||
assert_eq!((8, 1), example6_destroyed[0]);
|
||||
assert_eq!((9, 0), example6_destroyed[1]);
|
||||
assert_eq!((9, 1), example6_destroyed[2]);
|
||||
assert_eq!((10, 0), example6_destroyed[3]);
|
||||
assert_eq!((9, 2), example6_destroyed[4]);
|
||||
assert_eq!((11, 1), example6_destroyed[5]);
|
||||
assert_eq!((12, 1), example6_destroyed[6]);
|
||||
assert_eq!((11, 2), example6_destroyed[7]);
|
||||
assert_eq!((15, 1), example6_destroyed[8]);
|
||||
assert_eq!((12, 2), example6_destroyed[9]);
|
||||
assert_eq!((13, 2), example6_destroyed[10]);
|
||||
assert_eq!((14, 2), example6_destroyed[11]);
|
||||
assert_eq!((15, 2), example6_destroyed[12]);
|
||||
assert_eq!((12, 3), example6_destroyed[13]);
|
||||
assert_eq!((16, 4), example6_destroyed[14]);
|
||||
assert_eq!((15, 4), example6_destroyed[15]);
|
||||
assert_eq!((10, 4), example6_destroyed[16]);
|
||||
assert_eq!((4, 4), example6_destroyed[17]);
|
||||
assert_eq!((2, 4), example6_destroyed[18]);
|
||||
assert_eq!((2, 3), example6_destroyed[19]);
|
||||
assert_eq!((0, 2), example6_destroyed[20]);
|
||||
assert_eq!((1, 2), example6_destroyed[21]);
|
||||
assert_eq!((0, 1), example6_destroyed[22]);
|
||||
assert_eq!((1, 1), example6_destroyed[23]);
|
||||
assert_eq!((5, 2), example6_destroyed[24]);
|
||||
assert_eq!((1, 0), example6_destroyed[25]);
|
||||
assert_eq!((5, 1), example6_destroyed[26]);
|
||||
assert_eq!((6, 1), example6_destroyed[27]);
|
||||
assert_eq!((6, 0), example6_destroyed[28]);
|
||||
assert_eq!((7, 0), example6_destroyed[29]);
|
||||
assert_eq!((8, 0), example6_destroyed[30]);
|
||||
assert_eq!((10, 1), example6_destroyed[31]);
|
||||
assert_eq!((14, 0), example6_destroyed[32]);
|
||||
assert_eq!((16, 1), example6_destroyed[33]);
|
||||
assert_eq!((13, 3), example6_destroyed[34]);
|
||||
assert_eq!((14, 3), example6_destroyed[35]);
|
||||
|
||||
let day10_contents = fs::read("inputs/day10").expect("Couldn't open day10 problem");
|
||||
let day10_str = str::from_utf8(&day10_contents).expect("Couldn't decode day10 problem");
|
||||
let day10a = StationMap::new(&day10_str);
|
||||
day10a.print();
|
||||
assert_eq!((334,23,20), day10a.place_station());
|
||||
let mut day10 = StationMap::new(&day10_str);
|
||||
day10.print();
|
||||
let (count, x, y) = day10.place_station();
|
||||
assert_eq!((334,23,20), (count, x, y));
|
||||
let order = day10.marvinize(x, y);
|
||||
assert!(order.len() > 200);
|
||||
assert_eq!((11, 19), order[199]);
|
||||
}
|
||||
Reference in New Issue
Block a user