Spiegelzahlen – auch Palindrome genannt

1. Aufgabe

Eine natürliche Zahl, die identisch mit ihrer Kehrzahl ist, wie z.B. 131, wird Spiegelzahl oder auch Palindrom genannt. In dieser Aufgabe entwickeln wir eine nicht deterministische Methode zur Berechnung beliebig großer Palindrome. Die in C# eingebauten elementaren Datentypen (wie int oder long) stellen keine echte Hilfe dar, wenn wir potentiell unendlich große Palindrome berechnen wollen. Zu diesem Zweck entwerfen wir im Folgenden zunächst zwei Klassen Digit und Number, mit deren Hilfe sich leicht sehr große Zahlen darstellen lassen. Im Anschluss daran gehen wir auf die Klasse PalindromCalculator ein, um Palindrome zu berechnen.

Vorbemerkung:

Versuchen Sie, beim Entwurf der Klassen möglichst viele Sprachelemente von C# mit objektorientiertem Charakter wie Eigenschaften, Schnittstellen, Methoden der Basisklasse Object, usw. zum Einsatz zu bringen.

1.1 Klasse Digit

Objekte der Klasse Digit beschreiben eine einzelne Ziffer von 0 bis 9. Die Klasse Digit ist äußerst einfach in Ihrer Realisierung, wir spezifizieren sie deshalb nur an Hand eines Beispiels:

Code-Fragment:

Digit d1 = new Digit(9);
Console.WriteLine(d1);

int n = d1.Value;
Console.WriteLine(n);

Digit d2 = new Digit(8);
Console.WriteLine(d2);
Console.WriteLine(d1 == d2);

Digit d3 = (Digit)d1.Clone();
Console.WriteLine(d3);
Console.WriteLine(d1 == d3);

Ausgabe:

9
9
8
False
9
True

1.2 Klasse Number

Objekte der Klasse Number beschreiben eine beliebig große Zahl, deren Ziffern durch Digit-Objekte festgelegt sind. Die in Tabelle 1 beschriebenen Elemente der Klasse Number sind zur Vorbereitung der Berechnung von Palindromen zu implementieren:

Element

Beschreibung

Standard-Konstruktor

public Number ();

Erzeugt ein Number-Objekt mit dem Wert 0.

Benutzerdefinierter Konstruktor

public Number (String number);

Erzeugt ein Number-Objekt mit Hilfe der Beschreibung einer Zahl in Form einer Zeichenkette. Der besseren Lesbarkeit halber sind Punkte in der Zeichenkette zulässig, wie etwa "12.345". Mit Ausnahme von Punkten dürfen in der Zeichenkette keine anderen Zeichen enthalten sein.

Methode Add

public Number Add (Number n);

Addiert das Number-Objekt n zum aktuellen Objekt.

Operator +

public static Number operator+ (Number a, Number b);

Liefert ein neues Number-Objekt mit dem Wert a + b zurück.

Methode Reverse

public Number Reverse ();

Erstellt zum aktuellen Number-Objekt das inverse Number-Objekt, auch als Kehrzahl bezeichnet.

Eigenschaft IsSymmetric

public bool IsSymmetric { get; }

Liefert true zurück, wenn das aktuelle Number-Objekt eine Spiegelzahl ist, andernfalls false.

Tabelle 1. Elemente der Klasse Number.

1.3 Klasse PalindromCalculator

Für die Erzeugung von Palindromen gibt es einen Algorithmus, der leider nicht deterministisch ist: Addiert man eine beliebige Zahl wiederholt mit ihrer Kehrzahl (inversen Zahl), kann man ein Palindrom erhalten.

Beispiel:

Zahl:                           53978        Kein Palindrom
inverse Zahl:                 + 87935
addiert:                       141913        Kein Palindrom
inverse Zahl:                + 319141
addiert:                       461054        Kein Palindrom
inverse Zahl:                + 450164
addiert:                       911218        Kein Palindrom
inverse Zahl:                + 812119
addiert:                      1723337        Kein Palindrom
inverse Zahl:               + 7333271
addiert:                      9056608        Kein Palindrom
inverse Zahl:               + 8066509
addiert:                     17123117        Kein Palindrom
inverse Zahl:              + 71132171
addiert:                     88255288        (!) Palindrom - 7 Schritte

Die einfache Idee des Algorithmus basiert also auf der wiederholten Addition einer beliebigen Zahl mit ihrer inversen Zahl. Da in einigen (wenigen) Situationen der Algorithmus in eine Endlosschleife geraten kann, müssen Sie die Anzahl der wiederholten Additionen begrenzen. Weitere Details entnehmen Sie Tabelle 2:

Element

Beschreibung

Eigenschaft Start

public Number Start { get; set; };

Startwert zur versuchsweisen Berechnung eines Palindroms.

Eigenschaft Limit

public int Limit { get; set; };

Legt die obere Grenze für die Anzahl von Additionen (Number-Objekt mit Kehrwert) fest, die zur versuchsweisen Berechnung eines Palindroms durchgeführt werden.

Methode CalcPalindrom

public bool CalcPalindrom ();

Ermittelt zum festgelegten Startwert (Eigenschaft Start) ein Palindrom. Die Berechnung wird nach einer bestimmten Anzahl von Schritten abgebrochen, wenn noch kein Palindrom gefunden wurde (siehe Eigenschaft Limit), die Methode liefert dann den Wert false zurück. Im Erfolgsfall wird true zurückgeliefert, das berechnete Palindrom ist in der Eigenschaft Palindrom abgelegt.

Eigenschaft Palindrom

public Number Palindrom { get; };

Liefert das Ergebnis des letzten CalcPalindrom-Aufrufs zurück, falls ein Palindrom berechnet werden konnte. Andernfalls wird die Nullreferenz zurückgegeben.

Eigenschaft Steps

public int Steps { get; };

Liefert die Anzahl der Additionen zurück, die bei der Berechnung des letzten Palindroms stattgefunden haben. Konnte kein Palindrom berechnet werden, nimmt Steps den Wert der Eigenschaft Limit an.

Tabelle 2. Elemente der Klasse PalindromCalculator.


Kontrollfrage:

Wir betrachten zur Kontrolle Ihrer Implementierung bei den Startzahlen den Bereich von 1 bis 10000. Wie viele Palindrome lassen sich in diesem Bereich mit Ihrer Implementierung der Methode CalcPalindrom erzeugen, wenn Sie für die maximale Anzahl von Additionen den Wert 1000 (Eigenschaft Limit) zu Grunde legen?

Die Ausgaben Ihres Programms zur Beantwortung der Frage könnten in etwa so aussehen:

Found Palindroms: Start =    1 -- Palindrom = 1                  -- Steps: 1
Found Palindroms: Start =    2 -- Palindrom = 2                  -- Steps: 1
Found Palindroms: Start =    3 -- Palindrom = 3                  -- Steps: 1
Found Palindroms: Start =    4 -- Palindrom = 4                  -- Steps: 1
Found Palindroms: Start =    5 -- Palindrom = 5                  -- Steps: 1
Found Palindroms: Start =    6 -- Palindrom = 6                  -- Steps: 1
Found Palindroms: Start =    7 -- Palindrom = 7                  -- Steps: 1
Found Palindroms: Start =    8 -- Palindrom = 8                  -- Steps: 1
Found Palindroms: Start =    9 -- Palindrom = 9                  -- Steps: 1
Found Palindroms: Start =   10 -- Palindrom = 11                 -- Steps: 2
Found Palindroms: Start =   11 -- Palindrom = 11                 -- Steps: 1
Found Palindroms: Start =   12 -- Palindrom = 33                 -- Steps: 2

...
...
...

Found Palindroms: Start =  9985 -- Palindrom = 595595            -- Steps: 6
Found Palindroms: Start =  9986 -- Palindrom = 445544            -- Steps: 5
Found Palindroms: Start =  9987 -- Palindrom = 687786            -- Steps: 5
No Palindrom:     Start =  9988
Found Palindroms: Start =  9989 -- Palindrom = 22399322          -- Steps: 9
Found Palindroms: Start =  9990 -- Palindrom = 8939779398        -- Steps: 16
Found Palindroms: Start =  9991 -- Palindrom = 712217            -- Steps: 8
Found Palindroms: Start =  9992 -- Palindrom = 2322232           -- Steps: 10
Found Palindroms: Start =  9993 -- Palindrom = 579975            -- Steps: 6
Found Palindroms: Start =  9994 -- Palindrom = 16699661          -- Steps: 8
Found Palindroms: Start =  9995 -- Palindrom = 229922            -- Steps: 5
Found Palindroms: Start =  9996 -- Palindrom = 16668488486661    -- Steps: 21
Found Palindroms: Start =  9997 -- Palindrom = 8911661198        -- Steps: 14
Found Palindroms: Start =  9998 -- Palindrom = 8836388           -- Steps: 7
Found Palindroms: Start =  9999 -- Palindrom = 9999              -- Steps: 1
Found Palindroms: Start = 10000 -- Palindrom = 10001             -- Steps: 2

Total Palindroms: ???              Max Steps:  ???

1.4 Viertes Eulersches Problem

Ein nach dem Mathematiker Leonhard Euler benanntes Problem lautet: „Finde das größte Palindrom, das ein Produkt zweier dreistelligen Zahlen ist!“. Zum besseren Verständnis: Das größte 4-stellige Palindrom als Produkt zweier 2-stelliger Zahlen ist 9009 = 91 * 99.

Hinweis: Für die Multiplikation dreistelliger Zahlen dürfen Sie Variablen des Typs int verwenden. Sie müssen die Klasse Number also nicht um eine Multiplikationsmethode ergänzen.

Wie lautet die Lösung des vierten Eulerschen Problems?

2. Lösung

Quellcode: Siehe auch github.com/peterloos/CSharp_BigPalindrom.git.

Zur Realisierung der Klasse Number stellen wir gleich zwei Lösungen vor: Eine Variante, die die Verwaltung einzelner Ziffern mit Hilfe eines klassischen Arrays organisiert (Listing 2), also in unserem Fall einem Array bestehend aus Digit-Objekten. Im Kontrast dazu steht eine zweite Variante, die ein generisches List<Digit>-Objekt benutzt (Listing 3).

Wir beginnen in Listing 1 mit der Klasse Digit, die als Basis für beide Varianten der Klasse Number dient:

01: class Digit : IComparable, ICloneable
02: {
03:     // private member data
04:     private int digit;
05: 
06:     // c'tors
07:     public Digit()
08:     {
09:         this.digit = 0;
10:     }
11: 
12:     public Digit(int digit) : this()
13:     {
14:         if (digit >= 0 && digit <= 9)
15:             this.digit = digit;
16:     }
17: 
18:     // properties
19:     public int Value
20:     {
21:         get
22:         {
23:             return this.digit;
24:         }
25:     }
26: 
27:     // type conversion operators
28:     public static implicit operator char(Digit d)
29:     {
30:         return (char) (d.Value + '0');
31:     }
32: 
33:     // contract with base class 'Object'
34:     public override bool Equals(Object o)
35:     {
36:         if (!(o is Digit))
37:             return false;
38: 
39:         return this.digit == ((Digit)o).digit;
40:     }
41: 
42:     public override String ToString()
43:     {
44:         return String.Format("{0}", this.digit);
45:     }
46: 
47:     public override int GetHashCode()
48:     {
49:         return this.digit;
50:     }
51: 
52:     // operators
53:     public static bool operator==(Digit d1, Digit d2)
54:     {
55:         return d1.Equals(d2);
56:     }
57: 
58:     public static bool operator!=(Digit d1, Digit d2)
59:     {
60:         return !(d1 == d2);
61:     }
62: 
63:     // implementation of interface 'ICloneable'
64:     public Object Clone()
65:     {
66:         return new Digit(this.digit);
67:     }
68: 
69:     // implementation of interface 'IComparable'
70:     public int CompareTo(Object o)
71:     {
72:         Digit d = (Digit)o;
73:         return (this.digit < d.digit) ? -1 : (this.digit > d.digit) ? 1 : 0;
74:     }
75: }

Beispiel 1. Klasse Digit.


In Listing 2 stellen wir unsere erste Implementierung der Klasse Number vor. Sie verwaltet die Ziffern der Zahl intern in einem klassischen C#-Array bestehend aus Digit-Objekten:

001: using System;
002: using System.Text;
003: 
004: namespace NumberUsingArray
005: {
006:     class Number : IComparable, ICloneable
007:     {
008:         private Digit[] digits;
009: 
010:         // c'tors
011:         public Number()
012:         {
013:             this.digits = new Digit[0];
014:         }
015: 
016:         public Number(String s)
017:         {
018:             // count digits
019:             int count = 0;
020:             for (int i = 0; i < s.Length; i++)
021:                 if (Char.IsDigit(s[i]))
022:                     count++;
023: 
024:             // copy digits into array in reverse order
025:             this.digits = new Digit[count];
026:             for (int k = 0, i = s.Length - 1; i >= 0; i--)
027:             {
028:                 if (Char.IsDigit(s[i]))
029:                 {
030:                     this.digits[k] = new Digit(s[i] - '0');
031:                     k++;
032:                 }
033:             }
034:         }
035: 
036:         public Number(int n)
037:         {
038:             // count digits
039:             int tmp = n;
040:             int count = 0;
041:             while (tmp != 0)
042:             {
043:                 count++;
044:                 tmp = tmp / 10;
045:             }
046: 
047:             this.digits = new Digit[count];
048:             tmp = n;
049: 
050:             for (int i = 0; i < this.digits.Length; i++)
051:             {
052:                 int rem = tmp % 10;
053:                 Digit d = new Digit(rem);
054:                 this.digits[i] = d;
055:                 tmp = tmp / 10;
056:             }
057:         }
058: 
059:         private Number(Digit[] digits)
060:         {
061:             this.digits = digits;
062:         }
063: 
064:         // properties
065:         public int Count
066:         {
067:             get
068:             {
069:                 return this.digits.Length;
070:             }
071:         }
072: 
073:         // indexer
074:         private Digit this[int i]
075:         {
076:             get
077:             {
078:                 Digit d = new Digit(0);
079:                 if (i >= 0 && i < this.digits.Length)
080:                     d = this.digits[i];
081:                 return d;
082:             }
083:         }
084: 
085:         public bool IsSymmetric
086:         {
087:             get
088:             {
089:                 for (int i = 0; i < this.digits.Length / 2; i++)
090:                     if (this.digits[i] != this.digits[this.digits.Length - 1 - i])
091:                         return false;
092: 
093:                 return true;
094:             }
095:         }
096: 
097:         public Number Reverse()
098:         {
099:             Digit[] digits = new Digit[this.digits.Length];
100:             for (int i = 0; i < this.digits.Length; i++)
101:                 digits[i] = (Digit)this.digits[this.digits.Length - 1 - i].Clone();
102: 
103:             return new Number(digits);
104:         }
105: 
106:         public void AddDigit(Digit d)
107:         {
108:             Digit[] tmp = new Digit[this.digits.Length + 1];
109: 
110:             // copy old digits
111:             for (int i = 0; i < this.digits.Length; i++)
112:             {
113:                 tmp[i] = this.digits[i];
114:             }
115: 
116:             // add new digit
117:             tmp[this.digits.Length] = d;
118: 
119:             // switch to new array
120:             this.digits = tmp;
121:         }
122: 
123:         public Number Add(Number n)
124:         {
125:             Number result = new Number();
126: 
127:             int carry = 0;
128:             int maxDigits = Math.Max(this.Count, n.Count);
129:             for (int i = 0; i < maxDigits; i++)
130:             {
131:                 int sum = this[i].Value + n[i].Value + carry;
132:                 carry = (sum >= 10) ? 1 : 0;
133:                 Digit d = new Digit(sum % 10);
134:                 result.AddDigit(d);
135:             }
136:             if (carry == 1)
137:             {
138:                 Digit d = new Digit(1);
139:                 result.AddDigit(d);
140:             }
141: 
142:             return result;
143:         }
144: 
145:         // overloading operators
146:         public static bool operator== (Number n1, Number n2)
147:         {
148:             return n1.Equals(n2);
149:         }
150: 
151:         public static bool operator !=(Number n1, Number n2)
152:         {
153:             return ! n1.Equals(n2);
154:         }
155: 
156:         // contract with base class 'Object'
157:         public override String ToString()
158:         {
159:             StringBuilder sb = new StringBuilder();
160:             for (int i = this.Count - 1; i >= 0; i--)
161:                 sb.Append(this.digits[i]);
162: 
163:             return sb.ToString();
164:         }
165: 
166:         public override bool Equals(Object o)
167:         {
168:             Number n = (Number)o;
169: 
170:             if (this.Count != n.Count)
171:                 return false;
172: 
173:             for (int i = 0; i < this.Count; i++)
174:                 if (!this.digits[i].Equals(n.digits[i]))
175:                     return false;
176: 
177:             return true;
178:         }
179: 
180:         public override int GetHashCode()
181:         {
182:             return this.digits.GetHashCode();
183:         }
184: 
185:         // implementation of interface 'ICloneable'
186:         public Object Clone()
187:         {
188:             Digit[] digits = new Digit[this.digits.Length];
189:             for (int i = 0; i < this.digits.Length; i++)
190:                 digits[i] = (Digit)this.digits[i].Clone();
191: 
192:             return new Number(digits);
193:         }
194: 
195:         // implementation of interface 'IComparable'
196:         public int CompareTo(Object o)
197:         {
198:             Number n = (Number)o;
199: 
200:             if (this.Count < n.Count)
201:                 return -1;
202:             if (this.Count > n.Count)
203:                 return 1;
204: 
205:             for (int i = this.Count - 1; i >= 0; i--)
206:                 if (!this.digits[i].Equals(n.digits[i]))
207:                     return this.digits[i].CompareTo(n.digits[i]);
208: 
209:             return 0;
210:         }
211:     }
212: }

Beispiel 2. Klasse Number mit internem Array von Digit-Objekten.


Die alternative Implementierung der Klasse Number folgt in Listing 3:

001: using System;
002: using System.Collections.Generic;
003: using System.Text;
004: 
005: namespace NumberUsingList
006: {
007:     class Number : IComparable, ICloneable
008:     {
009:         private List<Digit> digits;
010: 
011:         // c'tors
012:         public Number()
013:         {
014:             this.digits = new List<Digit>();
015:         }
016: 
017:         public Number(String s) : this()
018:         {
019:             for (int i = s.Length - 1; i >= 0; i--)
020:             {
021:                 if (Char.IsDigit(s[i]))
022:                 {
023:                     Digit d = new Digit(s[i] - '0');
024:                     this.digits.Add(d);
025:                 }
026:             }
027:         }
028: 
029:         private Number(List<Digit> digits)
030:         {
031:             this.digits = digits;
032:         }
033: 
034:         // properties
035:         public int Count
036:         {
037:             get
038:             {
039:                 return this.digits.Count;
040:             }
041:         }
042: 
043:         // indexer
044:         private Digit this[int i]
045:         {
046:             get
047:             {
048:                 Digit d = new Digit(0);
049:                 if (i >= 0 && i < this.digits.Count)
050:                     d = (Digit)this.digits[i];
051:                 return d;
052:             }
053:         }
054: 
055:         public bool IsSymmetric
056:         {
057:             get
058:             {
059:                 for (int i = 0; i < this.digits.Count / 2; i++)
060:                     if (this.digits[i] != this.digits[this.digits.Count - 1 - i])
061:                         return false;
062: 
063:                 return true;
064:             }
065:         }
066: 
067:         public Number Reverse()
068:         {
069:             List<Digit> digits = new List<Digit>();
070:             for (int i = 0; i < this.digits.Count; i++)
071:             {
072:                 Digit d = (Digit)this.digits[this.digits.Count - 1 - i].Clone();
073:                 digits.Add(d);
074:             }
075: 
076:             return new Number(digits);
077:         }
078: 
079:         public Number Add(Number n)
080:         {
081:             Number result = new Number();
082: 
083:             int carry = 0;
084:             int maxDigits = Math.Max(this.Count, n.Count);
085:             for (int i = 0; i < maxDigits; i++)
086:             {
087:                 int sum = this[i].Value + n[i].Value + carry;
088:                 carry = (sum >= 10) ? 1 : 0;
089:                 Digit d = new Digit(sum % 10);
090:                 result.digits.Add(d);
091:             }
092:             if (carry == 1)
093:             {
094:                 Digit d = new Digit(1);
095:                 result.digits.Add(d);
096:             }
097: 
098:             return result;
099:         }
100: 
101:         public static bool operator ==(Number n1, Number n2)
102:         {
103:             return n1.Equals(n2);
104:         }
105: 
106:         public static bool operator !=(Number n1, Number n2)
107:         {
108:             return !n1.Equals(n2);
109:         }
110: 
111:         // contract with base class 'Object'
112:         public override String ToString()
113:         {
114:             StringBuilder sb = new StringBuilder();
115:             for (int i = this.Count - 1; i >= 0; i--)
116:                 sb.Append(this.digits[i]);
117: 
118:             return sb.ToString();
119:         }
120: 
121:         public override bool Equals(Object o)
122:         {
123:             Number n = (Number)o;
124: 
125:             if (this.Count != n.Count)
126:                 return false;
127: 
128:             for (int i = 0; i < this.Count; i++)
129:                 if (!this.digits[i].Equals(n.digits[i]))
130:                     return false;
131: 
132:             return true;
133:         }
134: 
135:         public override int GetHashCode()
136:         {
137:             return this.digits.GetHashCode();
138:         }
139: 
140:         // implementation of interface 'ICloneable'
141:         public Object Clone()
142:         {
143:             List<Digit> digits = new List<Digit>();
144:             for (int i = 0; i < this.digits.Count; i++)
145:             {
146:                 Digit d = (Digit)this.digits[i].Clone();
147:                 digits.Add(d);
148:             }
149: 
150:             return new Number(digits);
151:         }
152: 
153:         // implementation of interface 'IComparable'
154:         public int CompareTo(Object o)
155:         {
156:             Number n = (Number)o;
157: 
158:             if (this.Count < n.Count)
159:                 return -1;
160:             if (this.Count > n.Count)
161:                 return 1;
162: 
163:             for (int i = this.Count - 1; i >= 0; i--)
164:             {
165:                 Digit d1 = (Digit)this.digits[i];
166:                 Digit d2 = (Digit)n.digits[i];
167: 
168:                 if (!d1.Equals(d2))
169:                     return d1.CompareTo(d2);
170:             }
171: 
172:             return 0;
173:         }
174:     }
175: }

Beispiel 3. Klasse Number – arbeitet intern mit List<Digit>-Objekt.


Die Implementierung eines nicht-deterministischen Algorithmus zum Berechnen von Palindromen stellen wir an Hand der Klasse PalindromCalculator in Listing 4 vor:

01: // using NumberUsingArray;
02: using NumberUsingList;
03: 
04: class PalindromCalculator
05: {
06:     private Number start;        // start number
07:     private Number palindrom;    // palindrom, if any
08:     private int limit;           // maximum number of additions
09:     private int steps;           // number of needed additions
10: 
11:     // c'tors
12:     public PalindromCalculator()
13:     {
14:         this.start = null;
15:         this.palindrom = null;
16:         this.limit = 1000;
17:         this.steps = 0;
18:     }
19: 
20:     // properties
21:     public Number Start
22:     {
23:         get
24:         {
25:             return this.start;
26:         }
27: 
28:         set
29:         {
30:             this.start = value;
31:         }
32:     }
33: 
34:     public Number Palindrom
35:     {
36:         get
37:         {
38:             return this.palindrom;
39:         }
40:     }
41: 
42:     public int Limit
43:     {
44:         get
45:         {
46:             return this.limit;
47:         }
48: 
49:         set
50:         {
51:             this.limit = value;
52:         }
53:     }
54: 
55:     public int Steps
56:     {
57:         get
58:         {
59:             return this.steps;
60:         }
61:     }
62: 
63:     // public methods
64:     public bool CalcPalindrom()
65:     {
66:         this.palindrom = null;
67:         this.steps = 0;
68: 
69:         Number n = this.start;
70:         for (int i = 0; i < this.limit; i++)
71:         {
72:             if (n.IsSymmetric)
73:             {
74:                 this.palindrom = (Number)n.Clone();
75:                 this.steps = i;
76:                 return true;
77:             }
78: 
79:             Number m = n.Reverse();
80:             n = n.Add(m);
81:         }
82: 
83:         this.palindrom = null;
84:         return false;
85:     }
86: }

Beispiel 4. Klasse PalindromCalculator.


Leider produziert die CalcPalindrom-Methode nicht bei jedem ihrer Aufrufe ein Palindrom. Wir müssen aus diesem Grund die Klasse sehr sorgfältigen Tests unterziehen – einen Ausschnitt des Testszenarios finden Sie in den nachfolgenden Ausschnitten vor:

// currently known most delayed Palindromic number record
PalindromCalculator cal = new PalindromCalculator();
cal.Limit = 300;
cal.Start = new Number("1186060307891929990");
if (cal.CalcPalindrom())
{
    Console.WriteLine("Most Delayed Palindromic Number Record:");
    Console.WriteLine("Start:     {0}", cal.Start);
    Console.WriteLine("Palindrom: {0}", cal.Palindrom, cal.Steps);
    Console.WriteLine("Steps:     {0}", cal.Steps);
}

Ausgabe:

Most Delayed Palindromic Number Record:
Start:     1186060307891929990
Palindrom: 44562665878976437622437848976653870388884783662598425855963436955852489526638748888307835667984873422673467987856626544
Steps:     261

Die Fragestellung aus dem Aufgabenteil beantworten wir mit folgendem Codefragment:

PalindromCalculator cal = new PalindromCalculator();
cal.Limit = 1000;

bool verbose = false;

int foundPalindroms = 0;
int maxSteps = -1;
for (int i = 1; i <= 10000; i++)
{
    String s = i.ToString();
    cal.Start = new Number(s);
    bool b = cal.CalcPalindrom();
    if (b)
    {
        foundPalindroms++;

        if (cal.Steps > maxSteps)
            maxSteps = cal.Steps;

        if (verbose)
        {
            Console.WriteLine("Found Palindrom: Start = {0} -- Palindrom = {1} -- Steps: {2}",
                cal.Start, cal.Palindrom, cal.Steps);
        }
        else
        {
            if (i % 1000 == 0)
                Console.Write(".");
        }
    }
    else
    {
        if (verbose)
        {
            Console.WriteLine("No Palindrom: Start = {0}", cal.Start);
        }
    }
}

Console.WriteLine();
Console.WriteLine("Total Palindroms: {0}      Max Steps: {1}",
    foundPalindroms, maxSteps);

Ausgabe:

Total Palindroms: 9754      Max Steps: 24

Zum Abschluss wollen wir ein Codefragment zur Lösung des vierten Eulerschen Problems betrachten:

int i = 1, j = 1;
int candidate = 1;

for (int n = 111; n < 999; n++)
{
    for (int m = 111; m < 999; m++)
    {
        if (n < m)
        {
            int prod = n * m;
            String s = prod.ToString();
            Number num = new Number(s);
            if (num.IsSymmetric)
            {
                if (prod > candidate)
                {
                    i = n;
                    j = m;
                    candidate = i * j;
                }
            }
        }
    }
}

Console.WriteLine("Solution of fourth Euler problem:");
Console.WriteLine("{0} * {1} = {2}", i, j, i * j);

Ausgabe:

Solution of fourth Euler problem:
913 * 993 = 906609