AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Erstellung einer Funktion

Ein Thema von Mo53 · begonnen am 3. Jun 2021 · letzter Beitrag vom 10. Jun 2021
Antwort Antwort
Seite 1 von 2  1 2      
Michael II

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
778 Beiträge
 
Delphi 11 Alexandria
 
#1

AW: Erstellung einer Funktion

  Alt 6. Jun 2021, 00:47
Da der zu durchsuchende String beim Aufruf der Funktion vollständig bekannt ist: Verzichte möglichst auf "teure" Additionen von Strings: Es macht zum Beispiel genau 0 Sinn, wenn du jede auftretende Ziffernfolge aufaddierst, diese abspeicherst, nur um sie später wieder zu verwerfen, wenn du eine längere Folge gefunden hast. - Stringoperationen kosten viel, Integerops wenig.

Merke dir also nur Start und Länge der jeweils "maximalen" Folge und nicht den Zeichensalat.

Beispiel:
A0022DJIOE390220DJIWOEDJ390J3

An Position i=1 liest du A und tust nix.
An i=2 liest du 0. Du merkst dir start=2, dann liest du 0, 2, 2.
Bei i=6 liest du "D"; also keine Ziffer mehr. Du hast die erste Ziffernfolge gefunden: Laenge = i-start = 6-2 = 4. Du merkst dir die momentan längste Folge, indem du maxstart=start=2 und maxlaenge=laenge=4 speicherst.

Es folgen keine Ziffern bis und mit i=10. Du tust nix.
Bei i=11 liest du eine 3. Du merkst dir start=11. Bei i=17 "D" ist die Ziffernfolge zu Ende. Die Laenge = i-start beträgt Laenge=17-11 = 6. Laenge=6 ist grösser als die bisherige maxlaenge=4 => Du merkst dir maxstart=11 maxlaenge=6 usw.

Am Ende weisst du, dass eine längste Folge bei maxstart beginnt und maxlaenge lang ist.

Auf dem zehnjährigen 2,2GHz Prozessor i7-3620QM können so 1000 1Mio Zeichen lange Strings in 4,4 Sekunden durchsucht werden.

Delphi-Quellcode:
function LaengsteZiffernFolgeDerWelt( s : string ) : string;
var
  len_s,
  maxlaenge, maxstart, laenge, start, i: Integer;

begin
  start := 0;
  maxlaenge := 0;
  maxstart := 0;
  i := 1;
  len_s := length(s);
  while i <= len_s do
  begin
    if ( s[i] in ['0'..'9'] ) then
    begin
      if start = 0 then start := i
    end
    else
    begin
      if start > 0 then
      begin
        laenge := i-start;
        if laenge > maxlaenge then
        begin
          maxlaenge := laenge;
          maxstart := start;
        end;
        start := 0;
      end;
    end;
    inc(i);
  end;

  if start > 0 then // *
  begin
    laenge := i-start;
    if laenge > maxlaenge then
    begin
      maxlaenge := laenge;
      maxstart := start;
    end;
  end;

  if maxlaenge > 0 then Result := Copy( s, maxstart, maxlaenge )
  else Result := '';
end;
* Wenn s[length(s)] eine Ziffer ist, dann müssen wir noch prüfen, ob diese letzte Ziffernfolge in s die längste ist. Du könntest auch gleich nach dem "begin" der Funktion an s ein "Nichtzifferzeichen" anhängen. Also s := s+'A'; Dann kannst du auf diesen Check (if start > 0 then begin... end) verzichten. In den allermeisten Fällen wäre das sicher auch ok...
Michael Gasser
  Mit Zitat antworten Zitat
Amateurprofi

Registriert seit: 17. Nov 2005
Ort: Hamburg
1.111 Beiträge
 
Delphi XE2 Professional
 
#2

AW: Erstellung einer Funktion

  Alt 6. Jun 2021, 04:35
Oder so:
Delphi-Quellcode:
FUNCTION LongestCipherSequence(const S:String):Integer;
var N:Integer; P:PChar;
begin
   Result:=0;
   P:=PChar(S);
   if P<>Nil then
      repeat
         case P^ of
            #0 : Break;
            '0'..'9' : begin
                           N:=1;
                           Inc(P);
                           while P^ in ['0'..'9'] do begin
                              Inc(N);
                              Inc(P);
                           end;
                           if N>Result then Result:=N;
                        end;
            else Inc(P);
         end;
      until False;
end;
Oder um Michaels Hinweis aufzugreifen:

Delphi-Quellcode:
FUNCTION LongestCipherSequence2(const S:String):Integer;
var P,PS:PChar;
begin
   Result:=0;
   P:=PChar(S);
   if P<>Nil then
      repeat
         case P^ of
            #0 : Break;
            '0'..'9' : begin
                           PS:=P;
                           Inc(P);
                           while P^ in ['0'..'9'] do Inc(P);
                           if P-PS>Result then Result:=P-PS;
                        end;
            else Inc(P);
         end;
      until False;
end;
Delphi-Quellcode:
PROCEDURE TMain.Test;
const S='1A22B333C4444D55555E';
begin
   ShowMessage(IntToStr(LongestCipherSequence(S)));
   ShowMessage(IntToStr(LongestCipherSequence2(S)));
end;
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat
Michael II

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
778 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Erstellung einer Funktion

  Alt 6. Jun 2021, 09:51
Nicht "oder so", sondern nur so wie Profi .
Es gibt allerdings einen Unterschied: #37 liefert wie in #26 verlangt den String, #38 die Position.
Zeitlich bewegen wir uns im gleichen Rahmen. Profi nutzt aus, dass Strings Null-terminiert sind, muss aber die =#0 Abfrage bei jedem Zeichen ausführen, #37 "einmal" am Schluss *.
Michael Gasser

Geändert von Michael II ( 6. Jun 2021 um 12:14 Uhr)
  Mit Zitat antworten Zitat
Mo53

Registriert seit: 16. Mai 2021
59 Beiträge
 
Delphi 10.3 Rio
 
#4

AW: Erstellung einer Funktion

  Alt 6. Jun 2021, 11:11
Wirklich sehr Interessant, Vielen Dank für eure Mühe
  Mit Zitat antworten Zitat
Mo53

Registriert seit: 16. Mai 2021
59 Beiträge
 
Delphi 10.3 Rio
 
#5

AW: Erstellung einer Funktion

  Alt 6. Jun 2021, 12:37
Kann man das denn so regeln das die längste Ziffernfolge auf Basis des Strings bestimmt wird aber ein word-Wert zurückgegeben wird also z.B. wenn die längste Ziffernfolge 012 ist wird eine 12 zurückgegeben ?
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.592 Beiträge
 
Delphi 7 Professional
 
#6

AW: Erstellung einer Funktion

  Alt 6. Jun 2021, 13:10
Ja, aber die hier genannten führenden Nullen gehen dabei verloren:
Zitat:
Die längste Ziffernfolge muß nicht unbedingt die größte Zahl in s sein! Eine so gefundene Ziffernfolge darf auch mit einer oder mehreren '0' beginnen.
Man könnte aus dem String die führenden Nullen entfernen, man könnte den String in eine Zahl umwandeln.

Nur: Soll die längste Ziffernfolge zurückgegeben werden oder ihr nummericher Wert?

Die Frage ist also: Was ist jetzt bitteschön die Aufgabenstellung und welche Syntaxelemente wurden bisher im Lehrstoff vermittelt und welche Syntaxelemente dürfen für die Lösung der Aufgabe verwendet werden?

Soll das Problem mit while, for, repeat, if und / oder case gelöst werden, dürfen Arrays genutzt werden, ist die Nutzung von Zeigern erlaubt? Dürfen alle delphiseitig möglichen Datentypen genutzt werden oder nur die bisher im Lehrstoff vermittelten? Sind Typkonvertierungen (beliebiger Form) Teil des Unterrichtsstoffes, ...?

