Programm von Jens Kunerle (Snej)
e-Mail: 03342300948@t-online.de
Dateien: LiesMich.txt
         puzz.cpp
         puzz.exe
	 p1.asm


Das Programm besteht aus einem Mix von c++ (Initialisierung) und asm (Rekursion)
und braucht auf einem PIII-450: <1200 Sekunden
Compiler von Borland C++5, tasmx-Compiler , tlink32-Linker
c-Compiler Optionen: ???
tasmx Optionen: -ml -m3
tlink32 Optionen: tlink32 /v /c /S:A000000 /Lc:\bc5\lib;c:\bc5\include 
          \bc5\lib\c0x32 px puzz,puzz,puzz,cw32 import32
(die Groesse des Stacks ist wichtig)

Brute-Force Bitfuellmethode:
Das Symmetrieteil ist das aus 5 Bit bestehende raeumliche Teil.
Die Permutation ist so gewaehlt das zuerst 2 Schichten des 3x4x5 Quaders gefuellt werden,
dann eine Schicht des 3x3x4 Quaders und zum Schluss der 3x3x3 Wuerfel immer von der 
schmalsten Seite her.

Das Programm:

I Initialisierung

Global Init:
 1.Permutation (permutierte Bits im 64Bit Bereich - 0..59 bzw. 4..63)
   NBit PBit RBit (BitPerm,RevPerm und BitHPerm sind Hilfen bei der Initialisierung)
 2.Nachbar wird in Rekursion verwendet 
   BSF liefert dort Bitindex i (0..63)
   Nachbar[i] liefert zugehoerige Nachbarn je nach Permutation
Teile einzeln initialisieren
 1.bool Variablen als gesetzte Bits in einem 4x4x4 Quader interpretieren je nach 
   Initialisierungsquader
 2.InitAnsicht dreht den Quader so,dass jede Seite mal oben liegt
   InitAnsichtSub dreht pro obenliegende Seite den Quader um die z-Achse bis jede
     der vier moeglichen Seiten mal vorn war 
   Die Ergebnisse der Drehungen werden in Ansicht gespeichert (->24 Ansichten/Teil)
     und zwar so, das das Teil soweit wie moeglich links,vorn,unten liegt
   durch Vergleiche der 24 Ansichten werden doppelte geloescht
 3.Symhack1 loescht symmetrische Lagen des Symmetrieteils bzgl. Rotation 
   um x-,y- und z-Achse (1/4 der Lagen bleiben uebrig)
Quaderteile einzeln initialisieren
 1.Teile werden auf alle moeglichen Positionen im Quader verschoben und als 
   permutiertes Quaderteil gespeichert
 2.Nach Symhack2 werden alle Positionen global gespeichert in Lage2
 3.Symhack2 besteht aus drei Teilen:
   a) zum Symmetrieteil werden wieder alle vier symmetrischen Lagen erzeugt und die
      Lage mit kleinstem gesetzten "ersten" Bit bzgl. der Permutation wird genommen
      -> wegen symTeil='A' und verwendeter Permutation liegt 'A' im hintersten 
         3x3x3 Wuerfel
   b) Es wird sichergestellt, das zu jeder Ansicht von 'A' auch die an der yz-Ebene
      gespiegelte Ansicht vorhanden ist. Dabei wird (wenn moeglich) das weiter hinten 
      liegende Paar genommen.[Verschlechterung gegenueber a)]
      -> Jetzt darf man zu jeder beliebigen Ansicht von 'B' entscheiden, ob man diese
         oder die an der yz-Ebene gespiegelte verwendet. 
      Gibt es eine gespiegelte Loesung, so auch eine normale, die man wiederum durch
      Spiegelung an der yz-Ebene erhaelt. Gespiegelt 'B' geht wieder in 'B' ueber und
      alle anderen Teile in andere Lagen von sich selbst. Denn alle Teile bis auf 'B'
      koennen so gedreht werden, das sie gespiegelt erscheinen.
      Damit das auch bei 'A' der Fall ist, (weil ja einige Ansichten von 'A' im Quader
      gestrichen wurden) ist Schritt b) notwendig.  
   c) Es wird die weiter hinten liegende Ansicht von 'B' oder Gespiegelt'B' genommen.
      [Verbesserung gegenueber a)]

   Leider bringen b) und c) nur 3% Geschwindigkeitszuwachs :(( 

Puzzle initialisieren (globale Variablen fuer die Rekursion)
 1.Deadend1/2 (Verweis)
   zu jedem Teil werden das NachbarBit und die Nachbarn des NachbarBits (ohne Teil)
   gespeichert um spaeter zu erkennen ob durch ein Teil ein NachbarBit vollkommen
   zugebaut wird.
   fuer ein Teil gilt:
   DeadEnd2[Teil][0] enthaelt Nachbarn fuer bsf , n , 0
   DeadEnd2[Teil][i] enthaelt Bit i , Nachbarn von Bit i ohne Bits von Teil
      wobei i Nachbarbit von Teil ist
 2.Kette1/Offset (Verweis) siehe auch im Programm
   ueber Verweis wird Deadend gelinkt
   ueber nb und benutzt wird mittels Offset der entsprechende Teil in Kette 1 gefunden
   die Header enthalten Bereiche fuer die zu testenden Teile die danach folgen
   ein zu testendes Teil besteht aus Teil, v (Verweis) , n

II Rekursion

1.Das erste freie Bit (nb) wird ueber bsf gesucht
2.wenn keins gefunden wurde gibt es eine loesung mehr
3.Je nachdem welche der drei Richtungen ab nb noch frei sind werden die zu testenden
  Teile ausgesucht und getestet
4.rekursiver aufruf

// nicht mehr implementiert:
4.war ein Test erfolgreich wird untersucht ob evtl. ein Bit zugebaut wird
  ist dem nicht so wird die Funktion rekursiv aufgerufen
5.ab Bit 33 wird getestet ob die langen Teile schon verbaut wurden
6.ab Bit 28 werden 32Bit Routinen benutzt
Aufrufreihenfolge: solve,_solve1,solve64,solve32a,solve32b

Ende 