Don't store bus position

This commit is contained in:
Arne Keller 2019-03-29 18:53:57 +01:00
parent ddc323eba7
commit 103e8c309c
2 changed files with 79 additions and 75 deletions

View File

@ -74,6 +74,7 @@ pub(crate) fn dump_latex_code(route: &[RunState], polys: &[Polygon]) {
println!("\\end{{tikzpicture}}");
}
/*
pub(crate) fn dump_route(house: Point, polys: &[Polygon], route: &Vec<RunState>) {
let (points, lines, route1, route2_start) = gen_params(house, route);
print!(
@ -243,3 +244,4 @@ pub(crate) fn generate_svg(
document.to_string()
}
*/

View File

@ -23,8 +23,8 @@ struct RunState {
delay: f64,
/// Lisas Position
pos: Point,
/// Position des Busses
bus: Point,
// Bisher zurückgelegte Strecke
total_distance: f64,
}
impl cmp::Eq for RunState {}
impl cmp::Ord for RunState {
@ -39,14 +39,17 @@ impl cmp::PartialOrd for RunState {
}
fn main() {
// 07:00: Bus ist 15 km entfernt
let start_time = NaiveTime::from_hms(7, 0, 0);
let bus = Point::new(0.0, -15000.0);
let bus_start = bus;
// 30 km/h -> 8.3 m/s
let bus_speed = 30.0 / 3.6;
let lisa_speed = 15.0 / 3.6;
// Zeitpunkt basierend auf Wartezeit in Sekunden berechnen
let delay_to_time = |delay| start_time + Duration::seconds((delay / bus_speed) as i64);
let calc_time = |total_distance, y| {
NaiveTime::from_hms(7, 30, 0)
- Duration::seconds(((total_distance * 2.0 - y) / bus_speed) as i64)
};
let calc_end_time = |total_distance, y| {
calc_time(total_distance, y) + Duration::seconds((total_distance / lisa_speed) as i64)
};
// Input einlesen (Lisas Haus und Hindernisse)
let data = input::read_input();
@ -62,18 +65,22 @@ fn main() {
// Startzustand: Lisa ist an ihrem Haus, Bus noch nicht losgefahren
let start = RunState {
pos: house,
bus: bus,
delay: max_possible_delay(bus, house),
delay: max_possible_delay(0.0, house),
total_distance: 0.0,
};
eprintln!("Theoretisches Maximum: {:?}", delay_to_time(start.delay));
let meeting_point = Point::new(0.0, house.y() + 30.0f64.to_radians().tan() * house.x());
eprintln!(
"Theoretisches Maximum: {:?}",
calc_time(distance(meeting_point, house), meeting_point.y())
);
// Zustände in Max-Heap sortieren
let mut states = BinaryHeap::new();
states.push(vec![start]);
// beste Lösung speichern
let mut best_delay = 0.0;
let mut best_delay = f64::NEG_INFINITY;
let mut best = vec![];
// Zwischenlösungen speichern
let save_prefix = "tmp_";
@ -84,6 +91,7 @@ fn main() {
// besten Zustand einlesen
let state = states.pop().unwrap();
let last = &state[0];
println!("last {:?}", last);
// neue Zustände
let mut all = vec![];
@ -98,79 +106,79 @@ fn main() {
.filter(|next| none_intersect(&polys, &Line::new(last.pos, *next)))
{
// Lisa könnte zu dieser Ecke rennen
let bus_next = last.bus.translate(0.0, distance(last.pos, next) * 2.0);
let delay = max_possible_delay(bus_next, next);
let total_distance = last.total_distance + distance(last.pos, next);
let delay = max_possible_delay(total_distance, next);
if delay > best_delay {
let mut route = state.clone();
route.insert(
0,
RunState {
pos: next,
bus: bus_next,
delay,
total_distance,
},
);
all.push(route);
}
}
// versuche, direkt zum Bus zu gehen
let bus = last.bus;
let range = to_bus(bus, last.pos);
if range.len() == 2 {
// Lisa trifft Bus mit 60°-Winkel
let next = Point::new(
0.0,
last.pos.y() + 30.0f64.to_radians().tan() * last.pos.x(),
);
let line = Line::new(last.pos, next);
// freier Weg?
if none_intersect(&polys, &line) {
let delay = line.end.y
- bus.y() - line.end_point().euclidean_distance(&line.start_point())
* 2.0;
if delay > best_delay {
// neue beste Wartezeit
let mut route = state.clone();
route.insert(
0,
RunState {
pos: next,
bus: next,
delay,
},
);
// Verbesserung anzeigen und speichern
eprintln!(
"Verbesserung: {:?} ({:?}+ Zustände verbleiben)",
delay_to_time(delay),
states.len()
);
best = route;
best.reverse();
best_delay = delay;
display::save_svg(
&format!("{}{}.svg", save_prefix, save_counter),
house,
&polys,
&best,
);
save_counter += 1;
}
// Lisa trifft Bus mit 60°-Winkel
let next = Point::new(
0.0,
last.pos.y() + 30.0f64.to_radians().tan() * last.pos.x(),
);
let line = Line::new(last.pos, next);
// freier Weg?
if none_intersect(&polys, &line) {
let line_length = line.end_point().euclidean_distance(&line.start_point());
let total_distance = last.total_distance + line_length;
let delay = max_possible_delay(total_distance, line.end_point());
if delay > best_delay {
// neue beste Wartezeit
let mut route = state.clone();
route.insert(
0,
RunState {
pos: next,
delay,
total_distance,
},
);
// Verbesserung anzeigen und speichern
eprintln!(
"Verbesserung: {:?} ({:?}+ Zustände verbleiben)",
calc_time(total_distance, line.end.y),
states.len()
);
best = route;
best.reverse();
best_delay = delay;
/*
display::save_svg(
&format!("{}{}.svg", save_prefix, save_counter),
house,
&polys,
&best,
);
*/
save_counter += 1;
}
// falls Bus überhaupt noch erreicht wird: neu gefundene Routen speichern
states.extend(all);
}
// neu gefundene Routen speichern
states.extend(all);
}
eprintln!("Finale Lösung:");
let route = best;
eprintln!("Startzeit: {:?}", delay_to_time(best_delay));
let last = route.last().unwrap();
eprintln!(
"Startzeit: {:?}",
calc_time(last.total_distance, last.pos.y())
);
eprintln!(
"Zielzeit: {:?}",
delay_to_time(route.last().unwrap().bus.y() - bus_start.y())
calc_end_time(last.total_distance, last.pos.y())
);
eprintln!("Treffpunkt: y={:.0}", route.last().unwrap().pos.y());
let mut length = 0.0;
let mut last = &house;
eprintln!("Treffpunkt: y={:.0}", last.pos.y());
eprintln!("Route:");
for s in &route {
if s.pos == house {
@ -187,11 +195,9 @@ fn main() {
);
}
eprintln!("x={:.02} y={:.02}", s.pos.x(), s.pos.y());
length += last.euclidean_distance(&s.pos);
last = &s.pos;
}
eprintln!("Länge: {:.0}m", length);
let seconds = length / (15.0 / 3.6);
eprintln!("Länge: {:.0}m", last.total_distance);
let seconds = last.total_distance / (15.0 / 3.6);
eprintln!("Dauer: {:02.0}:{:02.0}", seconds / 60.0, seconds % 60.0);
// beste Route grafisch ausgeben
display::dump_latex_code(&route, &polys);
@ -235,14 +241,10 @@ fn distance(a: Point, b: Point) -> f64 {
((a.x() - b.x()).powi(2) + (a.y() - b.y()).powi(2)).sqrt()
}
fn max_possible_delay(bus: Point, start: Point) -> f64 {
let x_l = start.x();
let y_l = start.y();
let x_b = bus.x();
assert_eq!(x_b, 0.0);
let y_b = bus.y();
y_l - (3.0 * x_l.powi(2)).sqrt() - y_b
fn max_possible_delay(total_distance: f64, lisa: Point) -> f64 {
let x_l = lisa.x();
let y_l = lisa.y();
y_l - (3.0 * x_l.powi(2)).sqrt() - total_distance * 2.0
}
/// Gehe direkt zum Bus. Gibt die Punkte zurück, bei denen Lisa nicht auf den Bus warten müsste.