ProgrammieraufgabenHier wird regelmäßig eine neue Programmieraufgabe gestellt, die dann gelöst werden soll und in Zusammenarbeit mit den Moderatoren auch besprochen werden kann.
Navigationssystem
Diskussion: Navigationssystem im Forum Programmieraufgaben, in der Kategorie Code Kitchen; Anzeige
Hallo,
ich hab gerade die Mails meiner alten Email Adresse angeschaut und dort hat Ivan Dolvich mir folgenden
Link ...
Diese Woche geht es um das Aussprechen von Zahlen, wie das zum Beispiel ein Auto-Navigationssystem für jede benötigte Entfernungsangabe fertigbringt.
Die freundliche Stimme unseres Auto-Navis sagt dabei nicht wie ein alter Blech-Roboter:
Eins Fünf Drei Kilometer zum Ziel
Nein, sie spricht die Zahl genauso aus wie wir:
Einhundertdreiundfünfzig Kilometer zum Ziel
Ein "weltraumtaugliches" Navigationssystem müsste noch viel größere Zahlen aussprechen können, z.B. die Zahl 12 345 678 987 654 321 als
zwölf Billiarden
dreihundertfünfundvierzig Billionen
sechshundertachtundsiebzig Milliarden
neunhundertsiebenundachtzig Millionen
sechshundertvierundfünfzigtausend
dreihunderteinundzwanzig
Sowas kann eigentlich jeder von uns. Aber wie sieht ein entsprechendes Programm aus? Da steckt der Teufel wie so oft im Detail!
Es sollen Zahlen bis zu 1er Million geschrieben werden
Wollt nur sagen, dass einfache Sprachausgabe auch kein großes Problem ist.
Man nehme das wave-Format mit PCM Codierung. Nehme alle Zahlen und Wörter wie "tausend", "und", .... auf. Dann Liest man diese Dateien einfach ein und klebt sie zu dem ganzen Wort zusammen.
<drei><hundert><ein><und><zwanzig>
Ich hab das mal mit der deutschen Sprache probiert a,b,c,ch,sch,....,z.
Ergebnis hört sich natürlich scheiße an, aber man kann einiges verstehen. Ist sehr lustig.
Mit Zahlen ist es vermutlich besser.
Daraus wird leider nichts. Durch die ganzen Soundfiles ist mein Programm nämlich auf etwa 800 MB angewachsen, ja, ich neige etwas zur Geschwätzigkeit.
Dafür gibt es bei mir jetzt richtiges Weltraumfeeling.
Hier ein kleiner Eindruck:l
greet.wav:
"Wir begrüßen Sie herzlich zu diesem Flug mit ihrem TaraTec Weltraum-Navigationssystem 9001. Bitte warten Sie einen Moment, während ich den günstigsten Kurs für Sie berechne ... bitte warten ... Kurs berechnet ... System initialisiert ... Startfreigabe erteilt ...
Nach Verlassen der Andockschleuse fliegen Sie bitte XXX.XXX AE geradeaus. Aufgrund der dichten Bebauung bertägt die erlaubte Höchstgeschwindigkeit bis zum Verlassen dieses Systems X AE/h."
Auf halber Strecke zwischen zwei zufälligen Kurskorrekturen (die zu programmieren ja eigentlich gefordert war) gibt es bei mir zufällig eingestreut Reklame, z.B.
Adv3.wav:
"Fliegen Sie beim nächsten Mal nicht ohne unser TaraCorp-Sightseeing-Addon 2.0, das für Sie eine Route entlang optisch besonders reizvoller Nebel und interessanter Sternenkonstellationen berechnet. Erhältlich in jeder TaraCorp-Niederlassung des Quadranten."
Wenn es Morgen wieder so scheußlich regnet programmiere ich noch einen kleinen optischen Eindruck dazu, es gab ja früher mal diesen Starfield-Bildschirmschoner, ist hoffentlich nicht zu schwer.
Hi Hackers, hier ist mein Programm in Groovy. Geht die Zahl in 3-stelligen Teilen durch und konvertiert die Teile. Gruß, Ivan
Code:
digits = ["", "ein", "zwei", "drei", "vier", "fünf", "sechs", "sieben", "acht", "neun"]
rounds = ["", "tausend", "million", "milliarde", "billion"]
void sayNum(String num)
{
LinkedList result = new LinkedList() // Ergebnis-Liste mit den Teilen
String part // der aktuelle 3-stellige Teil
Integer i = num.size() // markiert den Anfang des akt. Teils
Integer r = 0 // die aktuelle Runde (tausend, million etc.)
// die Teile von hinten nach vorne bearbeiten
while ((i -= 3) >= 0) {
part = getPart(num[i..i+2].toInteger())
if (part != "")
result.addFirst(part + rounds[r])
r++
}
// gibt es noch ein Teil mit weniger als 3 Stellen?
if (i > -3) {
part = getPart(num[0..i+2].toInteger()) + rounds[r]
result.addFirst(part)
}
result.each { println it }
println ""
}
/** Konvertiert eine 3-stellige Zahl: XXX */
String getPart(Integer p)
{
Integer p__X = (p % 10) // die letzte ziffer
Integer p_XX = (p % 100) // die letzten 2 ziffern
Integer pX__ = p.intdiv(100) // die erste Ziffer
Integer p_X_ = p.intdiv(10) // die mittlere Ziffer
Integer p_X0 = p_XX - p__X // 10, 20, 30 etc.
// ist die Zahl 3-stellig?
if (p in 100..999)
return "${digits[pX__]}hundert${getPart(p_XX)}"
// Zahl hat 1 oder 2 stellen
switch (p) {
case 0..9: return "${digits[p]}"; break
case 10: return "zehn"; break
case 11: return "elf"; break
case 12: return "zwölf"; break
case 13..19: return "${digits[p__X]}zehn"; break
case 20: return "zwanzig"; break
case 30: return "dreißig"; break
case 40: return "vierzig"; break
case 50: return "fünfzig"; break
case 60: return "sechzig"; break
case 70: return "siebzig"; break
case 80: return "achtzig"; break
case 90: return "neunzig"; break
default: return "${digits[p__X]}und${getPart(p_X0)}"
}
}
sayNum("18") // achtzehn
sayNum("35") // fünfunddreißig
sayNum("2402") // zweitausend vierhundertzwei
sayNum("32322402") // zweiunddreißigmillion dreihundertzweiundzwanzigtausend vierhundertzwei
sayNum("2500402") // zweimillion fünfhunderttausend vierhundertzwei
sayNum("5000402") // fünfmillion vierhundertzwei
sayNum("250000402") // zweihundertfünfzigmillion vierhundertzwei