AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi Zahlen überprüfen --> keine darf doppelt
Thema durchsuchen
Ansicht
Themen-Optionen

Zahlen überprüfen --> keine darf doppelt

Ein Thema von Christian18 · begonnen am 29. Jun 2007 · letzter Beitrag vom 2. Jul 2007
Antwort Antwort
Seite 1 von 2  1 2      
Christian18

Registriert seit: 9. Dez 2003
Ort: Hamburg
1.279 Beiträge
 
#1

Zahlen überprüfen --> keine darf doppelt

  Alt 29. Jun 2007, 00:34
Hallo,

ich soll als Hausarbeit ein kleines Tool schreiben, welches Zahlen miteinander vergleicht. Ich habe 4 Edit Felder in den Zahlen von eins bis vier eingetragen werden sollen. Bsp.: 1 2 3 4 Es darf keine Zahl doppelt eingetragen werden. Also so nicht: 1 2 2 4

Also ähnlich wie bei Sudoku!!!

Ich habe das Programm schon fertig. Es gibt nur ein Problem. Die Routine, die überprüft ob eine Zahl doppelt vorkommt, soll erweiterbar sein. Das heisst es kann passieren, dass mal 5 oder 6 Edit Felder hinzugefügt werden. Dann soll es mit so wenig aufwand wie möglich trotzdem Funktionieren. Und das ist mein Problem.

Ich hatte das Problem folgendermäßen gelöst. Ich habe alle Permutionen von 1234 gebildet und in ein Array gespeichert.

Dann habe ich die Eingabe des Benutzers mit dem Array verglichen. Wenn die Eingabe des Benutzers im Array vorhanden ist, dann ist die Eingabe richtig, sonst ist bei der Eingabe ein Fehler unterlaufen. Kann man das eigentlich so machen? Oder gibt es trotzdem eine Variante um an der überprüfung vorbei zu kommen? Weiss nicht!!!

So, das funktioniert alles super. Ich kann es auch auf 10 und mehr Edit Felder erweitern, bloß die ganze Angelegenheit dauert ein weilchen. Hat ihr vieleicht einen Tipp für mich wie ich das ganze schneller machen kann???

MFG Christian18
  Mit Zitat antworten Zitat
fwsp
(Gast)

n/a Beiträge
 
#2

Re: Zahlen überprüfen --> keine darf doppelt

  Alt 29. Jun 2007, 00:43
ich würde die eingaben in ein array lesen. anschließend das array sortieren. und dann musst du nur noch überprüfen ob 2 mal die gleiche zahl hintereinander im array steht.

bsp:
eingaben: 5, 6, 4, 6, 8
sortiert: 4, 5, 6, 6, 8
und wenn du dann an die dritte stelle kommst, merkst du ja, dass danach nochmal die gleiche zahl kommt. das ganze sollte dann nicht so lange dauern.
  Mit Zitat antworten Zitat
Christian18

Registriert seit: 9. Dez 2003
Ort: Hamburg
1.279 Beiträge
 
#3

Re: Zahlen überprüfen --> keine darf doppelt

  Alt 29. Jun 2007, 01:05
Hallo,

ja stimmt. Dein Lösungsansatz ist auf jeden Fall effiktiver als meiner. Gibt es vieleicht noch effektivere Ansätze??? Freu mich schon auf die Antworten.

[EDIT]
Ich vermute mal das es irgendwann mal ein Sudoku Spiel werden soll. Denn warum die erweiterung ??? Macht für mich keinen Sinn!!! aber naja mal schauen was kommt.

LG Chris
  Mit Zitat antworten Zitat
Benutzerbild von cruiser
cruiser

Registriert seit: 23. Dez 2003
Ort: Königsbrück/Sachsen
455 Beiträge
 
Delphi 7 Enterprise
 
#4

Re: Zahlen überprüfen --> keine darf doppelt

  Alt 29. Jun 2007, 01:19
Hum...

1.) Controls durchgehn
2.) Wenn Edit in Zahl umwandeln
3.) Zahl mit Array prüfen
-> wenn nicht drin: reinschreiben
-> wenn drin: Routine abbrechen
evtl. Edit umfärben.
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#5

Re: Zahlen überprüfen --> keine darf doppelt

  Alt 29. Jun 2007, 02:49
Du benutzt ur sehr sehr wenig Zahlen -> 1 bis 4. Das lässt sich immer besser optimieren als zb. der Vorschlag die Zahlen in ein Array[] zu speichern, es zu sortieren und auf Duplikate zu prüfen. In deinem Falle ist dies nämlich sehr umständlich.

Baue dir ein Array[1..4] of Boolean. Initialisiere es mikt Fillchar(Array, SizeOf(Array), False), also alle Elemente = FALSE. Nachdem der Benutzer in einem Edit eine Zahl eingegeben hat, zb. im OnKeyPress(), wandelst du mit StrToInt(Edit.Text); dessen Zahl in einen Integer um. Dieser Wert wird als erstes überprüft auf >=1 und <=4, also StrToInt(Edit.Text) >= Low(Array) und <= High(Array). Danach benutzt du diesen Index ins Array und schaust nach ob dort TRUE oder FALSE steht. Bei TRUE hat schon ein anderes Edit die gleiche Zahl bei FALSE noch kein anderes Edit, ergo: das Array Elemlent auf TRRUE setzen.

Lange Rede kurzer Source

Delphi-Quellcode:
type
  TForm1 = class(TForm)
  private
    FZahlen: array[1..4] of Boolean;
  end;

procedure TForm1.EditKeyPress(var Key: Char; ....)
// alle deine Edits verweisen mit OnKeyPress() auf diesen Eventhandler
var
  I: Integer;
begin
  if Key in ['0'..'9'] then
  begin
    I := StrToInt(Key);
    if (I >= Low(FZahlen)) and (I <= High(FZahlen)) and not FZahlen[I] then FZahlen[I] := True
      else Key := #0; // lösche Taste, erscheint also nicht in Edit.Text
  end;
end;

procedure TForm1.ButtonRestartClick();
// lösche alle Edits und das FZahlen Array, Benutzer kann nun neu eingeben
var
  I: Integer;
begin
  FillChar(FZahlen, SizeOf(FZahlen), 0);
  for I := 0 to ControlCount -1 do
    if Controls[I] is TEdit then
       TEdit(Controls[I]).Text := '';
end;
Vorteile sind eben das es sehr einfach verständlich ist und aus Sicht der Performance wird es kein schnellers Verfahren geben in deinem Falle. Die Komplexität meines Vorschlages ist O(1) (Big O) und damit weitaus schneller als jeder Sortier- oder Suchalgorithmus.

Man kann das so wie oben machen immer dann wenn man nur sehr kleine und wenige Zahlen überprüfen/sortieren muß.

Gruß Hagen
  Mit Zitat antworten Zitat
oldmax

Registriert seit: 27. Apr 2006
Ort: Gieboldehausen
167 Beiträge
 
#6

Re: Zahlen überprüfen --> keine darf doppelt

  Alt 29. Jun 2007, 05:43
Hi
Denkbar wäre auch eine globale Stringvariable, die im OnKeypressed-Ereignis über Posnach der Zahl sucht und diese eventuell anhängt.
if Pos(Key, Zahlenstring) =0 then ZahlenString:=ZahlenString+Key else Key:=#0; In der Reset- Routine reicht dann ein
Zahlenstring:=''; ok, damit keine anderen Zeichen in den Zahlenstring kommen, die Abfrage ist bereits schon erklärt...
Gruß oldmax
Noch ist mein Rechner mir zu Diensten.... ansonsten habe ich die Macht ihn zu vernichten !
  Mit Zitat antworten Zitat
Benutzerbild von Niels14
Niels14

Registriert seit: 28. Dez 2005
Ort: Sydney/Australien
18 Beiträge
 
Delphi XE4 Enterprise
 
#7

Re: Zahlen überprüfen --> keine darf doppelt

  Alt 29. Jun 2007, 06:16
Hi,
waere es in diesem Fall nicht schneller einen mit 0 initialisierten Bit Array zu haben?
Dann koenntest Du der Reihe nach jeden Bit Array auf Eins setzen (00001000000...), dessen Index der Zahl entspricht.
Davor kannst Du noch checken ob der schon eins hat oder nicht, also schon im String vorkommt.
Sollte eigentlich sehr platzsparend, schnell und einfach zu erweitern sein!
LG Niels
Niels Maschmeyer
  Mit Zitat antworten Zitat
oldmax

Registriert seit: 27. Apr 2006
Ort: Gieboldehausen
167 Beiträge
 
#8

Re: Zahlen überprüfen --> keine darf doppelt

  Alt 29. Jun 2007, 08:24
hi
Also, alle Abfragen mit onkeypressed sind nur geeignet für Zahlen von 0 - 9, aber was ist mit 164555 ?
dazu Zitat :
Zitat:
Die Routine, die überprüft ob eine Zahl doppelt vorkommt, soll erweiterbar sein.
Mehrstellige Zahlen lassen sich beim Verlassen eines Editfeldes checken, eben auch mit der Pos-Function. Dazu brauchts nur einen kleinen Trick: Die Zahlengrenzen müssen markiert werden. z.B. mit einem Semikolon. Dann wird der String nicht mehr mit '' initialisiert, sondern mit ';'
in der OnExit -Methode prüft man

Delphi-Quellcode:
If Pos(';'+Edit1.Text+';',Zahlenstring)=0 then ZahlenString:=Zahlenstring+Edit1.Text+';'
 else Edit1.Text:='';
Soviel zur Erweiterbarkeit und unbekannten Grenzen......
@niels
Natürlich gibt's Arrays und in einem Array [0..9] of Boolean kann ich jede Zahl markieren. Schneller.. hmmm, bei Zahlen von 0 bis 9 vermutlich nur für den PC, nicht für den Anwender, denn der merkt den Unterschied zwischen 3ms und 30 wohl kaum, obwohl da Faktor 10 drin ist.... Aber gut, manchmal machts schon Sinn, Geschwindigkeitsoptimiert zu denken und zu programmieren.
Gruß oldmax
Noch ist mein Rechner mir zu Diensten.... ansonsten habe ich die Macht ihn zu vernichten !
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#9

Re: Zahlen überprüfen --> keine darf doppelt

  Alt 29. Jun 2007, 15:20
Es geht nicht darum "Geschwindigkeitsoptimiert" zu arbeiten, sondern um effektiv und effizient zu arbeiten. Entscheidend ist das der Programmierer hierbei die zu dem Problem optimal passende Lösung findet. Sie sollte schlicht sein und nach Möglichkeit annerkannte Standard-Algos. der Programmierung benutzen, wenn sie auch Sinn machen.

Beispiel eben 6 Zahlen zwischen 1 bis 6 auf Duplikate prüfen. Ein sehr einfaches Problem mag man meinen, aber an Hand der unterschiedlichen Lösungsansätze kann man sehr wohl erkennen wie der Wissenstand, bzw. die Fähigkeit des Programmieres ein Problem analytisch zerlegen zu können, gereift ist.

Standdardlösung wäre es die Zahlen in ein Array/Liste zu packen, diese zu sortieren und vor dem Einfügen eines neuen Wertes per binärer Suche in dieser Liste den Wert zu überprüfen. Eine idelae Aufgabe für eine TIntegerList (TList Nachlkommen) die mit Duplicates=dupIgnore arbeitet. Aber in diesem Falle ist es auf Grund der geringen Zahlen/Menge offensichtlich das man eine viel simplere Lösung benutzten kann. Also einfach ein Array/Liste mit der maximalen Anzahl aller vorkommenden Zahlen initialisieren und dann einfach jede Zahl aus dem Array rausstreichen die eingegeben wurde. Da unsere jeweilige Zahl der direkte Index in dieses Array[] darstellt entfällt das Durchsuchen/Sortieren eines Speicherbereiches. Nun stellt sich die Frage welche Datentypen der Programmierer dafür wählt. Auch hier gibts essentiell zwei unterschiedliche Denkweisen:

1.) man nehme schon vorhandene Klassen/Code egal ob er überhaupt geeignet ist. Das sind Vorschläge wie "nim TList und caste alle deine Integer von/nach Pointer", oder "nimm einen String der erstmal leer ist, hänge die Zahlen als String hintendran und überprüfe mit Pos ob die neue Zahl vorkommt im String".

2.) man benutzt die Fähigkeit der Programmiersprache gezielt eigene Datentypen zu konstruieren, eben ein array[1...6] of Boolean.

Der Unterschied in beiden Arbeitsstilen ist der das der eine immer nur das Problem zu lösen versucht indem er Standardgeschichten die schon fertig sind benutzt. Er passt quasi die Lösung des Problemes an die ihm zur Verfügung stehenden Mittel an. Benötigt man zur Lösung des Problemes einen Hammer und die Programmiersprache enthält keine vorgefertigte Klasse/Code "Hammer" dann wird ein solcher Programmierer es schwerer haben. Der andere baut sich eine eigene Umwelt in der er das jeweilige Problem optimal lösen kann, indem er der Programmiersprache sagt was er haben möchte als Umwelt. Man könnte sagen das dies den Unterschied zwischen einem Anwendungs- und Systementwickler ausmacht.

Bei meinen Postings ging es also nicht darum das der erzeugte Code nun die gleiche Aufgabe in 3ms statt 30ms lösst, sondern darum aufzuzeigen das in diesem Falle auch eine ganz ganz simple Lösung optimal sein kann. Es ist klar das wenn sich die Aufgabenstellung verändert, zb. > 100 Zahlen und nicht nur einstellige Zahlen, sich auch die benutzte Lösung unterscheiden muß. Das was mich "wurmt" ist eher der Punkt das Vorschläge kamen die eher sehr unelegant sind, zb. mit Strings zu rechnen statt gezielt eigene Datentypen zu benutzen ! Das ist so als würde der Programmierer nur 50% der Leistungsfähigkeit seiner Programmiersprache benutzen, denn man programmiert nicht nur Klassen, Prozeduren und Formulare sondern meist als Schritt davor programmiert/deklariert man seine Datentypen zugeschnitten auf das Problem.

Gruß Hagen
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#10

Re: Zahlen überprüfen --> keine darf doppelt

  Alt 29. Jun 2007, 17:48
Hallo,

ich hätte auch noch einen Lösungsansatz - ohne Anspruch auf Reife:

Delphi-Quellcode:
uses
  StrUtils;

type
  TNumberSet = set of 1..9;

var
  NumberSet: TNumberSet;

function CheckNumber(var ns: TNumberSet; n: Integer): Boolean;
begin
  Result := True;
  if not (n in ns)
    then ns := ns + [n]
    else Result := False;
end;

procedure TDemoForm.ButtonClick(Sender: TObject);
const
  FMT = '%d ist %s';
var
  i, n: Integer;
  b: Boolean;
begin
  NumberSet := [];
  for i := 1 to 9 do
  begin
    n := Succ(Random(9));
    b := CheckNumber(NumberSet, n);
    ShowMessage(Format(FMT, [n, IfThen(b, 'okay', 'doppelt')]));
  end;
end;
Freundliche Grüße
  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 00:22 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