Sprich: Darf alles genutzt werden, was mit Delphi möglich ist oder gibt es irgendwelche klar definierten Vorgaben?
Delphi-Quellcode:
// function longestNumber(s : string) : byte;
// Rückgabetype der Funktion ändern, da ja eine Zeichenfolge zurückgegeben werden soll.
function longestNumber(s : string) : String;
var
  run, number, longNum : byte;
  NumberStr, longNumStr : String; // zwei zusätzliche Variabeln.
  begin
    // Zu Beginn alle Variabeln initialisieren, um definierte Ausgangswerte zu haben.
    longNum := 0;
    longNumStr := '';
    number := 0;
    NumberStr := '';
    for run := 1 to length(s) do
    begin
      case s[run] of
       '0'..'9' : begin
                    inc(number);
                    NumberStr := NumberStr + s[run]; // Zusätzlich die Ziffer an den String anfügen.
                  end;
      else
        begin
          if number > longNum then
          begin
            longNum := number;
            LongNumStr := NumberStr; // zusätzlich den bisher längsten String speichern.
          end;
          number := 0;
          NumberStr := ''; // zusätzlich den String leeren.
        end;
      end;
    end;
    if number > longNum then
    begin
      longNum := number;
      LongNumStr := NumberStr; // zusätzlich den bisher längsten String speichern.
    end;
    // longestNumber := longNum;
    // Da eine Zeichenfolge zurückgegeben werden soll und der Typ der Funktion
    // entsprechend geändert wurde, geben wir hier die Zeichenfolge zurück.
    longestNumber := longNumStr;
  end;
Und ja: Unter Performanzgesichtspunkten mag das eventuell (messbar?) langsamer sein. Und mit PChar und Zeigern geht es eventuell auch eleganter, ...

Frage ist nur: Was bitte wurde bisher im Unterricht vermittelt und kann von daher für die Lösungssuche zur Anwendung kommen?
  Mit Zitat antworten Zitat
Mo53

Registriert seit: 16. Mai 2021
59 Beiträge
 
Delphi 10.3 Rio
 
#7

AW: Erstellung einer Funktion

  Alt 6. Jun 2021, 14:05
Was ist jetzt bitteschön die Aufgabenstellung und welche Syntaxelemente wurden bisher im Lehrstoff vermittelt und welche Syntaxelemente dürfen für die Lösung der Aufgabe verwendet werden?
Es sind verschiedene Prozeduren und Funktionen samt zugehörigen Testfällen zu erstellen, die mit Strings arbeiten. Diese sollen sich wo immer möglich auch gegenseitig aufrufen, um den zu erstellenden Code kurz zu halten (Codeverdopplung ist zu vermeiden!).
Beachtet bei der Entwicklung die vorgesehene Reihenfolge (s.u.): Erstellt ERST die Testfälle und DANN die eigentlichen Funktionen und Prozeduren! Somit macht Ihr Euch rechtzeitig vorab Gedanken, was genau eine Funktion/Prozedur können soll und schreibt nicht unnötig viel Quellcode.

Zusätzlich zum Hauptprogramm sind mehrere Prozeduren und Funktionen zu erstellen

Eine davon ist

''function longestNumber(s : string) : word;
Sucht die längste Ziffernfolge (aus Ziffern von '0' bis '9') im String s. Gibt es mehrere gleich lange, wird davon die erste zurückgegeben. Sind keine Ziffern enthalten, gibt die Funktion den Wert 0 zurück.
Hinweis: Die längste Ziffernfolge muß nicht unbedingt die größte Zahl in s sein! Eine so gefundene Ziffernfolge darf auch mit einer oder mehreren '0' beginnen.''

bei der ich Probleme habe, das restliche Programm und die restlichen sechs Funktionen/Prozeduren sind fertig.

Arrays dürfen nicht verwendet werden und die vorgegebene Funktion ''function longestNumber(s : string) : word'' darf nicht verändert werden also der Datentyp word muss word bleiben.
Ansonsten ist es uns überlassen was wir verwenden.

  Mit Zitat antworten Zitat
