Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Mehrere Variablen vergleichen (https://www.delphipraxis.net/151574-mehrere-variablen-vergleichen.html)

Delphi-Narr 23. Mai 2010 17:31


Mehrere Variablen vergleichen
 
Hallo, ich möchte gerne 9 Variablen vergleichen (alles integer).
Bedingung ist, dass alle unterschiedlich sind, also kein Wert doppelt vorkommen darf.
Leider kann ich nicht schreiben

Delphi-Quellcode:
if a<>b<>c<>d<>e<>f<>g<>h<>i then ...
Gibt es eine andere Möglichkeit, das zu überprüfen?

Liebe Grüße!

daywalker9 23. Mai 2010 17:38

Re: Mehrere Variablen vergleichen
 
Wenn du die in einem Array speichern würdest, wäre das für dich einfacher. Dann könntest du das mit for Schleifen lösen

Delphi-Narr 23. Mai 2010 17:42

Re: Mehrere Variablen vergleichen
 
Ok, danke. Dann werde ich das in ein Array packen...

himitsu 23. Mai 2010 18:25

Re: Mehrere Variablen vergleichen
 
Jupp, die Schleife ist keine Schlechte Idee, ansonsten mußt du ja so oder so jede Variable mit Jeder vergleichen, was natürlich 9*(9-1) Vergleiche ergibt.
Optimiert, durch Auslassung der äquivalenten Vergleiche ( a<>b = b<>a ), ergibt das ein bissl weniger:
Delphi-Quellcode:
if (a<>b) and (a<>c) and (a<>d) and (a<>e) and (a<>f) and (a<>g)
  and (a<>h) and (a<>i) and (b<>c) and (b<>d) and (b<>e) and (b<>f)
  and (b<>g) and (b<>h) and (b<>i) and (c<>d) and (c<>e) and (c<>f)
  and (c<>g) and (c<>h) and (c<>i) and (d<>e) and (d<>f) and (d<>g)
  and (d<>h) and (d<>i) and (e<>f) and (e<>g) and (e<>h) and (e<>i)
  and (f<>g) and (f<>h) and (f<>i) and (g<>h) and (g<>i) and (h<>i) then
PS: Bei der Schleife mußt du natürlich die selben Vergleiche durchführen, aber dieses läßt sich sehr leicht über zwei verschachtelte For-Schleifen in 3 Zeilchen lösen.

Wolfgang Mix 23. Mai 2010 18:49

Re: Mehrere Variablen vergleichen
 
Viel weniger Code wird dabei aber auch nicht herauskommen :(

mkinzler 23. Mai 2010 18:52

Re: Mehrere Variablen vergleichen
 
Aber auf jeden Fall übersichtlicher. Oder sorgt vorher dafür, dass die Variablen keinen vorhandenen Wert annehmen können

Matze 23. Mai 2010 18:53

Re: Mehrere Variablen vergleichen
 
Zitat:

Zitat von Wolfgang Mix
Viel weniger Code wird dabei aber auch nicht herauskommen :(

Die Code-Länge spielt überhaupt keine Rolle. Wichtig ist vorwiegend die Übersichtlichkeit und die Wartbarkeit bzw. Wiederverwendbarkeit des Codes.

Edit: Da war Markus schneller.

Wolfgang Mix 23. Mai 2010 18:57

Re: Mehrere Variablen vergleichen
 
Volle Zustimmung, kein Widerspruch :)

blauweiss 23. Mai 2010 19:05

Re: Mehrere Variablen vergleichen
 
Ich werfe folgende Idee in den Raum:

StringList verwenden mit Sorted auf TRUE und Duplicates auf dupError
alle Integer-Variablen per IntToStr dieser StringList hinzufügen
und das Ganze innerhalb try - except
-> wenn's kracht, gab's ne Doublette
oder alternativ, wenn man Exceptions nicht mag: Duplicates auf dupIgnore
-> hinterher Count überprüfen: falls kleiner als Anzahl Variablen, gab's ne Doublette

Grüße,
blauweiss

mkinzler 23. Mai 2010 19:09

Re: Mehrere Variablen vergleichen
 
Lieber eine Liste mit Integern oder Extendedwerten

Wolfgang Mix 23. Mai 2010 19:12

Re: Mehrere Variablen vergleichen
 
Wobei mir himitsus Lösung besser gefällt, weil sie
plattformunabhängig ist, aber das ist wohl Geschmacksache.

daywalker9 23. Mai 2010 19:15

Re: Mehrere Variablen vergleichen
 
Zitat:

Zitat von mkinzler
Lieber eine Liste mit Integern oder Extendedwerten

Ist wie ich finde - auch einfacher zu verstehen. Auch für die Delphi - Anfänger

himitsu 23. Mai 2010 19:25

Re: Mehrere Variablen vergleichen
 
Zitat:

Zitat von Wolfgang Mix
Wobei mir himitsus Lösung besser gefällt, weil sie
plattformunabhängig ist, aber das ist wohl Geschmacksache.

Nja, 'ne platformunabhängigkeit seh ich so oder so eh nicht.

PS: noch eine weitere Variable erzeugt gleich nochmal 1,5 weitere solcher Vergleichszeilen.

Wärend die Schleifen gleichlang bleiben.
Außerdem kann man sich bei den vielen Vergleichen schonmal verschreiben.
(nicht jeder läßt sich derartige Codes automatisch generieren :angel2: )
Delphi-Quellcode:
for i := 0 to High(arr) - 1 do
  for j := i + 1 to High(arr) do
    if arr[i] = arr[j] then
      >>doppelt<<
Delphi-Quellcode:
doppelt := False;
for i := 0 to High(arr) - 1 do
  for j := i + 1 to High(arr) do
    if arr[i] = arr[j] then begin
      doppelt := True;
      Break;
    end;
if doppelt then ...
Einzig und alleine die Geschwindigkeit könnte (unter gewissen Umständen) bei den direkten Vergleichen ein paar millionstel Sekunden schneller sein.

Delphi-Narr 24. Mai 2010 09:42

Re: Mehrere Variablen vergleichen
 
#13

Ja, so hatte ich das jetzt auch gemacht.
Danke!

gammatester 24. Mai 2010 12:32

Re: Mehrere Variablen vergleichen
 
Zitat:

Zitat von himitsu
Einzig und alleine die Geschwindigkeit könnte (unter gewissen Umständen) bei den direkten Vergleichen ein paar millionstel Sekunden schneller sein.

Aber nur, wenn Du es vernünftig programmiert hättest! Um Deinen Fehler zu sehen, teste mal Deinen Code mit folgenden Vorgaben:
Delphi-Quellcode:
setlength(arr, 10000000);
for i:=0 to high(arr) do arr[i] := i;
arr[0] := 1;
In der Zwischenzeit hier die Erklärung: Dein angeblich fast optimaler Code verläßt via break verläßt nämlich nur die innere for-Schleife, und die äußere Schleif wird immer wieder durchlaufen, auch wenn schon doppelte Einträge erkannt wurden. Wenn kein Goto oder exit aus einer separaten Funktion verwendet werden sollen, könnte ein verbesserter Vorschlag etwa so aussehen:
Delphi-Quellcode:
  doppelt := false;
  for i:=0 to High(arr)-1 do begin

    if not doppelt then begin
      for j:=i+1 to High(arr) do begin
        if arr[i]=arr[j] then begin
          doppelt := true;
          break;
        end;
      end;
    end;
  end;
  if doppelt then ...;

daywalker9 24. Mai 2010 12:42

Re: Mehrere Variablen vergleichen
 
Das kann man noch weiter optimieren. So braucht man nicht immer wieder die erste for Schleife komplett durchlaufen

Delphi-Quellcode:
doppelt := false;
  for i:=0 to High(arr)-1 do
    begin
      for j:=i+1 to High(arr) do
        begin
           if arr[i]=arr[j] then
             begin
                doppelt := true;
                 break;
             end;
        end;
      if doppelt then
       break;
    end;
  end;

himitsu 24. Mai 2010 12:52

Re: Mehrere Variablen vergleichen
 
Ach menno, das vergeß ich manchmal.

ich wünsche mir eh schon lange ein Break(2); für sowas. :cry:

gammatester 24. Mai 2010 13:17

Re: Mehrere Variablen vergleichen
 
Zitat:

Zitat von daywalker9
Das kann man noch weiter optimieren. So braucht man nicht immer wieder die erste for Schleife komplett durchlaufen

Schon klar. Wie schon gesagt, wäre eine separate Funktion mit einem exit oder ein goto noch schneller.

Allerdings ist wohl selbst dann im schlimmsten Fall immer noch eine quadratische Laufzeit erforderlich. Mit einem n*log(n) Sortierverfahren mit anschließendem linearen Vergleich oder eine Hashliste hätte man eine bessere Worst-case-Laufzeit.

himitsu 24. Mai 2010 13:30

Re: Mehrere Variablen vergleichen
 
Diese Schleife (inkl. richtiger Abruchbedingung) sollte im Worst-Case bei n*(n-1)/2 liegen. :gruebel:

PS: Aha, du willst also alles mehrfach durchgehn? @gammatester
- sortieren mit n*log(n)
- und prüfen mit n-1
wird bestimmt länger dauern.

gammatester 24. Mai 2010 15:49

Re: Mehrere Variablen vergleichen
 
Zitat:

Zitat von himitsu
Diese Schleife (inkl. richtiger Abruchbedingung) sollte im Worst-Case bei n*(n-1)/2 liegen. :gruebel:

PS: Aha, du willst also alles mehrfach durchgehn? @gammatester
- sortieren mit n*log(n)
- und prüfen mit n-1
wird bestimmt länger dauern.

Da wird nix länger dauern (außer für sehr kleine Arrays). Mit der folgenden Initialisierung (beachte umgekehrte Sortierung)
Delphi-Quellcode:
setlength(arr, NMAX);
j := high(arr);
for i:=0 to j-1 do arr[i] := -i;
arr[j] := arr[j-1];
erhalte ich für NMAX:
Code:
20000 mit 'optimierter' Schleife 721 ms
20000 mit Quicksort 0 ms
1000000 mit Quicksort 220 ms
Den Wert für 1000000 mit 'optimierter' Schleife kannst Du ja mal bestimmen. Dabei ist der Ablauf mit Quicksort wie folgt:
Delphi-Quellcode:
Quicksort(...);
for i:=0 to high(arr)-1 do begin
  if arr[i]=arr[i+1] then begin
    doppelt := true;
    break;
  end;
end;

Hawkeye219 24. Mai 2010 16:52

Re: Mehrere Variablen vergleichen
 
Hallo,

laut Eröffnungsbeitrag handelt es sich um lediglich 9 Werte, vermutlich sogar mit einem stark eingeschränkten Wertebereich von 1..9. Falls diese Vermutung stimmt, dann lässt sich das Problem relativ leicht lösen:

Delphi-Quellcode:
if ([a, b, c, d, e, f, g, h, i] = [1..9]) then
  ShowMessage ('alle Werte unterschiedlich')
else
  ShowMessage ('mindestens ein Wert fehlt bzw. doppelt');
Gruß Hawkeye

daywalker9 24. Mai 2010 16:57

Re: Mehrere Variablen vergleichen
 
Das funktioniert nur wenn die Werte in der Variablen a = 1 und i = 9 ist. Ansonsten klappt das nicht. Das heißt es muss sortiert werden, was wieder für ein Array spricht und dies dann mit for Schleifen durchzulaufen

Namenloser 24. Mai 2010 17:10

Re: Mehrere Variablen vergleichen
 
Zitat:

Zitat von daywalker9
Das funktioniert nur wenn die Werte in der Variablen a = 1 und i = 9 ist.

Bei einem Set soltle die Reihenfolge eigentlich keine Rolle spielen, schließlich ist ein Set letztlich nichts anderes als eine Bitmaske. In welcher Reihenfolge diese Bits gesetzt werden, macht keinen Unterschied.

daywalker9 24. Mai 2010 17:19

Re: Mehrere Variablen vergleichen
 
Stimmt, ich revidiere meine Aussage

Delphi-Narr 25. Mai 2010 13:04

Re: Mehrere Variablen vergleichen
 
Also es sind wirklich nur die Werte 1-9. Es ist, um ein Sudoku zu überprüfen.
Daher speicher ich immer eine Reihe/Spalte oder einen Block in einem Array [0..8] und prüfe, ob alle Werte stimmen...
Daher wäre das mit dem Set auch eine Möglichkeit, die mir entgangen ist...


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:07 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz