Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi "Schlossknack"-Algorithmus (https://www.delphipraxis.net/90569-schlossknack-algorithmus.html)

fLaSh11 19. Apr 2007 16:35


"Schlossknack"-Algorithmus
 
Hallo DPler,

ich weiß nicht mehr weiter. :)
Ich möchte sozusagen den "Schlossknack"-Algorithmus anwenden, d.h. eine Variable von 1 bis 9 hochählen, wenn 9, dann die nächste auf 1,... Nun hat mein "Schloss" aber x Stellen.

Die einzige möglichkeit, die mir einfiel, war ein dyn. Array of Integer zu erstellen, ihm die Länge zu geben und dann die einzelnen Integer-Zahlen hochzuzählen. Will der Compiler aber nicht :evil: ...

Gibts noch ne andere Möglichkeit?

MfG
Steffen

//Edit: besserer Titel

Neutral General 19. Apr 2007 16:43

Re: for-Schleife x-Mal
 
Hi,

Verschachtelte for-schleifen?
Oder versteh ich was falsch?

Delphi-Quellcode:
var Schloss: Array[1..Stellen] of Integer;
for i:= 1 to Stellen do
begin
  for j:= 1 to 9 do
    inc(Schloss[i]);
end;
Gruß
Neutral General

Apollonius 19. Apr 2007 16:46

Re: for-Schleife x-Mal
 
Das Problem hatte ich auch mal. Die Lösung ist Rekursion. Du setzt eine globale Variable auf x. Dann erstellst du eine Funktion:
Delphi-Quellcode:
procedure schlossknack(laenge:integer);
begin
//mach irgendwas mit globalen Variablen
if laenge>1 then
 schlossknack(laenge-1);
end;
Edit: Neutral Generals Lösung scheint aber besser zu sein.

fLaSh11 19. Apr 2007 16:57

Re: for-Schleife x-Mal
 
@Neutral General:
Soweit ich sehe, zählt dieser Algorithmus einfach alle Variablen von 1 bis 9 hoch. Aber wenn die nächste eins hochgesetzt wird, sollte erst die ganz erste wieder von 1 bis 9 gezählt werden, so als wölltest du ein Schloss knachen.

du versuchst es folgendermaßen (bei einem Schloss mit 3 Stellen:
Code:
1 1 1
2 1 1
3 1 1
...
9 1 1
1 2 1
2 2 1
3 2 1
...
8 9 3
9 9 3
1 1 4
2 1 4
...

Apollonius 19. Apr 2007 17:02

Re: "Schlossknack"-Algorithmus
 
Nun, du musst eben bei jedem Aufruf der ersten for-Schleife die aktuelle Schlossvariable auf 0 setzen: Schloss[i]:=0;
Und der Stackbedarf ist deutlich besser als bei der Rekusrion, ich versuche mal, mein Prog, indem ich das durch Rekursion gelöst habe, zu beschleunigen.
DANKE, NEUTRAL GENERAL!!!

Torpedo 19. Apr 2007 17:03

Re: for-Schleife x-Mal
 
Zitat:

Zitat von fLaSh11
du versuchst es folgendermaßen (bei einem Schloss mit 3 Stellen:
Code:
1 1 1
2 1 1
3 1 1
...
9 1 1
1 2 1
2 2 1
3 2 1
...
8 9 3
9 9 3
1 1 4
2 1 4
...

Also ich würde es anders versuchen. Und zwar so:
111
112
113
...

Wieso einfach, wenns auch schwierig geht? ;)

fLaSh11 19. Apr 2007 17:13

Re: "Schlossknack"-Algorithmus
 
@Torpedo: klaro, aber Start und Ende bei jeder Stelle sind dort, wo ich das Ganze brauche auch variabel :mrgreen:
@Apollonius: Werd mal überlegen :)

Torpedo 19. Apr 2007 17:21

Re: "Schlossknack"-Algorithmus
 
Zitat:

Zitat von fLaSh11
@Torpedo: klaro, aber Start und Ende bei jeder Stelle sind dort, wo ich das Ganze brauche auch variabel :mrgreen:

Vielleicht versteh ich ja was nicht richtig, aber wenn man will, dass er bei z.B. 246 beginnt und bei 500 aufhört, dann kan man ja auch nur diese Zahlen durchzählen.
Oder ist das Problem wie man aus den einzelnen Stellen eine ganze Zahl macht?
Ziffer1 = 2
Ziffer2 = 4
Ziffer3 = 6

Zahl = Ziffer1*100+Ziffer2*10+Ziffer3

Meflin 19. Apr 2007 17:48

Re: "Schlossknack"-Algorithmus
 
Du könntest auch einfach meine Komponente verwenden :mrgreen:

http://www.delphipraxis.net/internal...ct.php?t=62161


Apollonius 19. Apr 2007 17:54

Re: "Schlossknack"-Algorithmus
 
Ich nehme alles zurück!!! Neutral Generals Lösung funktioniert nicht, es sei denn, ich habe was falsch implementiert. Man muss ja sozusagen x ineinanderverschachtelte for-schleifen haben. Da fällt mir nichts anderes ein als die Rekursion, also:
Delphi-Quellcode:
var schloss:array[1..stellen] of integer;

