Navigationssystem

Hallo,

ich hab gerade die Mails meiner alten Email Adresse angeschaut und dort hat Ivan Dolvich mir folgenden
Link geschickt:

http://www-i1.informatik.rwth-aachen.de/~algorithmus/algo4.php

Hier die Aufgabe:

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


Viel Spaß
Xalon
 
Grundsätzlich würde ich sagen, alle zahlen bis 999.999.999 oder aber halt bis ausschließlich 1 Millionen... naja egal :)
Code:
#include <iostream>

using namespace std;

string worte[]={"ein", "zwei", "drei", "vier", "fuenf", "sechs", "sieben", "acht", "neun", "zehn", "elf", "zwoelf", "dreizehn", "vierzehn", "fuenfzehn", "sechzehn", "siebzehn", "achtzehn", "neunzehn"};

string wortz[]={"zwanzig", "dreissig", "vierzig", "fuenfzig", "sechzig", "siebzig", "achtzig", "neunzig"};

void h(int t)
{
	int h = (t / 100) % 10;
	int z = t % 100;
	if (h > 0)
		cout << worte[h - 1] << "hundert";
	if (z > 0) {
		if (z >= 20) {
			int e = z % 10;
			if (e > 0)
				cout << worte[e - 1];
			if (z / 10 > 0 && e > 0)
				cout << "und";
			if (z / 10 > 0)
				cout << wortz[z / 10 - 2];
		}
		else
			cout << worte[z - 1];
	}
}

int main()
{
	unsigned long i;
	cout << "Zahl: " << flush;
	cin >> i;
	if (i < 1 || i > 999999999) {
		cerr << "Out of range" << endl;
		return 1;
	}

	cout << "Noch:\n";

	if (i >= 1000000) {
		h(i / 1000000);
		cout << " Millionen\n";
	}
	if (i % 1000000 >= 1000) {
		h((i % 1000000) / 1000);
		cout << "tausend\n";
	}
	if (i % 1000 >= 1) {
		h(i % 1000);
		cout << "\n";
	}
	cout << "Kilometer" << endl;

	return 0;
}
Code:
Zahl: 893456723
Noch:
achthundertdreiundneunzig Millionen
vierhundertsechsundfuenfzigtausend
siebenhundertdreiundzwanzig
Kilometer
 
PHP:
<?php
$zahl = 654728;

$zahlen1 = array("ein", "zwei", "drei", "vier", "fuenf", "sechs", "sieben", "acht", "neun", "zehn", "elf", "zwoelf", "dreizehn", "vierzehn", "fuenfzehn", "sechzehn", "siebzehn", "achtzehn", "neunzehn");
$zahlen2 = array("zwanzig", "dreissig", "vierzig", "fuenfzig", "sechzig", "siebzig", "achtzig", "neunzig");
$zahl1 = "hundert";
$zahl2 = "tausend";
$zahl3 = "Million";

if ($zahl == 0) {
  print "null";
}
if ($zahl == 1) {
  print "eins";
}
if ($zahl > 1) {
  if ($zahl < 20) {
  	print $zahlen1[($zahl-1)];
	} else {
	  if ($zahl < 100) {
		  $zehner = substr($zahl,0,1);
			$einer = substr($zahl,1,1);
			if ($einer == 0) {
			  print $zahlen2[($zehner-2)];
			} else {
  			print $zahlen1[($einer-1)]."und".$zahlen2[($zehner-2)];
			}
		} else {
		  if ($zahl < 1000) {
			  $einer = substr($zahl,2,1);
				$zehner = substr($zahl,1,1);
				$hunderter = substr($zahl,0,1);
				if ($einer == 0) {
				  if ($zehner == 0) {
					  print $zahlen1[$hunderter-1].$zahl1;
					} else {
				    print $zahlen1[$hunderter-1].$zahl1.$zahlen2[($zehner-2)];
					}
				} else {
				  if ($zehner == 0) {
					  print $zahlen1[$hunderter-1].$zahl1.$zahlen1[($einer-1)];
          } else {
    				print $zahlen1[$hunderter-1].$zahl1.$zahlen1[($einer-1)]."und".$zahlen2[($zehner-2)];
					}
				}
			} else {
			  if ($zahl < 1000000) {
				  $tausender = substr($zahl,0,strlen($zahl)-3);
					$hunderter = substr($zahl,strlen($zahl)-3,1);
					$zehner = substr($zahl,strlen($zahl)-2,1);
					$einer = substr($zahl,strlen($zahl)-1,1);
          if ($tausender < 20) {
  	        $tausender2 = $zahlen1[($tausender-1)];
	        } else {
	          if ($tausender < 100) {
		          $zehner2 = substr($tausender,0,1);
			        $einer2 = substr($tausender,1,1);
			        if ($einer == 0) {
			          $tausender2 = $zahlen2[($zehner2-2)];
			        } else {
  			        $tausender2 = $zahlen1[($einer2-1)]."und".$zahlen2[($zehner2-2)];
		 	        }
		        } else {
		          if ($tausender < 1000) {
			          $einer2 = substr($tausender,2,1);
				        $zehner2 = substr($tausender,1,1);
				        $hunderter2 = substr($tausender,0,1);
				        if ($einer2 == 0) {
				          if ($zehner2 == 0) {
					          $tausender2 = $zahlen1[$hunderter2-1].$zahl1;
					        } else {
				            $tausender2 = $zahlen1[$hunderter2-1].$zahl1.$zahlen2[($zehner2-2)];
					        }
				        } else {
				          if ($zehner2 == 0) {
					          $tausender2 = $zahlen1[$hunderter2-1].$zahl1.$zahlen1[($einer2-1)];
                  } else {
    				        $tausender2 = $zahlen1[$hunderter2-1].$zahl1.$zahlen1[($einer2-1)]."und".$zahlen2[($zehner2-2)];
					        }
				        }
							}
						}
					}
			    if ($einer == 0) {
				    if ($zehner == 0) {
						  if ($hunderter == 0) {
					      print $tausender2.$zahl2;
					    } else {
				        print $tausender2.$zahl2."\n".$zahlen1[$hunderter-1].$zahl1;
							}
					  } else {
						  if ($hunderter == 0) {
					      print $tausender2.$zahl2."\n".$zahlen2[($zehner-2)];
					    } else {
							  print $tausender2.$zahl2."\n".$zahlen1[$hunderter-1].$zahl1.$zahlen2[($zehner-2)];
							}
						}
					} else {
					  if ($zehner == 0) {
						  if ($hunderter == 0) {
							  print $tausender2.$zahl2."\n".$zahlen1[($einer-1)];
							} else {
							  print $tausender2.$zahl2."\n".$zahlen1[$hunderter-1].$zahl1.$zahlen1[($einer-1)];
							}
						} else {
						  if ($hunderter == 0) {
							  print $tausender2.$zahl2."\n".$zahlen1[($einer-1)]."und".$$zahlen2[($zehner-2)];
							} else {
							  print $tausender2.$zahl2."\n".$zahlen1[$hunderter-1].$zahl1.$zahlen1[($einer-1)]."und".$zahlen2[($zehner-2)];
							}
						}						
					}
			  } else {
				  if ($zahl == 1000000) {
					  print "eine ".$zahl3;
					}
				}
			}
		}
	}
}

