001: package de.anifun3.ctpuzzle;
002:
003: import javax.vecmath.*;
004: import java.util.Vector;
005: import java.text.DecimalFormat;
006: import java.io.*;
007: import javax.media.j3d.Transform3D;
008:
009:
010:
011:
012:
013:
014: public class Puzzle implements Runnable
015: {
016:
017: private Thread ivPaintThread = null;
018:
019:
020: private boolean ivStopped = false;
021:
022:
023: private long ivCombCount = 0;
024:
025:
026: private long ivStartTime = 0;
027:
028:
029: private Part[] ivParts = null;
030:
031:
032: private long ivField = 0;
033: private int[][][] ivPrintField = null;
034: public static int[] ivSearchOrder = null;
035:
036:
037: private long ivSolvedField = 0;
038:
039:
040: private Transform3D[][] ivSolutions = null;
041: private int ivSolvCount = 0;
042: private int ivMasterSolv = 0;
043:
044:
045: private long ivCMasterPos = 0;
046: private long ivTMasterPos = 0;
047: private long ivAMasterPos = 0;
048:
049:
050:
051:
052: private boolean ivIsSilent = false;
053:
054: private boolean ivModal = true;
055:
056:
057: private DecimalFormat ivFieldFormat = null;
058: private DecimalFormat ivCombFormat = null;
059:
060:
061: public static final int X = 5;
062: public static final int Y = 3;
063: public static final int Z = 4;
064: public static final int NUM_PARTS = 12;
065: public static final int MAX_FIELDS = X*Y*Z;
066:
067:
068: private int ivpI = 0;
069:
070:
071:
072: public Puzzle()
073: {
074: this( false, true );
075: }
076:
077:
078:
079: public Puzzle( boolean silent, boolean modal )
080: {
081: super();
082: ivIsSilent = silent;
083: ivModal = modal;
084:
085:
086: ivParts = new Part[NUM_PARTS];
087: ivField = 0;
088: ivPrintField = new int[X][Y][Z];
089: ivSolutions = new Transform3D[409963][ivParts.length];
090: ivSearchOrder = new int[MAX_FIELDS+1];
091:
092:
093: ivSolvedField = 0;
094: for( int i=0; i<(X*Y*Z); i++)
095: ivSolvedField |= (long)1 << i;
096:
097:
098:
099: ivFieldFormat = new java.text.DecimalFormat();
100: ivFieldFormat.setMinimumIntegerDigits(2);
101: ivFieldFormat.setMinimumFractionDigits(0);
102:
103:
104:
105: ivCombFormat = new java.text.DecimalFormat();
106: ivCombFormat.setGroupingUsed(true);
107: ivCombFormat.setMinimumFractionDigits(0);
108:
109:
110: initParts();
111: }
112:
113:
114:
115:
116:
117: public long getComboCount()
118: {
119: return ivCombCount;
120: }
121:
122:
123:
124:
125:
126: public int getMasterSolution()
127: {
128: return ivMasterSolv;
129: }
130:
131:
132:
133:
134:
135: public Part[] getParts()
136: {
137: return ivParts;
138: }
139:
140:
141:
142:
143:
144:
145: public Transform3D[] getSolution(int index)
146: {
147: if( index < ivSolvCount && index >= 0)
148: return ivSolutions[index];
149: return null;
150: }
151:
152:
153:
154:
155:
156: public int getSolutionsCount()
157: {
158: return ivSolvCount;
159: }
160:
161:
162:
163:
164:
165: public long getTime()
166: {
167: return System.currentTimeMillis() - ivStartTime;
168: }
169:
170:
171:
172:
173:
174: public String getTimeString()
175: {
176: long dur = getTime();
177: int hour = (int)dur / 3600000;
178: dur = dur - 3600000*hour;
179: int min = (int)dur / (60000);
180: dur = dur - (60000*min);
181: int sec = (int)dur / 1000;
182:
183: return ivFieldFormat.format(hour) + ":" + ivFieldFormat.format(min) + ":" + ivFieldFormat.format(sec);
184: }
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195: private void initParts()
196: {
197:
198:
199: int field = 0;
200:
201: for( int x=0; x<X; x++ )
202: for( int z=Z-1; z>=0; z--)
203: for( int y=0; y<Y; y++ )
204: ivSearchOrder[field++] = x + z*Puzzle.X + y*Puzzle.X*Puzzle.Z;
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221: ivParts[0] = new Part( new int[]{ 1,2,21,41,42 } );
222: ivParts[1] = new Part( new int[]{ 1,2,22,42,43 } );
223: ivParts[2] = new Part( new int[]{ 16,17,12,7,2 } );
224: ivParts[3] = new Part( new int[]{ 16,11,06,07,1 } );
225: ivParts[4] = new Part( new int[]{ 1,6,21,26,7 } );
226: ivParts[5] = new Part( new int[]{ 1,2,3,7,12 } );
227: ivParts[6] = new Part( new int[]{ 2,6,7,11,12 }, true );
228: ivParts[7] = new Part( new int[]{ 11,12,7,8,3 } );
229: ivParts[8] = new Part( new int[]{ 21,26,27,7 });
230: ivParts[9] = new Part( new int[]{ 2,7,8,12,11 } );
231: ivParts[10] = new Part( new int[]{ 2,6,7,8,12 } );
232: ivParts[11] = new Part( new int[]{ 16,17,11,6,7,1 } );
233:
234:
235: long v = 1;
236: ivCMasterPos = v<<55 | v<<56 | v<<50 | v<<45 | v<<46;
237: ivTMasterPos = v<<58 | v<<59 | v<<53 | v<<48 | v<<43 | v<<49;
238: ivAMasterPos = v<<42 | v<<47 | v<<22 | v<<27 | v<<28;
239: }
240:
241:
242:
243:
244: public void printField()
245: {
246: for( int y=Y-1; y>=0; y--)
247: {
248: for( int z=0; z<Z; z++)
249: {
250: for( int w = 0; w<Z-z; w++ ) System.out.print(" ");
251:
252: for( int x=0; x<X; x++)
253: {
254: if (ivPrintField[x][y][z] == -1 )
255: System.out.print( "xx " );
256: else
257: System.out.print( ivFieldFormat.format( ivPrintField[x][y][z] +1 ) + " " );
258: }
259: System.out.println(" ");
260: }
261: System.out.println(" ");
262: }
263:
264: String mastersolv = (ivMasterSolv >0 ) ? ""+ivMasterSolv : "-";
265: System.out.println("Combos : " + ivCombFormat.format(ivCombCount));
266: System.out.println("Solutions: " + ivSolvCount + " ("+ mastersolv +")");
267: System.out.println("Time : " + getTimeString());
268: System.out.println("Solv/sec : " + ivSolvCount/(getTime()/1000) );
269: System.out.println("Comb/sec : " + ivCombFormat.format(ivCombCount/(getTime()/1000)));
270: System.out.println("---");
271: }
272:
273:
274:
275:
276: public void reset()
277: {
278: int i;
279:
280:
281: ivField = 0;
282:
283:
284: for( i=0; i<ivParts.length; i++)
285: ivParts[i].setIsUsed(false);
286:
287:
288: for( int x=0; x<ivPrintField.length; x++)
289: for( int y=0; y<ivPrintField[x].length; y++)
290: for( int z=0; z<ivPrintField[x][y].length; z++)
291: ivPrintField[x][y][z] = -1;
292:
293:
294: ivSolvCount = 0;
295: ivMasterSolv = 0;
296:
297:
298: ivCombCount = 0;
299: }
300:
301:
302:
303:
304: public void run()
305: {
306: while ( !ivStopped )
307: {
308: synchronized (ivPaintThread)
309: {
310: try
311: {
312:
313: ivPaintThread.wait(10000);
314: }
315: catch( InterruptedException e )
316: {
317: e.printStackTrace();
318: }
319:
320:
321: printField();
322: }
323: }
324: }
325:
326:
327:
328:
329: public void saveResult()
330: {
331: try
332: {
333: Matrix3f m = new Matrix3f();
334: DataOutputStream out = new DataOutputStream(
335: new BufferedOutputStream(
336: new FileOutputStream(new File("ctpuzzle.dat"))) );
337:
338: for( int i=0; i<ivSolvCount; i++)
339: {
340: for( int y=0; y<ivSolutions[0].length; y++ )
341: {
342: ivSolutions[i][y].get(m);
343: out.writeFloat( m.m00 );
344: out.writeFloat( m.m01 );
345: out.writeFloat( m.m02 );
346: out.writeFloat( m.m10 );
347: out.writeFloat( m.m11 );
348: out.writeFloat( m.m12 );
349: out.writeFloat( m.m20 );
350: out.writeFloat( m.m21 );
351: out.writeFloat( m.m22 );
352: }
353: }
354: out.flush();
355: out.close();
356: }
357: catch( Exception e)
358: {
359: e.printStackTrace();
360: }
361: }
362:
363:
364:
365:
366: public void solve()
367: {
368:
369:
370:
371:
372: reset();
373:
374:
375: ivStartTime = System.currentTimeMillis();
376:
377:
378: if( !ivIsSilent )
379: {
380: ivStopped = false;
381: ivPaintThread = new Thread( this, "PuzzlePainter");
382: ivPaintThread.setPriority( Thread.currentThread().getPriority() );
383: ivPaintThread.start();
384: }
385:
386:
387: solve(0);
388:
389:
390: ivStopped = true;
391:
392:
393: System.out.println("SOLUTIONS TOTAL: " + ivSolvCount);
394: }
395:
396:
397:
398:
399:
400: private void solve(int field)
401: {
402:
403:
404:
405:
406:
407:
408:
409:
410: if( ivField == ivSolvedField)
411: {
412: for( int i=0; i<ivParts.length; i++)
413: {
414:
415: if( ivSolvCount<ivSolutions.length)
416: ivSolutions[ivSolvCount][i] = ivParts[i].ivUnit.transform;
417:
418:
419: if( !ivIsSilent )
420: for( int y=0; y<ivParts[i].ivUnit.geometry.length; y++)
421: ivPrintField [ivParts[i].ivUnit.geometry[y].x]
422: [ivParts[i].ivUnit.geometry[y].y]
423: [ivParts[i].ivUnit.geometry[y].z] = (byte)i;
424: }
425:
426:
427: if( ivParts[0].ivUnit.fields == ivCMasterPos
428: && ivParts[ivParts.length-1].ivUnit.fields == ivTMasterPos
429: && ivParts[4].ivUnit.fields == ivAMasterPos
430: )
431: ivMasterSolv = ivSolvCount;
432:
433: ivSolvCount++;
434: return;
435: }
436:
437: long fieldBits = (long)1<<ivSearchOrder[field];
438:
439:
440: if( ((fieldBits) & ivField) != 0)
441: {
442:
443: solve( field+1 );
444: return;
445: }
446:
447: Projections.Unit[] units;
448: Projections.Unit unit;
449: Part part;
450:
451:
452:
453: for( int i=0; i<ivParts.length; i++)
454: {
455: part = ivParts[i];
456: if( !part.ivIsUsed )
457: {
458:
459:
460: units = part.ivProjections.ivMovedProjections[field];
461: for( int w=0; w<units.length; w++)
462: {
463: unit = units[w];
464:
465:
466: if( ((ivField & unit.fields) == 0) )
467: {
468:
469:
470: ivField |= unit.fields;
471: part.ivIsUsed = true;
472: part.ivUnit = unit;
473: ivCombCount++;
474:
475:
476:
477:
478:
479: solve(field+1);
480:
481:
482:
483: ivField = ivField ^ unit.fields;
484: part.ivIsUsed = false;
485:
486: }
487: }
488: }
489: }
490: }
491: }