procedure angriff(laenge:integer);
var i:integer;
begin
if laenge=1 then
 begin
  for i:=0 to 9 do
   begin
    schloss[laenge]:=i;
    knackdasschloss(schloss);
   end;
 end
else
 begin
  for i:=0 to 9 do
   begin
    schloss[laenge]:=i;
    angriff(laenge-1);
   end;
 end;

end;

//Aufruf
angriff(stellen);
Im Prinzip ist das eine Simulation von laenge ineineanderverschlachtelten for-Schleifen.

kalmi01 19. Apr 2007 17:59

Re: "Schlossknack"-Algorithmus
 
Hi,
hab ich da was falsch verstanden, oder geht es darum, den korrekten Code eines Zahlenschlosses zu ermitteln ?
Wenn dem so iss, wie wärs denn mit ner simplen
Delphi-Quellcode:
for i := 0 to MaxWert do ....
Schleife ?

shmia 19. Apr 2007 18:38

Re: "Schlossknack"-Algorithmus
 
Es geht auch ohne Rekursion. Man muss sich nur überlegen, was passiert,
wenn zu einer "Zahl" der Wert 1 addiert wird.
Es kann an jeder Stelle einen Übertrag geben.

Delphi-Quellcode:
{**************************************************************************
 * NAME:   IncrementWithMask
 * DESC:   erhöht eine Nummer (die als String vorliegt) um Eins
 *          Dabei darf "Number" an bestimmten Stellen auch Buchstaben enthalten
 *          "Mask" bestimmt, an welchen Positionen Ziffern oder Buchstaben erlaubt sind
 * Mask: 0 = Ziffern    (0..9)
 *        A = Buchstaben (A..Z)
 *        Z = Ziffern & Buchstaben
 *        H = Hex-Ziffern (0..9, A..F)
 *          = diese Stelle bleibt
 * PARAMS: [-]
 * RESULT: die erhöhte Nummer
 *************************************************************************}
function IncrementWithMask(const Number, Mask:string):string;

   function IncrementDigit(x:PChar; m:Char):Boolean;
   var
      c : Char;
   begin
      Result := False;
      case m of
         '0':
         begin
            c := Succ(x^);
            if c > '9' then
            begin
               c := '0';
               Result := True;
            end;
            x^ := c;
         end;
         'A':
         begin
            c := Succ(x^);
            if c > 'Z' then
            begin
               c := 'A';
               Result := True;
            end;
            x^ := c;
         end;
         'Z':
         begin
            c := x^;
            if c = '9' then
               c := 'A'
            else if c = 'Z' then
            begin
               c := '0';
               Result := True;
            end
            else
               c := Succ(c);
            x^ := c;
         end;

         'H':
         begin
            c := x^;
            if c = '9' then
               c := 'A'
            else if c = 'F' then
            begin
               c := '0';
               Result := True;
            end
            else
               c := Succ(c);
            x^ := c;
         end;

         ' ':
            ;
      else
         raise Exception.CreateFmt('IncrementWithMask(%s, %s) - invalid Mask', [Number, Mask]);
      end;
   end;

var
   i : Integer;
begin
   Result := Number;
   for i:=length(Result) downto 1 do
   begin
      if not IncrementDigit(@result[i], Mask[i]) then
         Break;
   end;
end;
Beispiel:
Delphi-Quellcode:
var
   s, m : string;
begin
  s:= '0008899';
  m:= '0000000';
  s := IncrementWithMask(s, m); // s enthält nun '0008900'

alzaimar 19. Apr 2007 19:45

Re: "Schlossknack"-Algorithmus
 
Hmmm... Oder so (einfacher, kann dafür mit beliebigen Zahlensystemen arbeiten)
Delphi-Quellcode:
Const
  ccDigits = '0123456789';
// ccDigits enthält alle 'Ziffern' und kann beliebig erweitert werden
// Für Addition von HEX-Zahlen, setze ccDigits auf '0123456789ABCDEF';

Function AddOne(s: String): String;
Var
  i: Integer;
  cLast,cFirst : Char;

Begin
  i := Length(s);
  Result := s;
  cLast := ccDigits [Length (ccDigits)];
  cFirst := ccDigits[1];
  While i > 0 Do Begin
    If Result[i] <> cLast Then Begin
      Result[i] := ccDigits[1 + Pos (Result[i], ccDigits)]; // nächste 'Ziffer' aus den Digits nehmen
      Exit;
    End
    Else Begin
      Result[i] := cFirst;
      dec(i);
      End;
  End;
  Raise Exception.Create('Überlauf');
End;
Code:
AddOne('000') = '001'
AddOne('009') = '010'
AddOne('999') = Exception 'Überlauf'
Prinzipiell funktioniert es wie ein mechanischer Zähler. Hier wird beim letzten Zeichen begonnen. Ist das Zeichen < als die höchste Ziffer, ersetzen wir es durch die nächste und sind fertig. Ansonsten haben wir einen Übertrag: Wir setzen diese Stelle auf '0' (also auf die kleinste Ziffer), gehen um eine Stelle nach links und wiederholen das Ganze.


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:58 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