D3kjd3Di38lk323nnm 26 8 S-Bahn in Byteburg Diese Aufgabe scheint zunächst leicht lösbar zu sein, allerdings blähen sich unbedacht konstruierte Lösungen schnell auf. Die Struktur des Liniennetzes lässt sich ausnutzen, um die verschiedenen Fahrpreisregeln mit einer passenden Abfolge von Tests sukzessive abzuspalten. Das S-Bahn-Netz von »Byteburg« ist regelmäßig aufgebaut. Es gibt fünf Hauptlinien (»1« bis »5«) und eine Ringlinie. Linie »6« befindet sich im Bau und wird noch nicht benutzt. Die Stationen entlang der Hauptlinien sind von innen nach außen mit 1 bis 6 durchnummeriert. Im Zentrum liegt Station »00«. Die Ringlinie verbindet reihum die Stationen 3 der Hauptlinien. Die Stationen sind mit einem zweistelligen Code benannt: Die Zehnerstelle nennt die Linie, die Einerstelle die Stationsnummer, wie in der folgenden Skizze gezeigt: 66 56 16 15 14 65 55 5 13 63 54 61 52 45 46 4 51 11 00 41 42 43 44 25 23 12 62 53 26 1 6 64 22 2 24 21 31 32 33 34 3 35 36 Im Innenraum (grau hinterlegt) liegen das Zentrum und alle Stationen bis einschließlich der Ringlinie. Die übrigen Stationen liegen im Außenraum. Reinhard Schiedermeier / Klaus Köhler, Das Java-Praktikum, dpunkt.verlag, ISBN 978-3-89864-765-6 27 Schreiben Sie ein Programm ByteburgTarif, das die Fahrpreise nach den folgenden Regeln berechnet: 1. Eine Fahrt kostet 2 Taler1 (Beispiel: 11 nach 13). 2. Jede überquerte Zonengrenze kostet zusätzlich 1 Taler (Beispiel: 11 nach 14: 2 + 1 = 3 Taler). 3. Jede benutzte Endstation kostet zusätzlich 1 Taler (Beispiel: 16 nach 11: 2 + 1 (Zonengrenze) + 1 (Endstation) = 4 Taler). 4. Eine Fahrt zwischen zwei benachbarten Stationen kostet immer 1 Taler, auch wenn eine Zonengrenze dazwischen liegt oder eine Endstation benutzt wird (Beispiele: 13 nach 14, 15 nach 16 und 13 nach 53: jeweils 1 Taler). Beachten Sie, dass nach Linie 6 auch noch weitere Hauptlinien geplant sind mit jeweils 6 Stationen, die die Ringlinie an Station 3 schneiden. Auch nach Ausbauten bleiben die Hauptlinien im Uhrzeigersinn fortlaufend durchnummeriert. Ihr Programm soll mit möglichst wenig Aufwand für die erweiterten Streckennetze anpassbar sein. Ihr Programm ByteburgTarif liest die Codes von zwei Stationen von der Kommandozeile und gibt die Fahrtkosten aus. Beispiele: $ java ByteburgTarif 11 13 2 $ java ByteburgTarif 13 14 1 $ java ByteburgTarif 00 16 4 Lösung Eine wesentliche Anforderung ist die Flexibilität bezüglich des späteren Ausbaus um weitere Linien. Die Anzahl der Linien, zugleich die höchste Nummer einer Hauptlinie, wird in der Variablen lines gespeichert. Im weiteren Programm wird nur noch lines verwendet. Sollten neue Linie gebaut werden, muss lediglich der Startwert dieser Variablen angepasst werden. int lines = 5; ... 1 »Taler« wird hier als beliebige Fantasiewährung verwendet. 28 8 S-Bahn in Byteburg Zunächst werden die Kommandozeilenargumente verarbeitet und in Variablen gespeichert: int code1 = Integer.parseInt(args[0]); int code2 = Integer.parseInt(args[1]); ... Eine Fahrt kostet in jeder Richtung den gleichen Betrag. Die weitere Berechnung fällt leichter, wenn der kleinere und der größere Code festgestellt werden: int codemin = Math.min(code1, code2); int codemax = Math.max(code1, code2); ... Die Ziffern der Stationscodes können mit ganzzahliger Arithmetik getrennt werden. Linien- und Stationsnummern (Zehner- und Einerstellen der Codes) liegen damit einzeln vor: int int int int ... lineMin = codemin / 10; stationMin = codemin % 10; lineMax = codemax / 10; stationMax = codemax % 10; In der Variablen result wird der Fahrpreis berechnet: int result; ... Im Rest des Programms werden die verschiedenen Regeln zur Bestimmung des Preises absteigend nach Vorrang überprüft. Als Erstes sind Kurzfahrten zu behandeln. Eine Kurzfahrt kann entlang einer Hauptlinie erfolgen. In diesem Fall sind die Zehnerstellen gleich und die größere Einerstelle liegt um 1 über der kleineren, wie zum Beispiel 13 und 14: // Kurzfahrt entlang einer Hauptlinie if(lineMin == lineMax && stationMin + 1 == stationMax) result = 1; ... Eine Kurzfahrt kann auch entlang der Ringlinie verlaufen. Die Einerstellen sind beide 3, die Zehnerstellen unterscheiden sich um 1, wie zum Beispiel 43 und 53: // Kurzfahrt entlang der Ringlinie else if(stationMin == 3 && stationMax == 3 && lineMin + 1 == lineMax) result = 1; ... Reinhard Schiedermeier / Klaus Köhler, Das Java-Praktikum, dpunkt.verlag, ISBN 978-3-89864-765-6 29 Noch nicht berücksichtigt ist der Fall, dass auf der Ringlinie von Hauptlinie 1 zur höchsten Hauptlinie gefahren wird. Wieder sind die Einerstellen beide 3. Die kleinere Zehnerstelle ist 1; die größere entspricht der Anzahl Linien, wie zum Beispiel 13 und 53: // Kurzfahrt auf der Ringlinie von Linie 1 zur hoechsten Linie else if(stationMin == 3 && stationMax == 3 && lineMax == lines && lineMin == 1) result = 1; ... Schließlich kann eine Kurzfahrt zum Zentrum führen. Die Summe der Einerstellen ist in diesem Fall 1: // Kurzfahrt zum/vom Zentrum else if(stationMin + stationMax == 1) result = 1; ... In allen anderen Fällen gilt der Grundpreis von 2 Taler, zuzüglich möglicher Aufschläge: else { result = 2; ... // Grundpreis; Aufschläge folgen Eine Zonengrenze wird überquert, wenn eine Stationsnummer im Innenraum liegt und die andere im Außenraum: if(stationMin < 4 && stationMax >= 4) result++; else if(stationMin >= 4 && stationMax < 4) result++; ... Wenn beide Stationsnummern im Außenraum liegen, müssen die Liniennummern verglichen werden. Wenn sie verschieden sind, wurden zwei Zonengrenzen überquert, ansonsten keine: else if(stationMin >= 4 && result += 2; ... stationMax >= 4 && lineMax != lineMin) 30 8 S-Bahn in Byteburg Schließlich sind noch Endstationen aufschlagspflichtig. Unabhängig voneinander und unabhängig von den vorhergehenden Tests wird jede Stationsnummer mit 6 verglichen: if(stationMin == 6) result++; if(stationMax == 6) result++; } ... Am Ende wird der Fahrpreis ausgegeben: System.out.println(result); Hier der gesamte Algorithmus: Lege die Anzahl Linien lines fest Lies die beiden Stationscodes ein Berechne die kleinere Liniennummer lineMin und deren Stationsnummer stationMin Berechne die größere Liniennummer lineMax und deren Stationsnummer stationMax Sind die Liniennummern gleich und die Stationsnummern um 1 verschieden? Y Preis = 1 Y Sind beide Stationsnummern == 3 und die Liniennummern um 1 verschieden? (Kurzfahrt) Preis = 1 Y Sind beide Stationsnummern == 3 und lineMin == 1 und lineMax == lines? (Kurzfahrt) Preis = 1 Y Ist die Summe der Stationsnummern == 1? (Kurzfahrt) Preis = 1 Preis = 2 (Kurzfahrt) Ist stationMin < 4 und stationMax > 3? Y Preis um 1 Ist stationMin > 3 erhöhen und stationMax < 4? Y (Zonengrenze) Preis um 1 Sind beide erhöhen Stationsnummern > 3 (Zonengrenze) und die Liniennummern verschieden? Y Preis um 2 erhöhen (2 Zonengrenzen) N N N N N N N Ist stationMin == 6? Y Preis um 1 erhöhen (Endstation) N Ist stationMax == 6? Y Preis um 1 erhöhen (Endstation) N Preis ausgeben Reinhard Schiedermeier / Klaus Köhler, Das Java-Praktikum, dpunkt.verlag, ISBN 978-3-89864-765-6