Michael II

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
778 Beiträge
 
Delphi 11 Alexandria
 
#8

AW: Erstellung einer Funktion

  Alt 6. Jun 2021, 14:10
Die Frage ist also: Was ist jetzt bitteschön die Aufgabenstellung und welche Syntaxelemente wurden bisher im Lehrstoff vermittelt und welche Syntaxelemente dürfen für die Lösung der Aufgabe verwendet werden?
Es geht hier doch nicht um echte Aufgaben; mo will lediglich eine kleine Untermenge von DP Menschen unterhalten .

Zitat:
Und ja: Unter Performanzgesichtspunkten mag das eventuell (messbar?) langsamer sein. Und mit PChar und Zeigern geht es eventuell auch eleganter, ...
Ich hatte auch an Pointer gedacht, vermutete aber, dass diese wohl noch nicht Teil von mos Delphi-Welt sein dürfen und habe keine verwendet. Punkto Performance gewinnst du hier kaum was oder gar nix.

Zur Performance: Deine Lösung hängt v.a. wegen NumberStr := NumberStr + s[run]; erheblich vom Eingabewert ab und ist v.a. wegen dieser Zeile etwas komplexer: Wenn in den 1000 x "1Mio-Strings Aufrufen" die Eingabe gar keine Ziffern enthält liegt meine bei 990ms und deine bei 4400ms. Bei 60% Ziffern 4,3sec, deine 31sec. Wenn nur Ziffern vorkommen, dann liegt meine bei 1.6sec und deine bei (erwartet hohen) 40sec.

NumberStr := NumberStr + s[run]; ist unnötig und langsam. mo soll sich nur Start und Länge des jeweiligen Maximums merken. Das reicht um am Ende der Suche die längste Ziffernfolge zu "berechnen" (entweder mit Copy oder wenn Copy nicht erlaubt ist mit for i:= start to ...) und auszugeben.

Nebenbei: Wegen run: Byte kann deine Routine nur kurze Strings verarbeiten.

Hinweis: Die längste Ziffernfolge muß nicht unbedingt die größte Zahl in s sein! Eine so gefundene Ziffernfolge darf auch mit einer oder mehreren '0' beginnen.''
mo, du wolltest die Strings in Zahlen umwandeln. Das geht mit Standard-Integer Typen nur gut, wenn der numerische Wert der gefundenen Folge nicht allzu gross ist: WORD zum Beispiel ist 16 Bit breit und kann nur Werte 0..65535 aufnehmen. Für die Umwandlung: Suche im Help von Delphi nach strtoint(), strtointdef() oder schreib dir als Übung eine Funktion, welche dies tut.

Ich bin hier raus. Viel Spass bei den weiteren Hausaufgaben. Ich freue mich bereits aufs nächste Wochenende.
Michael Gasser

Geändert von Michael II ( 6. Jun 2021 um 14:20 Uhr)
  Mit Zitat antworten Zitat
Amateurprofi

Registriert seit: 17. Nov 2005
Ort: Hamburg
1.111 Beiträge
 
Delphi XE2 Professional
 
#9

AW: Erstellung einer Funktion

  Alt 6. Jun 2021, 16:37
Nicht "oder so", sondern nur so wie Profi .
Es gibt allerdings einen Unterschied: #37 liefert wie in #26 verlangt den String, #38 die Position.
Zeitlich bewegen wir uns im gleichen Rahmen. Profi nutzt aus, dass Strings Null-terminiert sind, muss aber die =#0 Abfrage bei jedem Zeichen ausführen, #37 "einmal" am Schluss *.
Hallo Michael,
Zu "#37 liefert wie in #26 verlangt den String, #38 die Position"
Nee, #28 liefert die Länge der Ziffernfolge
Um die Ziffernfolge selbst zu liefern, bedarf es einiger kleiner Änderungen.
Hier die Funktion, die die Ziffernfolge liefert
Delphi-Quellcode:
FUNCTION LongestCipherSequence(const S:String):String;
var MaxLen:Integer; P,PS,PSMax,PStart:PChar;
begin
   MaxLen:=0;
   PStart:=PChar(S);
   P:=PStart;
   if P<>Nil then
      repeat
         case P^ of
            #0 : Break;
            '0'..'9' : begin
                           PS:=P;
                           Inc(P);
                           while P^ in ['0'..'9'] do Inc(P);
                           if P-PS>MaxLen then begin
                              MaxLen:=P-PS;
                              PSMax:=PS;
                           end;
                        end;
            else Inc(P);
         end;
      until False;
   if MaxLen=0 then Result:=''
      else Result:=Copy(S,PSMax-PStart+1,MaxLen);
end;
Zu "muss aber die =#0 Abfrage bei jedem Zeichen ausführen, #37 "einmal" am Schluss"
Nee, stimmt nicht.
Beim While wird ebenfalls bei jedem Zeichen geprüft, ob I >= len_s ist.
Vom Zeitaufwand her macht das keinen Unterschied.

Ich habe mal kurz das Zeitverhalten getestet. Gleiche Größenordung bei beiden Funktionen.
Ergebnis siehe Anhang:

Man könnte das Zeitverhalten noch optimieren:
Wenn bereits eine Ziffernfolge gefunden wurde, kann man beim Finden der nächsten Ziffer prüfen, ob das Zeichen an P+Maxlen eine Ziffer ist.
Wenn nicht, kann die Ziffernfolge nicht länger sein, als die bisher längste.
Dann kann man P = P+MaxLen setzen, muss also nicht jedes Zeichen separat prüfen.
Das lohnt sich aber nur, wenn wirklich lange Strings mit vielen Ziffern geprüft werden sollen, ansonsten wird das eher zu einem höheren Zeitbedarf führen.


Delphi-Quellcode:
PROCEDURE TMain.Test;
const Lines=10000; MaxLen=200; Rnd=12; Count=1000;
var I,J,Len:Integer; T0,T1,T2:Cardinal; S:String; List:TStrings;
begin
   List:=TStringList.Create;
   for I:=1 to Lines do begin
      Len:=Random(MaxLen);
      SetLength(S,Len);
      for J:=1 to Len do
         S[J]:=Char(Random(Rnd)+Ord('0'));
      List.Add(S)
   end;
   T0:=GetTickCount;
   for I:=1 to Count do
      for J:=0 to List.Count-1 do
         LongestCipherSequence(List[J]);
   T1:=GetTickCount;
   for I:=1 to Count do
      for J:=0 to List.Count-1 do
      LaengsteZiffernFolgeDerWelt(List[J]);
   T2:=GetTickCount;
   ShowMessage(IntToStr(T1-T0)+' LongestCipherSequence'#13+
               IntToStr(T2-T1)+' LaengsteZiffernFolgeDerWelt');
   List.Free;
end;
Angehängte Grafiken
Dateityp: jpg Unbenannt.jpg (13,9 KB, 8x aufgerufen)
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat
Michael II

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
778 Beiträge
 
Delphi 11 Alexandria
 
#10

AW: Erstellung einer Funktion

  Alt 7. Jun 2021, 16:54
Um die Ziffernfolge selbst zu liefern, bedarf es einiger kleiner Änderungen.
Hier die Funktion, die die Ziffernfolge liefert
FUNCTION LongestCipherSequence(const S:String):String; Ich habe mal kurz das Zeitverhalten getestet. Gleiche Größenordung bei beiden Funktionen.
Apfel Birnen Vergleich wegen deinem const Aufruf:
Mit const, also so
function LaengsteZiffernFolgeDerWelt( const s : string ) : string; ist's natürlich auch schneller.

Bei etwa 80% pseudozufällig verteilten Ziffern sind beide gleich schnell. Bei mehr als 80% Ziffernanteil deine, bei weniger meine.

Die Idee mit vorausschauender Prüfung ist schön.
Michael Gasser

Geändert von Michael II ( 8. Jun 2021 um 00:22 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:12 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz