From 460e0749ade4448604d208f4227a1fa141dcbc25 Mon Sep 17 00:00:00 2001 From: Arne Keller Date: Sun, 27 Jan 2019 14:24:18 +0100 Subject: [PATCH] Run rustfmt --- rustfmt.toml | 1 + src/display.rs | 55 ++++++++++--------- src/input.rs | 79 +++++++++++++++++++++++---- src/main.rs | 143 +++++++++++++++++++++++++++++++++---------------- 4 files changed, 197 insertions(+), 81 deletions(-) create mode 100644 rustfmt.toml diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..218e203 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1 @@ +hard_tabs = true diff --git a/src/display.rs b/src/display.rs index 5af5ba5..56e004b 100644 --- a/src/display.rs +++ b/src/display.rs @@ -1,19 +1,25 @@ +use svg::node::element::path::Data; +use svg::node::element::Path; +use svg::node::element::{AnimateMotion, Circle, MotionPath}; use svg::Document; use svg::Node; -use svg::node::element::{AnimateMotion, MotionPath, Circle}; -use svg::node::element::Path; -use svg::node::element::path::Data; use std::io; use super::*; -pub(crate) fn dump_svg(points: &[(Point, &'static str)], lines: &[(Line, &'static str)], polys: &[Polygon], route1: &[Point], route2_start: Point) { +pub(crate) fn dump_svg( + points: &[(Point, &'static str)], + lines: &[(Line, &'static str)], + polys: &[Polygon], + route1: &[Point], + route2_start: Point, +) { let mut document = Document::new() // view box at (0, -200), w*h (200, 200) .set("viewBox", (0, -1100, 2100, 2100)) .set("xmlns:xlink", "http://www.w3.org/1999/xlink"); - + for circle in points.iter().map(|(p, color)| { Circle::new() .set("cx", f64::from(p.x())) @@ -45,8 +51,7 @@ pub(crate) fn dump_svg(points: &[(Point, &'static str)], lines: &[(Line, &'stati let first = coords[0].x_y(); let mut first: (f64, f64) = (first.0.into(), first.1.into()); first.1 *= -1.0; - let mut data = Data::new() - .move_to(first); + let mut data = Data::new().move_to(first); for c in &coords[1..] { let c = c.x_y(); let mut c: (f64, f64) = (c.0.into(), c.1.into()); @@ -66,8 +71,7 @@ pub(crate) fn dump_svg(points: &[(Point, &'static str)], lines: &[(Line, &'stati let mut first: (f64, f64) = (route1[0].x().into(), route1[0].y().into()); first.1 *= -1.0; - let mut data = Data::new() - .move_to(first); + let mut data = Data::new().move_to(first); for point in &route1[1..] { let c = point.x_y(); let mut c: (f64, f64) = (c.0.into(), c.1.into()); @@ -82,12 +86,14 @@ pub(crate) fn dump_svg(points: &[(Point, &'static str)], lines: &[(Line, &'stati document.append(path); let mut dot1 = Circle::new() - .set("cx", 0.0) - .set("cy", 0.0) - .set("r", 25.2) - .set("opacity", 0.75) - .set("fill", "gray"); - let mut motion1 = AnimateMotion::new().set("dur", "2s").set("repeatCount", "indefinite"); + .set("cx", 0.0) + .set("cy", 0.0) + .set("r", 25.2) + .set("opacity", 0.75) + .set("fill", "gray"); + let mut motion1 = AnimateMotion::new() + .set("dur", "2s") + .set("repeatCount", "indefinite"); let path = MotionPath::new().set("xlink:href", "#route1"); motion1.append(path); dot1.append(motion1); @@ -95,10 +101,9 @@ pub(crate) fn dump_svg(points: &[(Point, &'static str)], lines: &[(Line, &'stati let mut first: (f64, f64) = (route2_start.x().into(), route2_start.y().into()); first.1 *= -1.0; - let mut data = Data::new() - .move_to(first); + let mut data = Data::new().move_to(first); let last = route1.last().unwrap(); - data = data.line_to::<(f64, f64)>((last.x().into(), (|x:f64|-x)(last.y().into()))); + data = data.line_to::<(f64, f64)>((last.x().into(), (|x: f64| -x)(last.y().into()))); let path = Path::new() .set("id", "route2") .set("fill", "none") @@ -107,12 +112,14 @@ pub(crate) fn dump_svg(points: &[(Point, &'static str)], lines: &[(Line, &'stati document.append(path); let mut dot1 = Circle::new() - .set("cx", 0.0) - .set("cy", 0.0) - .set("r", 25.2) - .set("opacity", 0.75) - .set("fill", "gray"); - let mut motion1 = AnimateMotion::new().set("dur", "2s").set("repeatCount", "indefinite"); + .set("cx", 0.0) + .set("cy", 0.0) + .set("r", 25.2) + .set("opacity", 0.75) + .set("fill", "gray"); + let mut motion1 = AnimateMotion::new() + .set("dur", "2s") + .set("repeatCount", "indefinite"); let path = MotionPath::new().set("xlink:href", "#route2"); motion1.append(path); dot1.append(motion1); diff --git a/src/input.rs b/src/input.rs index 10476ad..aa5fa8f 100644 --- a/src/input.rs +++ b/src/input.rs @@ -5,7 +5,7 @@ use std::io::prelude::*; pub(crate) struct InputData { pub start: Point, - pub polys: Vec + pub polys: Vec, } pub(crate) fn read_input() -> InputData { @@ -23,30 +23,87 @@ fn read_stdin() -> InputData { for _ in 0..polygon_count { let line = lines.next().unwrap(); - let numbers = line.trim().split(' ').map(|x| x.parse::().unwrap()).collect::>(); + let numbers = line + .trim() + .split(' ') + .map(|x| x.parse::().unwrap()) + .collect::>(); let corner_count = numbers[0]; - polygons.push(Polygon::new((0..corner_count).map(|idx| ((numbers[idx*2+1] as f32).into(), (numbers[idx*2+2] as f32).into())).collect::>().into(), vec![])); + polygons.push(Polygon::new( + (0..corner_count) + .map(|idx| { + ( + (numbers[idx * 2 + 1] as f32).into(), + (numbers[idx * 2 + 2] as f32).into(), + ) + }) + .collect::>() + .into(), + vec![], + )); } - let home = lines.next().unwrap().trim().split(' ').map(|x| x.parse::().unwrap().into()).collect::>(); + let home = lines + .next() + .unwrap() + .trim() + .split(' ') + .map(|x| x.parse::().unwrap().into()) + .collect::>(); InputData { start: Point::new(home[0], home[1]), - polys: polygons + polys: polygons, } } fn custom_input() -> InputData { let mut polys = vec![]; - polys.push(Polygon::new(vec![[2.0.into(), 0.0.into()], [6.0.into(), 0.0.into()], [6.0.into(), 6.0.into()], [2.0.into(), 5.0.into()]].into(), vec![])); - polys.push(Polygon::new(vec![[1.0.into(), 20.0.into()], [2.0.into(), 20.0.into()], [2.0.into(), 23.0.into()], [1.0.into(), 23.0.into()]].into(), vec![])); - polys.push(Polygon::new(vec![[1.0.into(), 25.0.into()], [2.0.into(), 25.0.into()], [2.0.into(), 28.0.into()], [1.0.into(), 28.0.into()]].into(), vec![])); - let mut stick = Polygon::new(vec![[1.0.into(), 115.0.into()], [2.0.into(), 115.0.into()], [2.0.into(), 130.0.into()], [1.0.into(), 130.0.into()]].into(), vec![]); + polys.push(Polygon::new( + vec![ + [2.0.into(), 0.0.into()], + [6.0.into(), 0.0.into()], + [6.0.into(), 6.0.into()], + [2.0.into(), 5.0.into()], + ] + .into(), + vec![], + )); + polys.push(Polygon::new( + vec![ + [1.0.into(), 20.0.into()], + [2.0.into(), 20.0.into()], + [2.0.into(), 23.0.into()], + [1.0.into(), 23.0.into()], + ] + .into(), + vec![], + )); + polys.push(Polygon::new( + vec![ + [1.0.into(), 25.0.into()], + [2.0.into(), 25.0.into()], + [2.0.into(), 28.0.into()], + [1.0.into(), 28.0.into()], + ] + .into(), + vec![], + )); + let mut stick = Polygon::new( + vec![ + [1.0.into(), 115.0.into()], + [2.0.into(), 115.0.into()], + [2.0.into(), 130.0.into()], + [1.0.into(), 130.0.into()], + ] + .into(), + vec![], + ); polys.push(stick.clone()); stick = stick.translate(35.0.into(), (-20.0).into()); polys.push(stick); InputData { start: Point::new(45.0.into(), 95.0.into()), - polys + polys, } -} \ No newline at end of file +} diff --git a/src/main.rs b/src/main.rs index 0eb5303..0f9bc62 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,3 @@ -use geo::*; use geo::prelude::*; use std::cmp; @@ -22,7 +21,7 @@ struct RunState { /// Our current location pos: Point, /// Current location of the bus, not including any delays - bus: Point + bus: Point, } impl cmp::Eq for RunState {} impl cmp::Ord for RunState { @@ -37,7 +36,7 @@ impl cmp::PartialOrd for RunState { } fn main() { - let bus = Point::new(0.0.into(), (-2000.0).into()); + let bus = Point::new(0.0, -2000.0); let data = input::read_input(); let house = data.start; @@ -46,40 +45,32 @@ fn main() { eprintln!("{:?}", polys); for p in &polys { assert!(p.interiors.is_empty()); - //assert!(p.is_convex()); } - let points = polys.iter().map(|x| x.exterior.0.clone()).flatten().collect::>(); + let points = polys + .iter() + .map(|x| x.exterior.0.clone()) + .flatten() + .collect::>(); let start = RunState { pos: house, bus: bus, - delay: max_possible_delay(bus, house) - //route: vec![house], - //length: 0.0.into() + delay: max_possible_delay(bus, house), }; - eprintln!("# Max delay possible: {:?}", start.delay); + eprintln!("# Max. delay possible: {:?}", start.delay); let mut states = BinaryHeap::new(); states.push(vec![start]); - + let mut best_delay = 0.0; let mut best = vec![]; while states.peek().map(|x| x[0].delay > best_delay) == Some(true) { eprintln!(". {:?} states left:", states.len()); - /* - if states.len() > 10 { - for s in &states { - eprintln!("{:?}", s); - } - panic!(); - } - */ let s = states.pop().unwrap(); let last = &s[0]; //s.last().unwrap(); eprintln!("{},{}", last.pos.x(), last.pos.y()); - //eprintln!("{:?}", states.peek()); // new states let mut all = vec![]; @@ -92,11 +83,14 @@ fn main() { let bus_next = last.bus.translate(0.0, distance(last.pos, next) * 2.0); let mut route = s.clone(); //eprintln!("{},{} would go {},{}", last.pos.x(), last.pos.y(), next.x(), next.y()); - route.insert(0, RunState { - pos: next, - bus: bus_next, - delay: max_possible_delay(bus_next, next) - }); + route.insert( + 0, + RunState { + pos: next, + bus: bus_next, + delay: max_possible_delay(bus_next, next), + }, + ); all.push(route); } } @@ -117,11 +111,14 @@ fn main() { if delay > best_delay { // new high score! let mut route = s.clone(); - route.insert(0, RunState { - pos: next, - bus: next, - delay - }); + route.insert( + 0, + RunState { + pos: next, + bus: next, + delay, + }, + ); eprintln!("# New best delay {:?}", delay); best = route; best.reverse(); @@ -137,7 +134,6 @@ fn main() { //eprintln!("-> adding all to queue"); states.extend(all); } - } eprintln!("d = {:?}", best_delay); let route = best; @@ -147,19 +143,33 @@ fn main() { } let first = route.first().unwrap(); let last = route.last().unwrap(); - let points = vec![(house, "red"), (first.bus.translate(0.0.into(), best_delay), "yellow"), (last.bus, "orange")]; - let lines = route.iter().map(|x| x.pos).collect::().lines().map(|x| { - (x, "gray") - }).collect::>(); - - display::dump_svg(&points, &lines, &polys, &route.iter().map(|x| x.pos).collect::>(), first.bus.translate(0.0.into(), best_delay)); + let points = vec![ + (house, "red"), + (first.bus.translate(0.0.into(), best_delay), "yellow"), + (last.bus, "orange"), + ]; + let lines = route + .iter() + .map(|x| x.pos) + .collect::() + .lines() + .map(|x| (x, "gray")) + .collect::>(); + + display::dump_svg( + &points, + &lines, + &polys, + &route.iter().map(|x| x.pos).collect::>(), + first.bus.translate(0.0.into(), best_delay), + ); } /// [a; b] fn float_range(a: f32, b: f32) -> impl Iterator { const STEPS: usize = 25; let d = b - a; - (0..=STEPS).map(move |s| a + ((s as f32) * d)/STEPS as f32) + (0..=STEPS).map(move |s| a + ((s as f32) * d) / STEPS as f32) } fn none_intersect(polys: &[Polygon], line: &Line) -> bool { @@ -178,12 +188,21 @@ fn none_intersect(polys: &[Polygon], line: &Line) -> bool { middle.y += line.dy() / 2.0; let middle: Point = middle.into(); 'poly: for p in polys { - for l in p.exterior.lines().chain(vec![Line::new(p.exterior.0[0], *p.exterior.0.last().unwrap())]) { - if (l.start == line.start && l.end == line.end) || (l.start == line.end && l.end == line.start) { + for l in p.exterior.lines().chain(vec![Line::new( + p.exterior.0[0], + *p.exterior.0.last().unwrap(), + )]) { + if (l.start == line.start && l.end == line.end) + || (l.start == line.end && l.end == line.start) + { // point is on polygon border continue 'poly; } - if l.start == line.start || l.end == line.end || l.start == line.end || l.end == line.start { + if l.start == line.start + || l.end == line.end + || l.start == line.end + || l.end == line.start + { /* if line.end.x > 0.0 { eprintln!("skipping {:?}", l); @@ -238,7 +257,8 @@ fn to_bus(bus: Point, start: Point) -> Vec { let c = bus.x(); let d = bus.y(); - let v = -a.powi(2) * (3.0) + (6.0) * a * c + b.powi(2) - (2.0) * b * d - (3.0) * c.powi(2) + d.powi(2); + let v = -a.powi(2) * (3.0) + (6.0) * a * c + b.powi(2) - (2.0) * b * d - (3.0) * c.powi(2) + + d.powi(2); if v >= 0.0 { // v = sqrt(-3 A^2 + 6 A C + B^2 - 2 B D - 3 C^2 + D^2) let v = v.sqrt(); @@ -246,18 +266,49 @@ fn to_bus(bus: Point, start: Point) -> Vec { let x1 = (v + 2.0 * b - 2.0 * d) / 3.0; let x2 = (-v + 2.0 * b - 2.0 * d) / 3.0; if x1 > (0.0) && x2 > (0.0) { - vec![bus.translate(0.0, (2.0) * x1), bus.translate(0.0, (2.0) * x2)] + vec![ + bus.translate(0.0, (2.0) * x1), + bus.translate(0.0, (2.0) * x2), + ] } else { vec![] } } else { - vec![] + vec![] } } #[cfg(test)] #[test] fn test_to_bus() { - assert!(to_bus(Coordinate { x: 0.0.into(), y: 0.0.into() }.into(), Coordinate { x: 1.0.into(), y: 23.0.into() }.into()).len() == 2); - assert_eq!(to_bus(Coordinate { x: 0.0.into(), y: 168.7601848778319.into() }.into(), Coordinate { x: 1.0.into(), y: 23.0.into() }.into()), vec![]); -} \ No newline at end of file + assert!( + to_bus( + Coordinate { + x: 0.0.into(), + y: 0.0.into() + } + .into(), + Coordinate { + x: 1.0.into(), + y: 23.0.into() + } + .into() + ) + .len() == 2 + ); + assert_eq!( + to_bus( + Coordinate { + x: 0.0.into(), + y: 168.7601848778319.into() + } + .into(), + Coordinate { + x: 1.0.into(), + y: 23.0.into() + } + .into() + ), + vec![] + ); +}