Advertisement
hpolzer

Kaprekar's process

May 3rd, 2016
152
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pascal 3.91 KB | None | 0 0
  1. {
  2.     Kaprekar's process. To compile run gpc -o kp kp.pas or fpc kp.pas.
  3.     Henning Polzer, May 1st, 2016. Send comments and error reports to:
  4.     h underscore polzer at gmx dot de.
  5. }
  6.  
  7. PROGRAM Kaprekarprozess;
  8. CONST obergrenze = 8;                   { Max. Anzahl der Stellen des Startwertes
  9.                                       in Abhaengigkeit von Tganzzahl, s. u. }
  10.       max_schritte = 30;                { Zahl der max. ausgefuehrten Rechenschritte }
  11.       periodenlaenge = max_schritte;        { Hoechste erkannte Periodenlaenge }
  12. TYPE Tganzzahl = longint;
  13. VAR zahl: Tganzzahl;
  14.     fehlercode: word;           { Zur Umwandlung des Kommandozeilenparameters }
  15.  
  16.  
  17. FUNCTION stellen (z: Tganzzahl): Tganzzahl;     { Ermittelt Stellen der Zahl }
  18. BEGIN
  19.   IF z <> 0 THEN stellen := trunc(abs(ln(z)/ln(10)))+1 ELSE stellen := 1
  20. END; { stellen }
  21.  
  22.  
  23. PROCEDURE kaprekar (zahl: Tganzzahl);
  24. VAR a: ARRAY[1..obergrenze] OF Tganzzahl;   { Ziffern der zu untersuchenden Zahl }
  25.     p: ARRAY[1..periodenlaenge] OF Tganzzahl; { Speichert Werte fuer Periodensuche }
  26.     altes_ergebnis, diff, hilf, i, j, min, max, n, schritt, st, startwert: Tganzzahl;
  27.     ende, geordnet, gleich: boolean;
  28.  
  29. BEGIN
  30.   altes_ergebnis := 0;
  31.   startwert := zahl;
  32.   ende := false;
  33.   schritt := 1;     { Zahl der ausgefuehrten Rechenschritte }
  34.   p[1] := zahl;     { Startwert fuer Periodensuche speichern }
  35.   j := 2;           { Naechsten Wert fuer Periodensuche ab 2. Element eintragen }
  36.  
  37.   REPEAT
  38.     st := stellen (zahl);
  39.  
  40.     FOR i := st DOWNTO 1 DO     { Zahl in Ziffern zerlegen und von }
  41.     BEGIN                   { rechts nach links in Feld eintragen }
  42.       a[i] := zahl MOD 10;
  43.       zahl := zahl DIV 10
  44.     END; { for }
  45.  
  46.     REPEAT                  { Sortieren }
  47.       geordnet := true;
  48.       FOR i := 1 TO st - 1 DO
  49.         IF a[i] > a[i+1] THEN
  50.         BEGIN
  51.           geordnet := false;        { Falsche Anordnung gefunden }
  52.           hilf := a[i];         { Austausch vornehmen }
  53.           a[i] := a[i+1];
  54.           a[i+1] := hilf
  55.         END { if }
  56.     UNTIL geordnet = true;      { Ende, wenn keine falsche Anordnung mehr gefunden }
  57.  
  58.     gleich := true;             { Ende, wenn alle Stellen des mindestens }
  59.     FOR i := 1 TO st - 1 DO     { zweistelligen >Start<wertes gleich sind, }
  60.       IF a[i] <> a[i+1] THEN gleich := false;   { in spaeteren Schritten koennen Zahlen }
  61.     IF (gleich = true) AND          { auftreten, in denen alle Ziffern gleich }
  62.        (schritt < 2) AND            { sind, vgl. Schritte 1 und 2 bei einem }
  63.        (stellen (startwert) > 1) THEN exit; { Startwert von 101. }
  64.  
  65.     min := 0;                   { Extrema finden und in den Variablen }
  66.     max := 0;                   { min und max speichern }
  67.     FOR i := 1 TO st DO
  68.     BEGIN
  69.       min := (min + a[i]) * 10;     { Von links nach rechts in Zahl ueberfuehren }
  70.       max := (max + a[st-i+1]) * 10 { Hier von rechts nach links vorgehen }
  71.     END;
  72.     min := min DIV 10;
  73.     IF max DIV 10 <> min THEN max := max DIV 10;
  74.  
  75.     diff := max - min;          { Ergebnis ausgeben }
  76.     IF (diff = altes_ergebnis) OR (schritt > max_schritte) THEN ende := true
  77.       ELSE writeln (schritt:2, '. Schritt: ', max:8, ' - ', min:8, ' = ', diff:8);
  78.     zahl := diff;
  79.  
  80.     p[j] := zahl;               { Nach Periode suchen: Ende, wenn gefunden }
  81.     hilf := 0;
  82.     i := 1;
  83.     n := 0;                 { Haelt ggf. Anfang der Periode fest }
  84.     REPEAT
  85.       IF zahl = p[i] THEN
  86.       BEGIN
  87.         hilf := hilf + 1;
  88.         IF n = 0 THEN n := i-1  { n nur aendern, wenn noch Ursprungswert (0, s. o.) }
  89.       END; { if }           { vorhanden, sonst ist bereits Periode erkannt }
  90.       i := i + 1
  91.     UNTIL i = periodenlaenge;
  92.     IF hilf > 1 THEN ende := true;
  93.     IF j = periodenlaenge THEN j := 1 ELSE j := j + 1;
  94.  
  95.     altes_ergebnis := zahl;
  96.     schritt := schritt + 1
  97.   UNTIL (ende = true);
  98.   writeln ('Periode beginnt bei Schritt ', n, '.')
  99. END; { kaprekar }
  100.  
  101.  
  102. BEGIN { Hauptprogramm }
  103.   val (paramstr (1), zahl, fehlercode);
  104.   IF (fehlercode = 0) AND
  105.      (stellen (zahl) > 1) AND       { Zahl soll mindestens zwei Stellen haben }
  106.      (stellen (zahl) <= obergrenze) THEN kaprekar (zahl)
  107. END.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement