1
0
mirror of https://github.com/retro-software/B5500-software.git synced 2026-01-11 23:42:42 +00:00
Paul Kimpel e24ebe2110 Commit new Sudoku solver program and RC documentation update.
1. Commit Sudoku solver program from Paul Cumberworth.
2. Replace RC reference document with version generated from CUBE13
library files
2019-03-24 14:14:06 -07:00

405 lines
15 KiB
Plaintext

?COMPILE SUDOKU/TEST WITH XALGOL GO
?XALGOL FILE LINE = LINE/SUDOKU PRINT BACK UP DISK
?STACK = 5000
?DATA CARD
%CARD STACK SEG PRT LIST SINGLE DEBUGN
$LIST PRT STACK SINGLE
% SUDOKU SOLVER
% ORIGINALLY WRITTEN IN C BY SCOTT HEMPHILL AND PLACED IN
% THE PUBLIC DOMAIN 5 SEPTEMBER 2005
% CONVERTED TO B5500 BY PAUL C JULY 2018
% MAKE SURE STACK SET TO AT LEAST 5000 WORDS TO COPE WITH RECURSION
BEGIN
BOOLEAN
FINDMULTIPLE; % FIND MULTIPLE SOLUTIONS (SET COMMON = 1 IN CC)
INTEGER
NUM, % COUNT OF NUMBER OF SOLUTIONS FOUND
CURDEPTH, % CURRENT RECURSION DEPTH
MAXDEPTH, % MAXIMUM RECURSION DEPTH
STARTET; % TIME(1) OF WHEN WE STARTED
INTEGER ARRAY
BITNO[0:11], % ALLOW FOR 12 BITS, ONLY USE 9 THOUGH
GRID [0:80], % THE PUZZLE GRID: 1 THRU 9, OR 0 IF NO NUMBER YET
BITS [0:80], % BITMAP OF EACH SQUARE: BIT SET => NOT POSSIBLE
% I.E. 3"001" => !1, 3"002" => !2, 3"004" => !3,
% 3"010" => !4, ... 3"400" => !9.
COUNT [0:511], % BIT COUNT FOR EACH NUMBER
OTHERSARY [0:80, 0:19];
DEFINE OTHERS(X,Y) =
OTHERSARY[X,Y] #; % MAKE IT EASIER TO OPTIMISE LATER
% FOR EACH SQUARE, AN ARRAY OF 20 "OTHER"
% LOCATIONS AFFECT BY THIS SQUARE. FOR
% EXAMPLE, IF THERE IS A "6" IN SQUARE 0,
% THERE ARE 20 OTHER SQUARES WE KNOW
% CANT CONTAIN A SIX:
% 1,2,3,4,5,6,7,8 (HORIZONTAL ROW)
% 9,18,27,36,45,54,63,72 (VERTCAL COLUMN)
% 1,2,9,10,11,18,19,20 (3X3 SQUARE)
% THATS A TOTAL OF 24 SQUARE NUMBERS,
% BUT 4 OF THEM ARE DUPLICATES. THE
% "OTHERS" ARRAY IS BIG ENOUGH TO HOLD
% 24 NUMBERS WHILE IT IS BEING BUILT, BUT
% WILL ONLY 20 NUMBERS WILL BE USED WHEN
% IT IS COMPLETE.
FILE CARD (2,10,150);
FILE SPO 11 (1,10);
FILE LINE 15 (1,15); % 15, 17 IS PRINTER BACKUP DISK
INTEGER PROCEDURE ONES32(I); % FROM HACKERS DELIGHT
%---------------------------
VALUE I; INTEGER I;
BEGIN
I:= I - REAL(BOOLEAN(I.[31:31]) AND BOOLEAN(3"12525252525"));
I:= REAL(BOOLEAN(I.[31:30]) AND BOOLEAN(3"6314631463")) +
REAL(BOOLEAN(I) AND BOOLEAN(3"6314631463"));
I:= REAL(BOOLEAN(I.[31:28] + I) AND BOOLEAN(3"1703607417"));
I:= I + I.[31:24];
I:= I + I.[31:16];
ONES32:= REAL(BOOLEAN(I) AND BOOLEAN(3"77"));
END;
PROCEDURE SETBOX(N, X, BIT);
%---------------------------
VALUE N, X, BIT; INTEGER N, X, BIT;
% "SETBOX" IS USED TO PLACE A NUMBER IN THE GRID, WHETHER IT IS KNOWN,
% OR A GUESS. IT ALSO UPDATES ALL THE BITMASKS FOR ALL THE ASSOCIATED
% SQUARES TO INDICATE THAT THEY CANT CONTAIN THIS NUMBER.
BEGIN
INTEGER I;
GRID[N]:= X;
FOR I:= 0 STEP 1 UNTIL 19 DO
BITS[OTHERS(N,I)]:= REAL(BOOLEAN(BITS[OTHERS(N,I)]) OR
BOOLEAN(BIT));
END;
PROCEDURE READGRID;
%------------------
% READ IN INITIAL DATA
% THE INITIAL BITMASK IS CALCULATED AT THE SAME TIME BY CALLING SETBOX
BEGIN
INTEGER I, J;
ALPHA ARRAY AIN[0:2];
POINTER P;
FOR I:= 0 STEP 1 UNTIL 8 DO % 9 ROWS OF 9 NUMBERS
BEGIN
READ(CARD, 3, AIN[*]);
P:= POINTER(AIN[0]);
FOR J:= 0 STEP 1 UNTIL 8 DO
BEGIN
SETBOX(9 | I + J, INTEGER(P,1),
BITNO[INTEGER(P,1)]); % SET BITNO, LSB=BIT0
P:= P + 1;
END;
END;
%WRITE OUT WHAT WE GOT!
WRITE(LINE, <"WE STORED IN GRID:">);
FOR I:= 0 STEP 1 UNTIL 8 DO
WRITE(LINE, <9I1>, FOR J:= 0 STEP 1 UNTIL 8 DO GRID[9|I+J]);
%CHECK FOR CONSISTENCY
FOR I:= 0 STEP 1 UNTIL 80 DO
IF GRID[I] > 0 THEN
IF REAL(BOOLEAN(BITS[I]) AND BOOLEAN(BITNO[GRID[I]])) > 0 THEN
BEGIN
WRITE(LINE, <"INCONSISTENT DATA IN ",I1,",",I1>,
(I DIV 9)+1, (I MOD 9) + 1);
J:= 1/0;
END;
END;
PROCEDURE PRINTSOLUTION;
%-----------------------
BEGIN
INTEGER I, J;
NUM:= NUM + 1;
IF NUM > 1 THEN
WRITE(LINE, <" ">); % BLANK
WRITE(LINE,<"SOLUTION ",I3,":">, NUM);
FOR I:= 0 STEP 1 UNTIL 8 DO
WRITE(LINE, <9I1>, FOR J:= 0 STEP 1 UNTIL 8 DO GRID[9|I+J]);
END;
PROCEDURE SELECTBOX;
%-------------------
% "SELECTBOX" IS THE HEART OF THE ALGORITHM. IT WORKS THIS WAY:
% FIRST, THE GRID IS SEARCHED FOR AN EMPTY SQUARE. IF THERE ISNT ONE,
% THEN THE GRID CONTAINS A SOLUTION, SO IT IS PRINTED. IF AN EMPTY
% SQUARE IS FOUND, THEN IT IS COMPARED WITH ALL OTHER EMPTY SQUARES TO
% SEE WHICH ONE OF THEM HAS THE MAXIMUM NUMBER OF 1-BITS IN ITS BITMASK.
% THAT SQUARE IS THE ONE SELECTED, AND EACH OF THE POSSIBLE VALUES ARE
% TRIED IN RETURN, CALLING "SELECTBOX" RECURSIVELY TO SEARCH FOR A
% SOLUTION. NOTE THAT IF A SQUARE HAS 9 1-BITS IN ITS BITMASK, THEN
% THERE ARE NO POSSIBLE VALUES, AND "SELECTBOX" WILL RETURN WITHOUT ANY
% FURTHER RECURSION. OTHERWISE, IF A SQUARE HAS 8 1-BITS IN ITS BITMASK,
% THEN IT HAS A FORCED CHOICE, AND ONLY THAT CHOICE WILL BE TAKEN AT THIS
% LEVEL IN THE RECURSION.
BEGIN
INTEGER ARRAY
BITSAVE[0:80]; % SAVED ON EVERY RECURSION, MAX DEPTH 81|81 = 4131 WORDS?
INTEGER
I,
J,
BEST,
BESTCOUNT;
BOOLEAN
FINISHED;
LABEL XIT;
CURDEPTH:= CURDEPTH + 1;
MAXDEPTH:= MAX(MAXDEPTH, CURDEPTH);
% IF NUM = 0 THEN % RECURSE ONLY IF NO SOLUTIONS SO FAR
BEGIN
% FIND EMPTY SQUARE
BEST:= 0;
WHILE NOT FINISHED DO % PREFER TO HAVE CONDITIONAL AND :)
IF NOT FINISHED:= GRID[BEST] = 0 THEN
FINISHED:= (BEST:= BEST + 1) GTR 80;
IF BEST = 81 THEN % 81 INDICATES NO EMPTY SQUARES
BEGIN
PRINTSOLUTION;
GO TO XIT;
END;
BESTCOUNT:= COUNT[BITS[BEST]]; % BITS IN THE SQUARE WE FOUND
FOR I:= BEST+1 STEP 1 WHILE I LSS 81 DO
BEGIN % FIND THE BIGGEST COUNT OVER ALL SQUARES
IF GRID[I] = 0 THEN % ONLY CONSIDER EMPTY SQUARES
BEGIN
J:= COUNT[BITS[I]];
IF J > BESTCOUNT THEN
BEGIN
BEST:= I;
BESTCOUNT:= J;
END;
END;
END;
% TRY ALL NUMBERS FOR THIS SQUARE
FOR I:= 1 STEP 1 WHILE I LEQ 9 DO
BEGIN
IF REAL(BOOLEAN(BITS[BEST]) AND BOOLEAN(BITNO[I])) = 0 THEN
BEGIN % IF THE NUMBER IS POSSIBLE, RECURSE
% SAVE STATE ON STACK
REPLACE POINTER(BITSAVE) BY POINTER(BITS) FOR 81 WORDS;
SETBOX(BEST, I, BITNO[I]); % SET NUMBER AND FIX BITMASK
SELECTBOX; % RECURSE
GRID[BEST]:= 0; % UNPLACE NUMBER IN SQUARE
% RESTORE
REPLACE POINTER(BITS) BY POINTER(BITSAVE) FOR 81 WORDS;
END;
END;
END;
XIT:
CURDEPTH:= CURDEPTH - 1;
END;
PROCEDURE INITIALIZE;
%---------------------
% FILL THE COUNT AND OTHERS ARRAYS
BEGIN
DEFINE FO(I) = FILL OTHERSARY[I, *] WITH #; % MAKE IT EASIER TO WRITE!
INTEGER CNT;
% PREFILLED COUNT ARRAY: PT= 0.833 IO= 9.267 ET= 3.483
% CALCULATED COUNT ARRAY: PT= 1.150 IO= 8.850 ET= 3.517
FOR CNT:= 0 STEP 1 UNTIL 511 DO
COUNT[CNT]:= ONES32(CNT);
% BE NICE TO REDUCE PBITTING SOMEHOW, AND MAYBE MAKE FASTER ACCESS,
% WHICH IS BETTER INDEXED DESCRIPTOR OR MULTIPLY TO DETERMINE VALUE?
% CURRENT IMPLEMENTATION SLOWS THE COMPILER AS WELL!
% AS FILL CAN ONLY DO 1024 NUMBERS, CANNOT USE SINGLE DIMENSION ARRAY
% 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
FO( 0) 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,18,19,20,27,36,45,54,63,72; % 0
FO( 1) 0, 2, 3, 4, 5, 6, 7, 8, 9,10,11,18,19,20,28,37,46,55,64,73; % 1
FO( 2) 0, 1, 3, 4, 5, 6, 7, 8, 9,10,11,18,19,20,29,38,47,56,65,74; % 2
FO( 3) 0, 1, 2, 4, 5, 6, 7, 8,12,13,14,21,22,23,30,39,48,57,66,75; % 3
FO( 4) 0, 1, 2, 3, 5, 6, 7, 8,12,13,14,21,22,23,31,40,49,58,67,76; % 4
FO( 5) 0, 1, 2, 3, 4, 6, 7, 8,12,13,14,21,22,23,32,41,50,59,68,77; % 5
FO( 6) 0, 1, 2, 3, 4, 5, 7, 8,15,16,17,24,25,26,33,42,51,60,69,78; % 6
FO( 7) 0, 1, 2, 3, 4, 5, 6, 8,15,16,17,24,25,26,34,43,52,61,70,79; % 7
FO( 8) 0, 1, 2, 3, 4, 5, 6, 7,15,16,17,24,25,26,35,44,53,62,71,80; % 8
FO( 9) 0, 1, 2,10,11,12,13,14,15,16,17,18,19,20,27,36,45,54,63,72; % 9
FO(10) 0, 1, 2, 9,11,12,13,14,15,16,17,18,19,20,28,37,46,55,64,73; % 10
FO(11) 0, 1, 2, 9,10,12,13,14,15,16,17,18,19,20,29,38,47,56,65,74; % 11
FO(12) 3, 4, 5, 9,10,11,13,14,15,16,17,21,22,23,30,39,48,57,66,75; % 12
FO(13) 3, 4, 5, 9,10,11,12,14,15,16,17,21,22,23,31,40,49,58,67,76; % 13
FO(14) 3, 4, 5, 9,10,11,12,13,15,16,17,21,22,23,32,41,50,59,68,77; % 14
FO(15) 6, 7, 8, 9,10,11,12,13,14,16,17,24,25,26,33,42,51,60,69,78; % 15
FO(16) 6, 7, 8, 9,10,11,12,13,14,15,17,24,25,26,34,43,52,61,70,79; % 16
FO(17) 6, 7, 8, 9,10,11,12,13,14,15,16,24,25,26,35,44,53,62,71,80; % 17
FO(18) 0, 1, 2, 9,10,11,19,20,21,22,23,24,25,26,27,36,45,54,63,72; % 18
FO(19) 0, 1, 2, 9,10,11,18,20,21,22,23,24,25,26,28,37,46,55,64,73; % 19
FO(20) 0, 1, 2, 9,10,11,18,19,21,22,23,24,25,26,29,38,47,56,65,74; % 20
FO(21) 3, 4, 5,12,13,14,18,19,20,22,23,24,25,26,30,39,48,57,66,75; % 21
FO(22) 3, 4, 5,12,13,14,18,19,20,21,23,24,25,26,31,40,49,58,67,76; % 22
FO(23) 3, 4, 5,12,13,14,18,19,20,21,22,24,25,26,32,41,50,59,68,77; % 23
FO(24) 6, 7, 8,15,16,17,18,19,20,21,22,23,25,26,33,42,51,60,69,78; % 24
FO(25) 6, 7, 8,15,16,17,18,19,20,21,22,23,24,26,34,43,52,61,70,79; % 25
FO(26) 6, 7, 8,15,16,17,18,19,20,21,22,23,24,25,35,44,53,62,71,80; % 26
FO(27) 0, 9,18,28,29,30,31,32,33,34,35,36,37,38,45,46,47,54,63,72; % 27
FO(28) 1,10,19,27,29,30,31,32,33,34,35,36,37,38,45,46,47,55,64,73; % 28
FO(29) 2,11,20,27,28,30,31,32,33,34,35,36,37,38,45,46,47,56,65,74; % 29
FO(30) 3,12,21,27,28,29,31,32,33,34,35,39,40,41,48,49,50,57,66,75; % 30
FO(31) 4,13,22,27,28,29,30,32,33,34,35,39,40,41,48,49,50,58,67,76; % 31
FO(32) 5,14,23,27,28,29,30,31,33,34,35,39,40,41,48,49,50,59,68,77; % 32
FO(33) 6,15,24,27,28,29,30,31,32,34,35,42,43,44,51,52,53,60,69,78; % 33
FO(34) 7,16,25,27,28,29,30,31,32,33,35,42,43,44,51,52,53,61,70,79; % 34
FO(35) 8,17,26,27,28,29,30,31,32,33,34,42,43,44,51,52,53,62,71,80; % 35
FO(36) 0, 9,18,27,28,29,37,38,39,40,41,42,43,44,45,46,47,54,63,72; % 36
FO(37) 1,10,19,27,28,29,36,38,39,40,41,42,43,44,45,46,47,55,64,73; % 37
FO(38) 2,11,20,27,28,29,36,37,39,40,41,42,43,44,45,46,47,56,65,74; % 38
FO(39) 3,12,21,30,31,32,36,37,38,40,41,42,43,44,48,49,50,57,66,75; % 39
FO(40) 4,13,22,30,31,32,36,37,38,39,41,42,43,44,48,49,50,58,67,76; % 40
FO(41) 5,14,23,30,31,32,36,37,38,39,40,42,43,44,48,49,50,59,68,77; % 41
FO(42) 6,15,24,33,34,35,36,37,38,39,40,41,43,44,51,52,53,60,69,78; % 42
FO(43) 7,16,25,33,34,35,36,37,38,39,40,41,42,44,51,52,53,61,70,79; % 43
FO(44) 8,17,26,33,34,35,36,37,38,39,40,41,42,43,51,52,53,62,71,80; % 44
FO(45) 0, 9,18,27,28,29,36,37,38,46,47,48,49,50,51,52,53,54,63,72; % 45
FO(46) 1,10,19,27,28,29,36,37,38,45,47,48,49,50,51,52,53,55,64,73; % 46
FO(47) 2,11,20,27,28,29,36,37,38,45,46,48,49,50,51,52,53,56,65,74; % 47
FO(48) 3,12,21,30,31,32,39,40,41,45,46,47,49,50,51,52,53,57,66,75; % 48
FO(49) 4,13,22,30,31,32,39,40,41,45,46,47,48,50,51,52,53,58,67,76; % 49
FO(50) 5,14,23,30,31,32,39,40,41,45,46,47,48,49,51,52,53,59,68,77; % 50
FO(51) 6,15,24,33,34,35,42,43,44,45,46,47,48,49,50,52,53,60,69,78; % 51
FO(52) 7,16,25,33,34,35,42,43,44,45,46,47,48,49,50,51,53,61,70,79; % 52
FO(53) 8,17,26,33,34,35,42,43,44,45,46,47,48,49,50,51,52,62,71,80; % 53
FO(54) 0, 9,18,27,36,45,55,56,57,58,59,60,61,62,63,64,65,72,73,74; % 54
FO(55) 1,10,19,28,37,46,54,56,57,58,59,60,61,62,63,64,65,72,73,74; % 55
FO(56) 2,11,20,29,38,47,54,55,57,58,59,60,61,62,63,64,65,72,73,74; % 56
FO(57) 3,12,21,30,39,48,54,55,56,58,59,60,61,62,66,67,68,75,76,77; % 57
FO(58) 4,13,22,31,40,49,54,55,56,57,59,60,61,62,66,67,68,75,76,77; % 58
FO(59) 5,14,23,32,41,50,54,55,56,57,58,60,61,62,66,67,68,75,76,77; % 59
FO(60) 6,15,24,33,42,51,54,55,56,57,58,59,61,62,69,70,71,78,79,80; % 60
FO(61) 7,16,25,34,43,52,54,55,56,57,58,59,60,62,69,70,71,78,79,80; % 61
FO(62) 8,17,26,35,44,53,54,55,56,57,58,59,60,61,69,70,71,78,79,80; % 62
FO(63) 0, 9,18,27,36,45,54,55,56,64,65,66,67,68,69,70,71,72,73,74; % 63
FO(64) 1,10,19,28,37,46,54,55,56,63,65,66,67,68,69,70,71,72,73,74; % 64
FO(65) 2,11,20,29,38,47,54,55,56,63,64,66,67,68,69,70,71,72,73,74; % 65
FO(66) 3,12,21,30,39,48,57,58,59,63,64,65,67,68,69,70,71,75,76,77; % 66
FO(67) 4,13,22,31,40,49,57,58,59,63,64,65,66,68,69,70,71,75,76,77; % 67
FO(68) 5,14,23,32,41,50,57,58,59,63,64,65,66,67,69,70,71,75,76,77; % 68
FO(69) 6,15,24,33,42,51,60,61,62,63,64,65,66,67,68,70,71,78,79,80; % 69
FO(70) 7,16,25,34,43,52,60,61,62,63,64,65,66,67,68,69,71,78,79,80; % 70
FO(71) 8,17,26,35,44,53,60,61,62,63,64,65,66,67,68,69,70,78,79,80; % 71
FO(72) 0, 9,18,27,36,45,54,55,56,63,64,65,73,74,75,76,77,78,79,80; % 72
FO(73) 1,10,19,28,37,46,54,55,56,63,64,65,72,74,75,76,77,78,79,80; % 73
FO(74) 2,11,20,29,38,47,54,55,56,63,64,65,72,73,75,76,77,78,79,80; % 74
FO(75) 3,12,21,30,39,48,57,58,59,66,67,68,72,73,74,76,77,78,79,80; % 75
FO(76) 4,13,22,31,40,49,57,58,59,66,67,68,72,73,74,75,77,78,79,80; % 76
FO(77) 5,14,23,32,41,50,57,58,59,66,67,68,72,73,74,75,76,78,79,80; % 77
FO(78) 6,15,24,33,42,51,60,61,62,69,70,71,72,73,74,75,76,77,79,80; % 78
FO(79) 7,16,25,34,43,52,60,61,62,69,70,71,72,73,74,75,76,77,78,80; % 79
FO(80) 8,17,26,35,44,53,60,61,62,69,70,71,72,73,74,75,76,77,78,79; % 80
FILL BITNO[*] WITH 0, 1, 2, 4, % NOTE ZERO BASED!!!
8, 16, 32, 64,
128, 256, 512, 1024;
WRITE(LINE, <"INITIALIZATION TIME: ",
"PT=",F8.3," IO=",F8.3," ET=", F10.3>,
TIME(2)/60, TIME(3)/60, (TIME(1)-STARTET)/60);
END;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% SOME TESTED DATA VALUES,
%071698035
%600030700
%090400100
%000009002
%300000009
%500200000
%004006070
%006080001
%820314950
%000000008
%010000040
%000645910
%591300000
%062401790
%000008165
%024173000
%080000020
%900000000
%000000000 - 272 SOLUTIONS
%010000040
%000605910
%591300000
%062401790
%000008105
%024173000
%080000020
%000000000
%600900050 - VERY HARD - PT = 30SEC+
%009000003
%050040007
%013502790
%000000000
%092603540
%900050020
%100000600
%020004005
%000000008 - 12 SOLUTIONS
%010000040
%000645910
%591300000
%000000007
%000008165
%024173000
%080000020
%900000000
%000000008 - 118 SOLUTIONS
%010000040
%000645910
%591300000
%000000000
%000008165
%024173000
%080000020
%900000000
STARTET:= TIME(1);
INITIALIZE;
READGRID;
SELECTBOX;
% WARN THE OPERATOR
IF NUM > 1 THEN
WRITE(SPO, <"FOUND ", I5, " SOLUTIONS">, NUM);
WRITE(LINE, <" ">);
WRITE(LINE, <I3," SOLUTION(S), ",
"MAX RECURSION DEPTH = ",I3,", TIMES: ",
"PT=",F8.3," IO=",F8.3," ET = ", F10.3>,
NUM, MAXDEPTH,
TIME(2)/60, TIME(3)/60, (TIME(1)-STARTET)/60);
END.
?DATA CARD
000000008
010000040
000645910
591300000
062401790
000008165
024173000
080000020
900000000
?END