Subversion Repositories distributed

Rev

Rev 30 | Rev 37 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 30 Rev 32
1
package de.viathinksoft.immortal.genX;
1
package de.viathinksoft.immortal.genX;
2
 
2
 
3
import java.io.BufferedReader;
3
import java.io.BufferedReader;
4
import java.io.BufferedWriter;
4
import java.io.BufferedWriter;
5
import java.io.File;
5
import java.io.File;
6
import java.io.FileNotFoundException;
6
import java.io.FileNotFoundException;
7
import java.io.FileReader;
7
import java.io.FileReader;
8
import java.io.FileWriter;
8
import java.io.FileWriter;
9
import java.io.IOException;
9
import java.io.IOException;
10
import java.math.BigInteger;
10
import java.math.BigInteger;
11
 
11
 
12
/**
12
/**
13
 * Immortable Iterator
13
 * Immortable Iterator
14
 *
14
 *
15
 * @author Daniel Marschall, Big thanks to the users of MatheBoard.de
15
 * @author Daniel Marschall, Big thanks to the users of MatheBoard.de
16
 * @see http://www.matheboard.de/archive/435725/thread.html
16
 * @see http://www.matheboard.de/archive/435725/thread.html
17
 */
17
 */
18
public class ImmortableNumberSearch {
18
public class ImmortalNumberSearch {
19
 
19
 
20
        private static final String SIGNATURE = "Immortal Number Report File Version 2.02";
20
        private static final String SIGNATURE = "Immortal Number Report File Version 2.02";
21
        private static final String SIGNATURE_MINOR = "Iterator GenX Java (100k save-interval, load-integrity-check, int32-r, array-object) r29";
21
        private static final String SIGNATURE_MINOR = "Iterator GenX Java (100k save-interval, load-integrity-check, int32-r, array-object) r29";
22
        private static final String END_SIG = "END OF REPORT";
22
        private static final String END_SIG = "END OF REPORT";
23
        private static final int SOFTBREAK = 76;
23
        private static final int SOFTBREAK = 76;
24
 
24
 
25
        private ByteArray a;
25
        private ByteArray a;
26
        private String filename;
26
        private String filename;
27
        private int saveInterval = 100000;
27
        private int saveInterval = 100000;
28
        private int u = -1;
28
        private int u = -1;
29
        private int r = -1; // FUTURE: r als BigInteger
29
        private int r = -1; // FUTURE: r als BigInteger
30
        private String creation_time;
30
        private String creation_time;
31
        private String backupDir = "backup";
31
        private String backupDir = "backup";
32
 
32
 
33
        private static final int INITIAL_SIZE = 1000000;
33
        private static final int INITIAL_SIZE = 1000000;
34
        private static final int EXPANSION_SIZE = 1000000;
34
        private static final int EXPANSION_SIZE = 1000000;
35
 
35
 
36
        private boolean do_integrity_test = false;
36
        private boolean do_integrity_test = false;
37
        private boolean verbose = false;
37
        private boolean verbose = false;
38
 
38
 
39
        public boolean isDo_integrity_test() {
39
        public boolean isDo_integrity_test() {
40
                return do_integrity_test;
40
                return do_integrity_test;
41
        }
41
        }
42
 
42
 
43
        public void setDo_integrity_test(boolean doIntegrityTest) {
43
        public void setDo_integrity_test(boolean doIntegrityTest) {
44
                do_integrity_test = doIntegrityTest;
44
                do_integrity_test = doIntegrityTest;
45
        }
45
        }
46
 
46
 
47
        public boolean isVerbose() {
47
        public boolean isVerbose() {
48
                return verbose;
48
                return verbose;
49
        }
49
        }
50
 
50
 
51
        public void setVerbose(boolean verbose) {
51
        public void setVerbose(boolean verbose) {
52
                this.verbose = verbose;
52
                this.verbose = verbose;
53
        }
53
        }
54
 
54
 
55
        protected void log(String s) {
55
        protected void log(String s) {
56
                if (verbose) {
56
                if (verbose) {
57
                        String timestamp = DateUtils.now("EEE, d MMM yyyy HH:mm:ss Z");
57
                        String timestamp = DateUtils.now("EEE, d MMM yyyy HH:mm:ss Z");
58
                        System.out.println(timestamp + " - " + s); // FURUE: In eine
58
                        System.out.println(timestamp + " - " + s); // FURUE: In eine
59
                                                                                                                // Log-Datei schreiben
59
                                                                                                                // Log-Datei schreiben
60
                }
60
                }
61
        }
61
        }
62
 
62
 
63
        public ImmortableNumberSearch(String filename) throws LoadException {
63
        public ImmortalNumberSearch(String filename) throws LoadException {
64
                this.filename = filename;
64
                this.filename = filename;
65
                load();
65
                load();
66
        }
66
        }
67
 
67
 
68
        public String getBackupDir() {
68
        public String getBackupDir() {
69
                return backupDir;
69
                return backupDir;
70
        }
70
        }
71
 
71
 
72
        public void setBackupDir(String backupDir) {
72
        public void setBackupDir(String backupDir) {
73
                this.backupDir = backupDir;
73
                this.backupDir = backupDir;
74
        }
74
        }
75
 
75
 
76
        public int getSaveInterval() {
76
        public int getSaveInterval() {
77
                return this.saveInterval;
77
                return this.saveInterval;
78
        }
78
        }
79
 
79
 
80
        public ByteArray getA() {
80
        public ByteArray getA() {
81
                return a;
81
                return a;
82
        }
82
        }
83
 
83
 
84
        public int getU() {
84
        public int getU() {
85
                return u;
85
                return u;
86
        }
86
        }
87
 
87
 
88
        public int getR() {
88
        public int getR() {
89
                return r;
89
                return r;
90
        }
90
        }
91
 
91
 
92
        public String getFilename() {
92
        public String getFilename() {
93
                return filename;
93
                return filename;
94
        }
94
        }
95
 
95
 
96
        public void setSaveInterval(int saveInterval) {
96
        public void setSaveInterval(int saveInterval) {
97
                this.saveInterval = saveInterval;
97
                this.saveInterval = saveInterval;
98
        }
98
        }
99
 
99
 
100
        private boolean savePointExists() {
100
        private boolean savePointExists() {
101
                return new File(filename).exists();
101
                return new File(filename).exists();
102
        }
102
        }
103
 
103
 
104
        private void load() throws LoadException {
104
        private void load() throws LoadException {
105
                if (!savePointExists()) {
105
                if (!savePointExists()) {
106
                        this.a = new ByteArray(INITIAL_SIZE, EXPANSION_SIZE);
106
                        this.a = new ByteArray(INITIAL_SIZE, EXPANSION_SIZE);
107
                        return;
107
                        return;
108
                }
108
                }
109
 
109
 
110
                BufferedReader f;
110
                BufferedReader f;
111
                try {
111
                try {
112
                        f = new BufferedReader(new FileReader(filename));
112
                        f = new BufferedReader(new FileReader(filename));
113
                } catch (FileNotFoundException e) {
113
                } catch (FileNotFoundException e) {
114
                        // Will not happen because of savePointExists().
114
                        // Will not happen because of savePointExists().
115
                        return;
115
                        return;
116
                }
116
                }
117
 
117
 
118
                u = -1;
118
                u = -1;
119
                r = -1;
119
                r = -1;
120
 
120
 
121
                try {
121
                try {
122
                        try {
122
                        try {
123
                                String s = f.readLine();
123
                                String s = f.readLine();
124
                                if (!s.equals(SIGNATURE)) {
124
                                if (!s.equals(SIGNATURE)) {
125
                                        throw new LoadException("Corrupt: Wrong signature");
125
                                        throw new LoadException("Corrupt: Wrong signature");
126
                                }
126
                                }
127
 
127
 
128
                                f.readLine(); // Minor. signature
128
                                f.readLine(); // Minor. signature
129
                                f.readLine(); // ""
129
                                f.readLine(); // ""
130
 
130
 
131
                                f.readLine(); // "(Starting time)"
131
                                f.readLine(); // "(Starting time)"
132
                                creation_time = f.readLine();
132
                                creation_time = f.readLine();
133
                                f.readLine(); // ""
133
                                f.readLine(); // ""
134
 
134
 
135
                                f.readLine(); // "(Save timestamp)"
135
                                f.readLine(); // "(Save timestamp)"
136
                                f.readLine(); // Timestamp
136
                                f.readLine(); // Timestamp
137
                                f.readLine(); // ""
137
                                f.readLine(); // ""
138
 
138
 
139
                                f.readLine(); // "(Digits)"
139
                                f.readLine(); // "(Digits)"
140
                                s = f.readLine();
140
                                s = f.readLine();
141
                                u = Integer.parseInt(s) - 1;
141
                                u = Integer.parseInt(s) - 1;
142
                                f.readLine(); // ""
142
                                f.readLine(); // ""
143
 
143
 
144
                                f.readLine(); // "(r)"
144
                                f.readLine(); // "(r)"
145
                                s = f.readLine();
145
                                s = f.readLine();
146
                                r = Integer.parseInt(s); // FUTURE: (1) Multi-Line-Support?
146
                                r = Integer.parseInt(s); // FUTURE: (1) Multi-Line-Support?
147
                                f.readLine(); // ""
147
                                f.readLine(); // ""
148
 
148
 
149
                                this.a = new ByteArray(u + 1 + EXPANSION_SIZE, EXPANSION_SIZE);
149
                                this.a = new ByteArray(u + 1 + EXPANSION_SIZE, EXPANSION_SIZE);
150
 
150
 
151
                                f.readLine(); // "(M5 reversed)"
151
                                f.readLine(); // "(M5 reversed)"
152
                                do {
152
                                do {
153
                                        s = f.readLine();
153
                                        s = f.readLine();
154
                                        for (int i = 0; i < s.length(); i++) {
154
                                        for (int i = 0; i < s.length(); i++) {
155
                                                a.add(Byte.parseByte(s.substring(i, i + 1)));
155
                                                a.add(Byte.parseByte(s.substring(i, i + 1)));
156
                                        }
156
                                        }
157
                                } while (!s.equals(""));
157
                                } while (!s.equals(""));
158
 
158
 
159
                                if (u + 1 != a.count()) {
159
                                if (u + 1 != a.count()) {
160
                                        throw new LoadException(
160
                                        throw new LoadException(
161
                                                        "Corrupt: Formal and actual length mismatch!");
161
                                                        "Corrupt: Formal and actual length mismatch!");
162
                                }
162
                                }
163
 
163
 
164
                                s = f.readLine();
164
                                s = f.readLine();
165
                                if (!s.equals(END_SIG)) {
165
                                if (!s.equals(END_SIG)) {
166
                                        throw new LoadException("Corrupt: End-signature mismatch.");
166
                                        throw new LoadException("Corrupt: End-signature mismatch.");
167
                                }
167
                                }
168
                        } finally {
168
                        } finally {
169
                                f.close();
169
                                f.close();
170
                        }
170
                        }
171
                } catch (IOException e) {
171
                } catch (IOException e) {
172
                        throw new LoadException(e);
172
                        throw new LoadException(e);
173
                }
173
                }
174
        }
174
        }
175
 
175
 
176
        private void save(boolean integrityTest) throws SaveException {
176
        private void save(boolean integrityTest) throws SaveException {
177
                if ((integrityTest) && (do_integrity_test)) {
177
                if ((integrityTest) && (do_integrity_test)) {
178
                        log("Beginne Selbsttest vor erster Speicherung...");
178
                        log("Beginne Selbsttest vor erster Speicherung...");
179
 
179
 
180
                        if (!integryTest()) {
180
                        if (!integryTest()) {
181
                                throw new SaveException(
181
                                throw new SaveException(
182
                                                "Integrity test failed. (Loaded file broken?) Will not save.");
182
                                                "Integrity test failed. (Loaded file broken?) Will not save.");
183
                        }
183
                        }
184
                }
184
                }
185
 
185
 
186
                log("Speichere bei u=" + (u + 1));
186
                log("Speichere bei u=" + (u + 1));
187
 
187
 
188
                String timestamp = DateUtils.now("EEE, d MMM yyyy HH:mm:ss Z");
188
                String timestamp = DateUtils.now("EEE, d MMM yyyy HH:mm:ss Z");
189
                String timestamp_filename = DateUtils.now("dd-MM-yyyy_HH-mm-ss");
189
                String timestamp_filename = DateUtils.now("dd-MM-yyyy_HH-mm-ss");
190
 
190
 
191
                try {
191
                try {
192
                        BufferedWriter f = new BufferedWriter(new FileWriter(filename));
192
                        BufferedWriter f = new BufferedWriter(new FileWriter(filename));
193
 
193
 
194
                        try {
194
                        try {
195
                                f.write(SIGNATURE + "\r\n");
195
                                f.write(SIGNATURE + "\r\n");
196
 
196
 
197
                                f.write(SIGNATURE_MINOR + "\r\n");
197
                                f.write(SIGNATURE_MINOR + "\r\n");
198
                                f.write("\r\n");
198
                                f.write("\r\n");
199
 
199
 
200
                                f.write("(Starting time)\r\n");
200
                                f.write("(Starting time)\r\n");
201
                                f.write(creation_time + "\r\n");
201
                                f.write(creation_time + "\r\n");
202
                                f.write("\r\n");
202
                                f.write("\r\n");
203
 
203
 
204
                                f.write("(Save timestamp)\r\n");
204
                                f.write("(Save timestamp)\r\n");
205
                                f.write(timestamp + "\r\n");
205
                                f.write(timestamp + "\r\n");
206
                                f.write("\r\n");
206
                                f.write("\r\n");
207
 
207
 
208
                                f.write("(Digits)\r\n");
208
                                f.write("(Digits)\r\n");
209
                                f.write((u + 1) + "\r\n");
209
                                f.write((u + 1) + "\r\n");
210
                                f.write("\r\n");
210
                                f.write("\r\n");
211
 
211
 
212
                                f.write("(r)\r\n");
212
                                f.write("(r)\r\n");
213
                                f.write(r + "\r\n"); // FUTURE: (1) Multi-Line-Support?
213
                                f.write(r + "\r\n"); // FUTURE: (1) Multi-Line-Support?
214
                                f.write("\r\n");
214
                                f.write("\r\n");
215
 
215
 
216
                                f.write("(M5 reversed)\r\n");
216
                                f.write("(M5 reversed)\r\n");
217
                                int i;
217
                                int i;
218
                                for (i = 0; i < a.count(); i++) {
218
                                for (i = 0; i < a.count(); i++) {
219
                                        byte xa = a.get(i);
219
                                        byte xa = a.get(i);
220
                                        f.write("" + xa);
220
                                        f.write("" + xa);
221
                                        if ((i + 1) % SOFTBREAK == 0) {
221
                                        if ((i + 1) % SOFTBREAK == 0) {
222
                                                f.write("\r\n");
222
                                                f.write("\r\n");
223
                                        }
223
                                        }
224
                                }
224
                                }
225
                                if ((i + 1) % SOFTBREAK != 0) {
225
                                if ((i + 1) % SOFTBREAK != 0) {
226
                                        f.write("\r\n");
226
                                        f.write("\r\n");
227
                                }
227
                                }
228
                                f.write("\r\n");
228
                                f.write("\r\n");
229
 
229
 
230
                                f.write(END_SIG);
230
                                f.write(END_SIG);
231
                        } finally {
231
                        } finally {
232
                                f.close();
232
                                f.close();
233
                        }
233
                        }
234
                } catch (IOException e) {
234
                } catch (IOException e) {
235
                        throw new SaveException("Could not save master file.", e);
235
                        throw new SaveException("Could not save master file.", e);
236
                }
236
                }
237
 
237
 
238
                // Make backup
238
                // Make backup
239
 
239
 
240
                new File(backupDir).mkdir();
240
                new File(backupDir).mkdir();
241
                String bak_filename = backupDir + "/immortal_" + timestamp_filename
241
                String bak_filename = backupDir + "/immortal_" + timestamp_filename
242
                                + "_" + (u + 1) + ".txt";
242
                                + "_" + (u + 1) + ".txt";
243
                try {
243
                try {
244
                        FileUtils.copyFile(new File(filename), new File(bak_filename));
244
                        FileUtils.copyFile(new File(filename), new File(bak_filename));
245
                } catch (IOException e) {
245
                } catch (IOException e) {
246
                        throw new SaveException("Could not make backup", e);
246
                        throw new SaveException("Could not make backup", e);
247
                }
247
                }
248
 
248
 
249
                if ((integrityTest) && (do_integrity_test)) {
249
                if ((integrityTest) && (do_integrity_test)) {
250
                        log("Erste Speicherung absolviert. Stabile Phase hat begonnen.");
250
                        log("Erste Speicherung absolviert. Stabile Phase hat begonnen.");
251
                }
251
                }
252
        }
252
        }
253
 
253
 
254
        public void calcIterate(int amount) throws SaveException {
254
        public void calcIterate(int amount) throws SaveException {
255
                log("Beginn der Rechenarbeit...");
255
                log("Beginn der Rechenarbeit...");
256
 
256
 
257
                int cnt = 0;
257
                int cnt = 0;
258
 
258
 
259
                // Wir führen beim ersten Speichern einen weiteren
259
                // Wir führen beim ersten Speichern einen weiteren
260
                // integrity-Test durch. Grund: Wäre bei einer Fortsetzung einer
260
                // integrity-Test durch. Grund: Wäre bei einer Fortsetzung einer
261
                // Datei das "r" falsch (der Datenteil aber korrekt), dann würde
261
                // Datei das "r" falsch (der Datenteil aber korrekt), dann würde
262
                // diese Datei beim Speichern ungültige Daten enthalten (Zahl
262
                // diese Datei beim Speichern ungültige Daten enthalten (Zahl
263
                // nicht immortabel).
263
                // nicht immortabel).
264
                boolean firstSave = true;
264
                boolean firstSave = true;
265
 
265
 
266
                if (a.isEmpty()) {
266
                if (a.isEmpty()) {
267
                        creation_time = DateUtils.now("EEE, d MMM yyyy HH:mm:ss Z");
267
                        creation_time = DateUtils.now("EEE, d MMM yyyy HH:mm:ss Z");
268
                        a.add((byte) 5);
268
                        a.add((byte) 5);
269
                        a.add((byte) 2);
269
                        a.add((byte) 2);
270
                        u = 1;
270
                        u = 1;
271
                        r = 2;
271
                        r = 2;
272
                        cnt += 2;
272
                        cnt += 2;
273
                }
273
                }
274
 
274
 
275
                int s, m, k;
275
                int s, m, k;
276
 
276
 
277
                do {
277
                do {
278
                        r = (r /* - a.get(u) */) / 10 + a.get(u);
278
                        r = (r /* - a.get(u) */) / 10 + a.get(u);
279
                        s = 0;
279
                        s = 0;
280
                        for (m = 1, k = u; m < k; m++, k--) {
280
                        for (m = 1, k = u; m < k; m++, k--) {
281
                                s += a.get(m) * a.get(k);
281
                                s += a.get(m) * a.get(k);
282
                        }
282
                        }
283
                        r += 2 * s;
283
                        r += 2 * s;
284
                        if (m == k) {
284
                        if (m == k) {
285
                                r += a.get(m) * a.get(m);
285
                                r += a.get(m) * a.get(m);
286
                        }
286
                        }
287
                        u++;
287
                        u++;
288
                        a.add((byte) (r % 10));
288
                        a.add((byte) (r % 10));
289
 
289
 
290
                        cnt++;
290
                        cnt++;
291
                        if (cnt % saveInterval == 0) {
291
                        if (cnt % saveInterval == 0) {
292
                                save(firstSave);
292
                                save(firstSave);
293
                                firstSave = false;
293
                                firstSave = false;
294
                        }
294
                        }
295
                } while (cnt != amount);
295
                } while (cnt != amount);
296
 
296
 
297
                // Wir brauchen nicht zwei Mal zu speichern
297
                // Wir brauchen nicht zwei Mal zu speichern
298
                if (cnt - 1 % saveInterval != 0) {
298
                if (cnt - 1 % saveInterval != 0) {
299
                        log("Letzte Speicherung vor Ende...");
299
                        log("Letzte Speicherung vor Ende...");
300
                        save(firstSave);
300
                        save(firstSave);
301
                        // firstSave = false;
301
                        // firstSave = false;
302
                }
302
                }
303
 
303
 
304
                log("Ende der Rechenarbeit...");
304
                log("Ende der Rechenarbeit...");
305
        }
305
        }
306
 
306
 
307
        public byte getDigitReverse(int u) {
307
        public byte getDigitReverse(int u) {
308
                return a.get(u);
308
                return a.get(u);
309
        }
309
        }
310
 
310
 
311
        public StringBuilder M5_StringBuilder(int u) {
311
        public StringBuilder M5_StringBuilder(int u) {
312
                StringBuilder s = new StringBuilder();
312
                StringBuilder s = new StringBuilder();
313
                for (int i = 0; i < a.count(); i++) {
313
                for (int i = 0; i < a.count(); i++) {
314
                        byte xa = a.get(i);
314
                        byte xa = a.get(i);
315
                        s.append("" + xa);
315
                        s.append("" + xa);
316
                }
316
                }
317
                s.reverse();
317
                s.reverse();
318
                return s;
318
                return s;
319
        }
319
        }
320
 
320
 
321
        public String M5_String(int u) {
321
        public String M5_String(int u) {
322
                return M5_StringBuilder(u).toString();
322
                return M5_StringBuilder(u).toString();
323
        }
323
        }
324
 
324
 
325
        public BigInteger M5_BigInteger(int u) {
325
        public BigInteger M5_BigInteger(int u) {
326
                return new BigInteger(M5_String(u));
326
                return new BigInteger(M5_String(u));
327
        }
327
        }
328
 
328
 
329
        public StringBuilder M6_StringBuilder(int u) {
329
        public StringBuilder M6_StringBuilder(int u) {
330
                StringBuilder s = new StringBuilder();
330
                StringBuilder s = new StringBuilder();
331
                for (int i = 0; i < a.count(); i++) {
331
                for (int i = 0; i < a.count(); i++) {
332
                        byte xa = a.get(i);
332
                        byte xa = a.get(i);
333
                        if (i > 0) {
333
                        if (i > 0) {
334
                                s.append("" + (9 - xa));
334
                                s.append("" + (9 - xa));
335
                        } else {
335
                        } else {
336
                                s.append("" + (11 - xa));
336
                                s.append("" + (11 - xa));
337
                        }
337
                        }
338
                }
338
                }
339
                s.reverse();
339
                s.reverse();
340
                return s;
340
                return s;
341
        }
341
        }
342
 
342
 
343
        public String M6_String(int u) {
343
        public String M6_String(int u) {
344
                return M6_StringBuilder(u).toString();
344
                return M6_StringBuilder(u).toString();
345
        }
345
        }
346
 
346
 
347
        public BigInteger M6_BigInteger(int u) {
347
        public BigInteger M6_BigInteger(int u) {
348
                return new BigInteger(M6_String(u));
348
                return new BigInteger(M6_String(u));
349
        }
349
        }
350
 
350
 
351
        protected static boolean isImmortable(BigInteger num, int m) {
351
        protected static boolean isImmortable(BigInteger num, int m) {
352
                // Alternativ
352
                // Alternativ
353
                // return num.pow(2).toString().endsWith(num.toString());
353
                // return num.pow(2).toString().endsWith(num.toString());
354
 
354
 
355
                // n² === n (mod 10^m) <===> n²%10^m == n%10^m == n
355
                // n² === n (mod 10^m) <===> n²%10^m == n%10^m == n
356
 
356
 
357
                BigInteger m_pow = BigInteger.TEN.pow(m);
357
                BigInteger m_pow = BigInteger.TEN.pow(m);
358
                return num.pow(2).mod(m_pow).equals(num);
358
                return num.pow(2).mod(m_pow).equals(num);
359
        }
359
        }
360
 
360
 
361
        protected static boolean isImmortable(BigInteger num) {
361
        protected static boolean isImmortable(BigInteger num) {
362
                int m = num.toString().length();
362
                int m = num.toString().length();
363
                return isImmortable(num, m);
363
                return isImmortable(num, m);
364
        }
364
        }
365
 
365
 
366
        public boolean integryTest() {
366
        public boolean integryTest() {
367
                // return isImmortable(M5_BigInteger(u), a.count());
367
                // return isImmortable(M5_BigInteger(u), a.count());
368
                return isImmortable(M6_BigInteger(u), a.count());
368
                return isImmortable(M6_BigInteger(u), a.count());
369
        }
369
        }
370
}
370
}
371
 
371