Rev 14 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 14 | Rev 15 | ||
---|---|---|---|
Line 1... | Line 1... | ||
1 | package de.viathinksoft.immortable.genX; |
1 | package de.viathinksoft.immortable.genX; |
2 | 2 | ||
3 | // TODO: Immort Test + Backups regelmäßig durchführen |
3 | // TODO: r als BigInteger |
4 | 4 | ||
5 | import java.io.BufferedReader; |
5 | import java.io.BufferedReader; |
6 | import java.io.BufferedWriter; |
6 | import java.io.BufferedWriter; |
7 | import java.io.File; |
7 | import java.io.File; |
- | 8 | import java.io.FileNotFoundException; |
|
8 | import java.io.FileReader; |
9 | import java.io.FileReader; |
9 | import java.io.FileWriter; |
10 | import java.io.FileWriter; |
10 | import java.io.IOException; |
11 | import java.io.IOException; |
- | 12 | import java.math.BigInteger; |
|
11 | import java.util.Vector; |
13 | import java.util.Vector; |
12 | 14 | ||
- | 15 | /** |
|
13 | public class ImmortIterator { |
16 | * Immortable Iterator |
14 | - | ||
15 | /* |
17 | * |
16 | * public static boolean isImmortable(BigInteger num) { |
18 | * @author Daniel Marschall, René Gruber |
17 | // Alternativ: n²%10^m == n%10^m |
- | |
18 | return num.pow(2).toString().endsWith(num.toString()); |
19 | * @see http://www.matheboard.de/thread.php?postid=1259938 |
19 | } |
- | |
20 | - | ||
21 | */ |
20 | */ |
- | 21 | public class ImmortableNumberSearch { |
|
22 | 22 | ||
23 | // TODO: Output M5/M6 function... |
23 | private static final String SIGNATURE = "Immortable Number Report File Version 2000"; |
24 | // TODO: r als BigInteger? |
24 | private static final String SIGNATURE_MINOR = "Iterator GenX Java int"; |
25 | - | ||
26 | private static final String SIGNATURE = "Immortable Interator GenX int DSO 1000"; |
25 | private static final String END_SIG = "END OF REPORT"; |
27 | private static final int SOFTBREAK = 76; |
26 | private static final int SOFTBREAK = 76; |
28 | 27 | ||
29 | private Vector<Integer> a = new Vector<Integer>(); |
28 | private Vector<Integer> a = null; |
30 | private int u; |
- | |
31 | private int r; |
- | |
32 | private int saveInterval = 100000; // TODO: Größer |
- | |
33 | private String filename; |
29 | private String filename; |
- | 30 | private int saveInterval = 10000; |
|
- | 31 | private int u = -1; |
|
- | 32 | private int r = -1; |
|
- | 33 | private String creation_time; |
|
- | 34 | private String backupDir = "backup"; |
|
34 | 35 | ||
35 | // TODO: load+save prüfen |
- | |
36 | - | ||
37 | public ImmortIterator(String filename) throws Exception { |
36 | public ImmortableNumberSearch(String filename) throws LoadException { |
38 | this.filename = filename; |
37 | this.filename = filename; |
39 | load(); |
38 | load(); |
40 | } |
39 | } |
41 | 40 | ||
- | 41 | public String getBackupDir() { |
|
- | 42 | return backupDir; |
|
- | 43 | } |
|
- | 44 | ||
- | 45 | public void setBackupDir(String backupDir) { |
|
- | 46 | this.backupDir = backupDir; |
|
- | 47 | } |
|
- | 48 | ||
42 | public int getSaveInterval() { |
49 | public int getSaveInterval() { |
43 | return this.saveInterval; |
50 | return this.saveInterval; |
44 | } |
51 | } |
45 | 52 | ||
- | 53 | public Vector<Integer> getA() { |
|
- | 54 | return a; |
|
- | 55 | } |
|
- | 56 | ||
- | 57 | public int getU() { |
|
- | 58 | return u; |
|
- | 59 | } |
|
- | 60 | ||
- | 61 | public int getR() { |
|
- | 62 | return r; |
|
- | 63 | } |
|
- | 64 | ||
- | 65 | public String getFilename() { |
|
- | 66 | return filename; |
|
- | 67 | } |
|
- | 68 | ||
46 | public void setSaveInterval(int saveInterval) { |
69 | public void setSaveInterval(int saveInterval) { |
47 | this.saveInterval = saveInterval; |
70 | this.saveInterval = saveInterval; |
48 | } |
71 | } |
49 | 72 | ||
50 | private boolean savePointExists() { |
73 | private boolean savePointExists() { |
51 | return new File(filename).exists(); |
74 | return new File(filename).exists(); |
52 | } |
75 | } |
53 | 76 | ||
54 | private void load() throws Exception { |
77 | private void load() throws LoadException { |
55 | if (!savePointExists()) |
78 | if (!savePointExists()) { |
56 | return; |
79 | return; |
- | 80 | } |
|
- | 81 | ||
- | 82 | BufferedReader f; |
|
- | 83 | try { |
|
- | 84 | f = new BufferedReader(new FileReader(filename)); |
|
- | 85 | } catch (FileNotFoundException e) { |
|
- | 86 | // Will not happen because of savePointExists(). |
|
- | 87 | return; |
|
- | 88 | } |
|
57 | 89 | ||
58 | BufferedReader f = new BufferedReader(new FileReader(filename)); |
90 | a = null; |
- | 91 | u = -1; |
|
- | 92 | r = -1; |
|
59 | 93 | ||
- | 94 | try { |
|
- | 95 | try { |
|
60 | String s = f.readLine(); |
96 | String s = f.readLine(); |
61 | if (!s.equals(SIGNATURE)) { |
97 | if (!s.equals(SIGNATURE)) { |
62 | throw new Exception("Wrong signature"); |
98 | throw new LoadException("Wrong signature"); |
63 | } |
99 | } |
64 | 100 | ||
- | 101 | f.readLine(); // Minor. signature |
|
65 | f.readLine(); // "" |
102 | f.readLine(); // "" |
66 | f.readLine(); // "(u)" |
- | |
67 | 103 | ||
- | 104 | f.readLine(); // "(Starting time)" |
|
68 | s = f.readLine(); |
105 | creation_time = f.readLine(); |
69 | u = Integer.parseInt(s); |
106 | f.readLine(); // "" |
70 | 107 | ||
- | 108 | f.readLine(); // "(Save timestamp)" |
|
- | 109 | f.readLine(); // Timestamp |
|
71 | f.readLine(); // "" |
110 | f.readLine(); // "" |
72 | f.readLine(); // "(r)" |
- | |
73 | 111 | ||
- | 112 | f.readLine(); // "(u)" |
|
74 | s = f.readLine(); |
113 | s = f.readLine(); |
75 | r = Integer.parseInt(s); // TODO: more than 1 line |
114 | u = Integer.parseInt(s); |
- | 115 | f.readLine(); // "" |
|
76 | 116 | ||
- | 117 | f.readLine(); // "(r)" |
|
- | 118 | s = f.readLine(); |
|
- | 119 | r = Integer.parseInt(s); // FUTURE: (1) Multi-Line-Support? |
|
77 | f.readLine(); // "" |
120 | f.readLine(); // "" |
78 | f.readLine(); // "(M5rev)" |
- | |
79 | 121 | ||
- | 122 | f.readLine(); // "(M5rev)" |
|
80 | a.clear(); |
123 | a = new Vector<Integer>(); |
81 | do { |
124 | do { |
82 | s = f.readLine(); |
125 | s = f.readLine(); |
83 | if (s == null) break; // eof |
- | |
84 | for (int i=0; i<s.length(); i++) { |
126 | for (int i = 0; i < s.length(); i++) { |
85 | a.add(new Integer(s.substring(i, i+1))); |
127 | a.add(new Integer(s.substring(i, i + 1))); |
86 | } |
128 | } |
87 | } while (!s.equals("")); |
129 | } while (!s.equals("")); |
88 | 130 | ||
- | 131 | if (!integryTest()) { |
|
- | 132 | throw new LoadException("Corrupt: Not immortable!"); |
|
- | 133 | } |
|
- | 134 | ||
- | 135 | if (u+1 != a.size()) { |
|
- | 136 | throw new LoadException( |
|
- | 137 | "Corrupt: Formal and actual length mismatch!"); |
|
- | 138 | } |
|
- | 139 | ||
- | 140 | s = f.readLine(); |
|
- | 141 | if (!s.equals(END_SIG)) { |
|
- | 142 | throw new LoadException("Corrupt: End-signature mismatch."); |
|
- | 143 | } |
|
- | 144 | } finally { |
|
89 | f.close(); |
145 | f.close(); |
90 | } |
146 | } |
- | 147 | } catch (IOException e) { |
|
- | 148 | throw new LoadException(e); |
|
- | 149 | } |
|
- | 150 | } |
|
91 | 151 | ||
92 | private void save() throws IOException { |
152 | private void save(boolean integrityTest) throws SaveException { |
- | 153 | if (integrityTest) { |
|
- | 154 | if (!integryTest()) { |
|
- | 155 | throw new SaveException( |
|
- | 156 | "Integrity test failed. Will not save."); |
|
- | 157 | } |
|
- | 158 | } |
|
- | 159 | ||
- | 160 | String timestamp = DateUtils.now("EEE, d MMM yyyy HH:mm:ss Z"); |
|
- | 161 | String timestamp_filename = DateUtils.now("dd-MM-yyyy_HH-mm-ss"); |
|
- | 162 | ||
- | 163 | try { |
|
93 | BufferedWriter f = new BufferedWriter(new FileWriter(filename)); |
164 | BufferedWriter f = new BufferedWriter(new FileWriter(filename)); |
94 | 165 | ||
- | 166 | try { |
|
95 | f.write(SIGNATURE + "\r\n"); |
167 | f.write(SIGNATURE + "\r\n"); |
- | 168 | ||
- | 169 | f.write(SIGNATURE_MINOR + "\r\n"); |
|
- | 170 | f.write("\r\n"); |
|
- | 171 | ||
- | 172 | f.write("(Starting time)\r\n"); |
|
- | 173 | f.write(creation_time + "\r\n"); |
|
- | 174 | f.write("\r\n"); |
|
- | 175 | ||
- | 176 | f.write("(Save timestamp)\r\n"); |
|
- | 177 | f.write(timestamp + "\r\n"); |
|
96 | f.write("\r\n"); |
178 | f.write("\r\n"); |
97 | 179 | ||
98 | f.write("(u)\r\n"); |
180 | f.write("(u)\r\n"); |
99 | f.write(u + "\r\n"); |
181 | f.write(u + "\r\n"); |
100 | f.write("\r\n"); |
182 | f.write("\r\n"); |
101 | 183 | ||
102 | f.write("(r)\r\n"); |
184 | f.write("(r)\r\n"); |
103 | f.write(r + "\r\n"); // TODO: Softbreak |
185 | f.write(r + "\r\n"); // FUTURE: (1) Multi-Line-Support? |
104 | f.write("\r\n"); |
186 | f.write("\r\n"); |
105 | 187 | ||
106 | f.write("(M5rev)\r\n"); |
188 | f.write("(M5rev)\r\n"); |
107 | - | ||
108 | int i = 0; |
189 | int i = 0; |
109 | for (Integer xa : a) { |
190 | for (Integer xa : a) { |
110 | f.write(xa.toString()); |
191 | f.write(xa.toString()); |
111 | if (++i % SOFTBREAK == 0) { |
192 | if (++i % SOFTBREAK == 0) { |
112 | f.write("\r\n"); |
193 | f.write("\r\n"); |
113 | } |
194 | } |
114 | } |
195 | } |
115 | - | ||
116 | if (++i % SOFTBREAK != 0) { |
196 | if (++i % SOFTBREAK != 0) { |
117 | f.write("\r\n"); |
197 | f.write("\r\n"); |
118 | } |
198 | } |
- | 199 | f.write("\r\n"); |
|
119 | 200 | ||
- | 201 | f.write(END_SIG); |
|
- | 202 | } finally { |
|
120 | f.close(); |
203 | f.close(); |
121 | } |
204 | } |
- | 205 | } catch (IOException e) { |
|
- | 206 | throw new SaveException("Could not save master file.", e); |
|
- | 207 | } |
|
- | 208 | ||
- | 209 | // Make backup |
|
- | 210 | ||
- | 211 | new File(backupDir).mkdir(); |
|
- | 212 | String bak_filename = backupDir + "/immortal_" + timestamp_filename + "_" + (u+1) |
|
- | 213 | + ".txt"; |
|
- | 214 | try { |
|
- | 215 | FileUtils.copyFile(new File(filename), new File(bak_filename)); |
|
- | 216 | } catch (IOException e) { |
|
- | 217 | throw new SaveException("Could not make backup", e); |
|
- | 218 | } |
|
- | 219 | } |
|
122 | 220 | ||
123 | public void calcIterate(int amount) throws IOException { |
221 | public void calcIterate(int amount) throws SaveException { |
124 | int s, m, k; |
222 | int s, m, k; |
125 | int cnt = 0; |
223 | int cnt = 0; |
126 | 224 | ||
- | 225 | // Wir führen beim ersten Speichern einen weiteren |
|
- | 226 | // integrity-Test durch. Grund: Wäre bei einer Fortsetzung einer |
|
- | 227 | // Datei das "r" falsch (der Datenteil aber korrekt), dann würde |
|
- | 228 | // diese Datei beim Speichern ungültige Daten enthalten (Zahl |
|
- | 229 | // nicht immortabel). |
|
- | 230 | boolean firstSave = true; |
|
- | 231 | ||
127 | if (a.size() < 2) { |
232 | if (a == null) { |
- | 233 | creation_time = DateUtils.now("EEE, d MMM yyyy HH:mm:ss Z"); |
|
- | 234 | a = new Vector<Integer>(); |
|
128 | a.add(5); |
235 | a.add(5); |
129 | a.add(2); |
236 | a.add(2); |
130 | u = 1; |
237 | u = 1; |
131 | r = 2; |
238 | r = 2; |
132 | cnt += 2; |
239 | cnt += 2; |
133 | } |
240 | } |
134 | 241 | ||
135 | while (true) { |
242 | do { |
136 | r = (r - a.elementAt(u)) / 10 + a.elementAt(u); |
243 | r = (r - a.elementAt(u)) / 10 + a.elementAt(u); |
137 | s = 0; |
244 | s = 0; |
138 | for (m = 1, k = u; m < k; m++, k--) { |
245 | for (m = 1, k = u; m < k; m++, k--) { |
139 | s += a.elementAt(m) * a.elementAt(k); |
246 | s += a.elementAt(m) * a.elementAt(k); |
140 | } |
247 | } |
Line 144... | Line 251... | ||
144 | } |
251 | } |
145 | u++; |
252 | u++; |
146 | a.add(r % 10); |
253 | a.add(r % 10); |
147 | 254 | ||
148 | if (cnt % saveInterval == 0) { |
255 | if (cnt % saveInterval == 0) { |
149 | save(); |
256 | save(firstSave); |
- | 257 | firstSave = false; |
|
150 | } |
258 | } |
- | 259 | } while (++cnt != amount); |
|
151 | 260 | ||
- | 261 | // Wir brauchen nicht zwei Mal zu speichern |
|
152 | if (++cnt == amount) { |
262 | if (cnt-1 % saveInterval != 0) { |
153 | save(); |
263 | save(firstSave); |
154 | break; |
264 | firstSave = false; |
155 | } |
265 | } |
156 | } |
266 | } |
- | 267 | ||
- | 268 | public int getDigit(int u) { |
|
- | 269 | return a.elementAt(u); |
|
157 | } |
270 | } |
158 | 271 | ||
- | 272 | public StringBuilder M5_StringBuilder(int u) { |
|
- | 273 | StringBuilder s = new StringBuilder(); |
|
- | 274 | for (Integer xa : a) { |
|
- | 275 | s.append(xa); |
|
- | 276 | } |
|
- | 277 | s.reverse(); |
|
- | 278 | return s; |
|
- | 279 | } |
|
- | 280 | ||
- | 281 | public String M5_String(int u) { |
|
- | 282 | return M5_StringBuilder(u).toString(); |
|
- | 283 | } |
|
- | 284 | ||
- | 285 | public BigInteger M5_BigInteger(int u) { |
|
- | 286 | return new BigInteger(M5_String(u)); |
|
- | 287 | } |
|
- | 288 | ||
- | 289 | public StringBuilder M6_StringBuilder(int u) { |
|
- | 290 | StringBuilder s = new StringBuilder(); |
|
- | 291 | boolean first = true; |
|
- | 292 | for (Integer xa : a) { |
|
- | 293 | if (first) { |
|
- | 294 | s.append(6); // xa = 5 |
|
- | 295 | first = false; |
|
- | 296 | } else { |
|
- | 297 | s.append(9 - xa); |
|
- | 298 | } |
|
- | 299 | } |
|
- | 300 | s.reverse(); |
|
- | 301 | return s; |
|
- | 302 | } |
|
- | 303 | ||
- | 304 | public String M6_String(int u) { |
|
- | 305 | return M6_StringBuilder(u).toString(); |
|
- | 306 | } |
|
- | 307 | ||
- | 308 | public BigInteger M6_BigInteger(int u) { |
|
- | 309 | return new BigInteger(M6_String(u)); |
|
- | 310 | } |
|
- | 311 | ||
- | 312 | private static boolean isImmortable(BigInteger num) { |
|
- | 313 | // Ist das auch OK? |
|
- | 314 | // return num.pow(2).toString().endsWith(num.toString()); |
|
- | 315 | ||
- | 316 | // n² === n (mod 10^m) <===> n²%10^m == n%10^m |
|
- | 317 | int m = num.toString().length(); |
|
- | 318 | BigInteger m_pow = BigInteger.TEN.pow(m); |
|
- | 319 | return num.pow(2).mod(m_pow).equals(num.mod(m_pow)); |
|
- | 320 | ||
- | 321 | } |
|
- | 322 | ||
- | 323 | public boolean integryTest() { |
|
- | 324 | // return isImmortable(M5_BigInteger(u)); |
|
- | 325 | return isImmortable(M6_BigInteger(u)); |
|
- | 326 | } |
|
159 | } |
327 | } |