?>

Das ist meine Version in PHP, ein bisschen umstaendlich geschrieben aber es funktioniert.

Junior

EDIT : Ich hab das script ein wenig geaendert jetzt gehen alle Zahlen von -999999999 bis 999999999.

PHP:
<?php
$zahl = -123234442;

$zahlen1 = array("ein", "zwei", "drei", "vier", "fuenf", "sechs", "sieben", "acht", "neun", "zehn", "elf", "zwoelf", "dreizehn", "vierzehn", "fuenfzehn", "sechzehn", "siebzehn", "achtzehn", "neunzehn");
$zahlen2 = array("ein", "zwei", "drei", "vier", "fuenf", "sechs", "sieben", "acht", "neun");
$zahlen3 = array("zwanzig", "dreissig", "vierzig", "fuenfzig", "sechzig", "siebzig", "achtzig", "neunzig");

function bis20 ($number) {
  global $zahlen1;
 	if ($number > 0) {
    return($zahlen1[$number-1]);
	}
}

function bis100 ($number) {
  global $zahlen2;
	global $zahlen3;
  if ($number < 20) {
	  return(bis20($number));
	} else {
	  $zehner = substr($number, 0, 1);
		$einer = substr($number, 1, 1);
	  if ($einer == 0) {
		  return($zahlen3[($zehner-2)]);
		} else {
  		return($zahlen2[($einer-1)]."und".$zahlen3[($zehner-2)]);
		}		
	}
}

function bis1000 ($number) {
  global $zahlen2;
  if ($number < 100) {
	  return(bis100($number));
	} else {
	  $hunderter = substr($number, 0, 1);
		$andere = substr($number, 1, (strlen($number)-1));
		$i = bis100($andere);
		return($zahlen2[($hunderter-1)]."hundert".$i);
	}
}

function bis1000000 ($number) {
	if ($number < 1000) {
	  return(bis1000($number));
	} else {
	  $tausender = substr($number, 0, (strlen($number)-3));
		$andere = substr($number, (strlen($number)-3), 3);
		$i = bis1000($tausender);
		$j = bis1000($andere);
		return($i."tausend"."\n".$j);
	}
}

function bis1Millarden ($number) {
  if ($number < 1000000) {
	  return(bis1000000($number));
	} else {
	  $Millioner = substr($number, 0, (strlen($number)-6));
		$andere = substr($number, (strlen($number)-6), 6);
		$i = bis1000($Millioner);
		$j = bis1000000($andere);
		return($i." Millionen"."\n".$j);	  
	}
}

if ($zahl == 0) {
  print "0 = null";
} else {
  if ($zahl > 0) {
    if ($zahl < 1000000000) {
      print $zahl." = "."\n".bis1Millarden($zahl);
	  } else {
	    print "Die Zahl ist zu gross.";
	  }
	}
	if ($zahl < 0) {
	  $zahl = substr($zahl,1,(strlen($zahl)-1));
    if ($zahl < 1000000000) {
      print "-".$zahl." = "."\n"."-".bis1Millarden($zahl);
	  } else {
	    print "Die Zahl ist zu klein.";
	  }
	} 
}

?>
 
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.
 
@ Corni:

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.

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.

Hat wirklich Spaß gemacht.
 
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
 
Zurück
Oben