15 puzzle solver: Difference between revisions

(→‎{{header|Fortran}}: Add content,)
Line 242:
===The Plan===
===The Code===
The source code started off as a mainline only, but then as facilities were added and service routines became helpful. This prompted the use of F90's MODULE facility so that the PARAMETER statement could be used to describe the shape of the board with this available to each routine without the need for passing the values as parameters or messing with COMMON storage, or repeating the PARAMETER statement in each routine. Otherwise, literal constants such as 4 would appear in various places. These appearances could now be documented by using the appropriate name such as <code>NR</code> and <code>NC</code> rather than just <code>4</code> and similar. However, inside FORMAT statements the use of <NR - 1> (and not <NC - 1>) rather than 3 will succeed only if the compiler accepts this usage, and not all do. More complex calculations involving the board size have not been attempted. The PARAMETER facility is useful only for simple calculations. Considerations such as a 4x4 board having 16 squares is easy, but the consequences of this count fitting into a four-bit binary field are not, thus the equivalences involving <code>BOARD, BORED and <BOAR</code> are not general for different board shapes, nor are the column headings adjustable. Similarly, subroutine UNPACK does not attempt to use a loop but employs explicit code.
<lang Fortran>
 
SUBROUTINE PROUST(T) !Remembrance of time passed.
This approach is followed in the calculation of the hash code, by writing out the product rather than using the compilers built-in <code>PRODUCT</code> and a startling difference results:
<pre>
59: H = MOD(ABS(PRODUCT(BRD)),APRIME)
004016E3 mov esi,1
004016E8 mov ecx,1
004016ED cmp ecx,2
004016F0 jg MAIN$SLIDESOLVE+490h (0040171e)
004016F2 cmp ecx,1
004016F5 jl MAIN$SLIDESOLVE+46Eh (004016fc)
004016F7 cmp ecx,2
004016FA jle MAIN$SLIDESOLVE+477h (00401705)
004016FC xor eax,eax
004016FE mov dword ptr [ebp-54h],eax
00401701 dec eax
00401702 bound eax,qword ptr [ebp-54h]
00401705 imul edx,ecx,4
00401708 mov edx,dword ptr H (00473714)[edx]
0040170E imul edx,esi
00401711 mov esi,edx
00401713 mov eax,ecx
00401715 add eax,1
0040171A mov ecx,eax
0040171C jmp MAIN$SLIDESOLVE+45Fh (004016ed)
0040171E mov eax,esi
00401720 cmp eax,0
00401725 jge MAIN$SLIDESOLVE+49Bh (00401729)
00401727 neg eax
00401729 mov edx,10549h
0040172E mov dword ptr [ebp-54h],edx
00401731 cdq
00401732 idiv eax,dword ptr [ebp-54h]
00401735 mov eax,edx
00401737 mov dword ptr [H (00473714)],eax
60: write (6,*) H,bored
</pre>
Whereas by writing out the product,
<pre>
59: H = MOD(ABS(BRD(1)*BRD(2)),APRIME)
004016E3 mov eax,dword ptr [BRD (00473718)]
004016E9 imul eax,dword ptr [BRD+4 (0047371c)]
004016F0 cmp eax,0
004016F5 jge MAIN$SLIDESOLVE+46Bh (004016f9)
004016F7 neg eax
004016F9 mov esi,10549h
004016FE cdq
004016FF idiv eax,esi
00401701 mov eax,edx
00401703 mov dword ptr [H (00473714)],eax
60: write (6,*) H,bored
</pre>
Granted a flexible pre-processor scheme (as in pl/i, say) one could imagine a menu of tricks being selected from according to the board shape specified, but without such a facility, the constants are merely named rather than literal.
<lang Fortran> SUBROUTINE PROUST(T) !Remembrance of time passed.
DOUBLE PRECISION T !The time, in seconds. Positive only, please.
DOUBLE PRECISION S !A copy I can mess with.
Line 774 ⟶ 826:
read (kbd,*,err=999) i
END</lang>
 
===The Results===
<pre>
1,220

edits