Zahlenreihenfolge erstellen

Hallo,

ich versuche folgendes, gelingt mir aber nicht so:

Eine Zahlenreihenfolge (in einem for-loop) in vierstellige Buchstabenblöcke konventieren, unter Verwendung der 26 „normalen“ Buchstabel (a bis z, ohne Umlaute)

Das Ergebnis sollte dann folgendes sein:

1 = aaaa
2 = aaab

26 = aaaz
27 = aaba

etc.

Wie kriege ich sowas hin ? ODer gibt’s da evtl. sogar eine Funktion ?

Danke & Gruss
Roger

Hallo Roger,

Eine Zahlenreihenfolge (in einem for-loop) in vierstellige
Buchstabenblöcke konventieren, unter Verwendung der 26
„normalen“ Buchstabel (a bis z, ohne Umlaute)

Das Ergebnis sollte dann folgendes sein:

1 = aaaa
2 = aaab

26 = aaaz
27 = aaba

Wenn ich das richtig verstanden habe sollte es so gehen:

Procedure TTestForm.Button1Click(Sender: TObject);
Var
 i, j, k, l : Integer;
 s : String;
 tf : TextFile;
Begin
 Screen.Cursor := crHourGlass;
 Try
 AssignFile( tf, 'c:\testch.txt' );
 Rewrite( tf );
 s := ' ';
 For i := 1 to 26 do Begin
 s[1] := Char( i + 96 );
 For j := 1 to 26 do Begin
 s[2] := Char( j + 96 );
 For k := 1 to 26 do Begin
 s[3] := Char( k + 96 );
 For l := 1 to 26 do Begin
 s[4] := Char( l + 96 );
 WriteLn( tf, s );
 End;
 End;
 End;
 End;
 System.Close( tf );
 Finally
 Screen.Cursor := crDefault;
 End;
End;

Gruß
Christian

Hallo,

vielleicht sollte man das Problemm besser mit einer rekursiven Funktion lösen, da das flexibler ist. Ansonsten ist es schneller, das i + 96 in die for-Anweisung zu übernehmen ( for i := 97 to 122). Die Addition ist zwar schnell, sie muss aber einige hundertausend mal ausgeführt werden. Außerdem sollte das System.Close (warum eigentlich nicht „CloseFile“?) zwingend in den finally-Abschnitt. Sonst bleibt bei einem Fehler eine offene Datei zurück.

Gruss, Niels

Procedure TTestForm.Button1Click(Sender: TObject);
Var
i, j, k, l : Integer;
s : String;
tf : TextFile;
Begin
Screen.Cursor := crHourGlass;
Try
AssignFile( tf, ‚c:\testch.txt‘ );
Rewrite( tf );
s := ’ ';
For i := 1 to 26 do Begin
s[1] := Char( i + 96 );
For j := 1 to 26 do Begin
s[2] := Char( j + 96 );
For k := 1 to 26 do Begin
s[3] := Char( k + 96 );
For l := 1 to 26 do Begin
s[4] := Char( l + 96 );
WriteLn( tf, s );
End;
End;
End;
End;
System.Close( tf );
Finally
Screen.Cursor := crDefault;
End;
End;

Gruß
Christian

Hallo Niels,

vielleicht sollte man das Problemm besser mit einer rekursiven
Funktion lösen, da das flexibler ist.

Stimmt. Mach mal

Ansonsten ist es
schneller, das i + 96 in die for-Anweisung zu übernehmen (
for i := 97 to 122). Die Addition ist zwar schnell, sie muss
aber einige hundertausend mal ausgeführt werden. Außerdem
sollte das System.Close (warum eigentlich nicht „CloseFile“?)
zwingend in den finally-Abschnitt. Sonst bleibt bei einem
Fehler eine offene Datei zurück.

Hast völlig Recht! Ich habe das nur mal so eben auf die schnelle runter geklappert… Sollte auch mehr ein Denkanstoß sein.
(Bei mir braucht die Funktion übrigens deutlich weniger als 1 Sekunde).

Warum System.Close? Weil ich das seit 20 Jahren so mache :smile:
Für angehende Komposties wie mich hat Borland ja die alten Funktionen belassen…

Gruß
Christian

Hallo Christian,

vielleicht sollte man das Problemm besser mit einer rekursiven
Funktion lösen, da das flexibler ist.

Stimmt. Mach mal

Bitte schön:

implementation

{$R \*.dfm}
var
 OutDatei: TextFile;

procedure CreateList(Len, posit: Integer; TestString: String);
var
 i: Integer;

begin
 if Length(TestString) 


Gruß, Niels

Hallo Niels,

Bitte schön:
[…]

Danke :smile:
Deine Variante ist gut. Auf jeden Fall sehr flexibel.
Ich verstehe nur noch nicht, warum sie ca. 22% langsamer ist. Eigentlich sollte sie schneller sein. Verstehst Du das?

Gruß
Christian

Hallo,

Ich verstehe nur noch nicht, warum sie ca. 22% langsamer ist.
Eigentlich sollte sie schneller sein.

eigentlich nicht. Es war mir von vorneherein klar, dass das langsamer wird. Das ist der Preis, der für die Flexibilität gezahlt werden muss. Es sind zusätzliche Abfragen drin, die du bei deinem Code nicht brauchst, weil du nur einen einzigen Fall abdeckst. Hinzu kommt der Zeitverlust durch die ständige Übergabe der drei Parameter. Letzteres ließe sich ändern indem man zB „TestString“ und „Len“ unitweit deklariert und nicht als übergibt. Außerdem muss bei jedem Aufruf der Funktion die Variable „i“ auf dem Stack neu erzeugt und dann wieder entfernt werden. Auch diese könnte man global deklarieren und damit etwas Zeit sparen.

Es ist wie immer beim Programmieren. Die Vorgaben Geschwindigkeit, Übersichtlichkeit des Codes, Wiederverwendbarkeit etc lassen sich kaum alle unter einen Hut bringen ohne an einigen Stellen Abstriche zu machen. Insofern ist dein Code (mit den kleinen Verbesserungen) sicher das Optimum für den Fall, dass die Geschwindigkeit im Vordergrund steht.

Ach so: Lass mal das Schreiben in die Datei weg und vergleich dann. Erst dann siehst du, wie schlapp meine Version tatsächlich ist.

Wenn ich mein Programm wie oben beschrieben ändere, ist es (ohne Dateischreiben) doppelt so schnell wie meine ursprüngliche Version.

Gruss, Niels

1 = aaaa
2 = aaab

26 = aaaz
27 = aaba

Hallo,
ich versuch’s mal mathematisch - den Delphi-Code kriegst’ vielleicht
selber zusammen.
Eingabe : x (die umzurechnende Zahl)
0. Zeichenkette := „“

  1. r := x mod 26
  2. d := x div 26
  3. Zeichenkette := Char(r + ‚a‘) + Zeichenkette
  4. x := d
  5. x == 0 ? wenn nein, dann gehe zu 1.

Gruß
Thorsten