I wanted to give a Christmas present to the user group, to thank everyone
for all the information that I have gathered over the years. So here is a
program to solve Sudoku puzzles. Just like most of my programs, the user
interface is the pits. And of course, it's not complete either. It
handles the "Easy" and "Medium" difficulty puzzles, but is pretty spotty
on "Difficult" puzzles.
Copy and paste, compile, I hope it works ok.
Enjoy, Merry Christmas, Happy Hanukkah, Kwanzaa, Eid al-Fitr, etc.
**********************************************
BIG.ARRAY = ''
EMPTY.ARRAY = ''
POSSIBLE.ARRAY = ''
STARTING.ARRAY = ''
*
* Print the opening screen
*
PRINT @(-1)
FOR I = 1 TO 9
PRINT ' ':STR('-',37)
PRINT ' | | | | | | | | | |'
NEXT I
PRINT ' ':STR('-',37)
*
* Input the starting numbers
*
PROMPT ''
FOR I = 1 TO 9
FOR J = 1 TO 9
PRINT @(J * 4,I * 2):;INPUT NUMBER
STARTING.ARRAY<I,J> = NUMBER
EMPTY.ARRAY<I,J> = ''
NEXT J
NEXT I
PRINT;PRINT 'Starting Puzzle'
PRINT
FOR I = 1 TO 9
FOR J = 1 TO 9
PRINT STARTING.ARRAY<I,J> 'R#1 ':
NEXT J
PRINT
NEXT I
PRINT;PRINT
BIG.ARRAY = STARTING.ARRAY
LOOP
POSSIBLE.ARRAY = EMPTY.ARRAY
*
* Find the easy ones. Start with 123456789, remove any hits. If
only one number remains, it must belong
* to the cell.
*
FOR ROW = 1 TO 9
FOR COLUMN = 1 TO 9
GOSUB FIRST.CHECK
NEXT J
NEXT I
*
* Check each 3x3 square, by eliminating numbers that are outside
the square
*
FOR SQ.ROW = 1 TO 7 STEP 3
FOR SQ.COLUMN = 1 TO 7 STEP 3
GOSUB SECOND.CHECK
NEXT SQ.COLUMN
NEXT SQ.ROW
GOSUB CHECK.ARRAY
IF ERROR.FLAG THEN
PRINT;PRINT 'Try again?':;INPUT TI
IF TI = 'D' THEN
FOR I = 1 TO 9
FOR J = 1 TO 9
PRINT BIG.ARRAY<I,J> 'R#1 ':
NEXT J
PRINT
NEXT I
PRINT
FOR I = 1 TO 9
FOR J = 1 TO 9
PRINT POSSIBLE.ARRAY<I,J>
'R#':'-':
NEXT J
PRINT
NEXT I
END
END ELSE
TI = 'N'
END
UNTIL TI = 'N' DO REPEAT
PRINT;PRINT 'Ending puzzle'
PRINT
FOR I = 1 TO 9
FOR J = 1 TO 9
PRINT BIG.ARRAY<I,J> 'R#1 ':
NEXT J
PRINT
NEXT I
PRINT
STOP
************
FIRST.CHECK:
************
*
* First, do not check any cells from the starting array
*
IF STARTING.ARRAY<ROW,COLUMN> # '' THEN RETURN
*
* Do not check any cells already in big array?
*
IF BIG.ARRAY<ROW,COLUMN> # '' THEN RETURN
*
* Check row/column
*
FULL.STRING = '123456789'
FOR I = 1 TO 9
CHARACTER = BIG.ARRAY<ROW,I>
IF CHARACTER # '' THEN
LOC = INDEX(FULL.STRING,CHARACTER,1)
IF LOC THEN
FULL.STRING = FULL.STRING[1,LOC -
1]:FULL.STRING[LOC + 1,9]
END
END
NEXT I
FOR I = 1 TO 9
CHARACTER = BIG.ARRAY<I,COLUMN>
IF CHARACTER # '' THEN
LOC = INDEX(FULL.STRING,CHARACTER,1)
IF LOC THEN
FULL.STRING = FULL.STRING[1,LOC -
1]:FULL.STRING[LOC + 1,9]
END
END
NEXT I
IF LEN(FULL.STRING) = 1 THEN
BIG.ARRAY<ROW,COLUMN> = FULL.STRING
RETURN
END
*
* Check the 3x3 square
*
FULL.STRING = '123456789'
I = 3 * INT((ROW - 1)/3)
J = 3 * INT((COLUMN - 1)/3)
FOR K = 1 TO 3
FOR L = 1 TO 3
CHARACTER = BIG.ARRAY<I + K,J + L>
IF CHARACTER # '' THEN
LOC = INDEX(FULL.STRING,CHARACTER,1)
IF LOC THEN
FULL.STRING = FULL.STRING[1,LOC -
1]:FULL.STRING[LOC + 1,9]
END
END
NEXT L
NEXT K
IF LEN(FULL.STRING) = 1 THEN
BIG.ARRAY<ROW,COLUMN> = FULL.STRING
END
RETURN
*************
SECOND.CHECK:
*************
TEMP.ARRAY = EMPTY.ARRAY
FULL.STRING = '123456789'
FOR I = SQ.ROW TO SQ.ROW + 2
FOR J = SQ.COLUMN TO SQ.COLUMN + 2
*
* If this cell is not blank, remove the number from
full.string, If this cell
* is blank, then get all of the other numbers from the
row/column
*
IF BIG.ARRAY<I,J> # '' THEN
NUMBER = BIG.ARRAY<I,J>
LOC = INDEX(FULL.STRING,NUMBER,1)
IF LOC THEN
FULL.STRING = FULL.STRING[1,LOC -
1]:FULL.STRING[LOC + 1,99]
END
TEMP.ARRAY<I,J> = '123456789'
END ELSE
USED.NUMBERS = ''
FOR L = 1 TO 9
NUMBER = BIG.ARRAY<I,L>
IF NUMBER # '' THEN
IF
NOT(INDEX(USED.NUMBERS,NUMBER,1)) THEN USED.NUMBERS := NUMBER
END
NEXT L
FOR K = 1 TO 9
NUMBER = BIG.ARRAY<K,J>
IF NUMBER # '' THEN
IF
NOT(INDEX(USED.NUMBERS,NUMBER,1)) THEN USED.NUMBERS := NUMBER
END
NEXT K
TEMP.ARRAY<I,J> = USED.NUMBERS
END
NEXT J
NEXT I
*
* If full.string is empty, then this square has already been filled in.
Otherwise, try and find
* a row or column that has not used any of the remaining numbers
*
NUM.REMAINING.NUMBERS = LEN(FULL.STRING)
FOR POSITION = 1 TO NUM.REMAINING.NUMBERS
NUMBER = FULL.STRING[POSITION,1]
HITS = 0
FOR I = SQ.ROW TO SQ.ROW + 2
FOR J = SQ.COLUMN TO SQ.COLUMN + 2
LOC = INDEX(TEMP.ARRAY<I,J>,NUMBER,1)
IF NOT(LOC) THEN
HITS<1> += 1 ; HITS<2,-1> =
NUMBER ; HITS<3,-1> = I ; HITS<4,-1> = J
END
NEXT J
NEXT I
*
* If you only had one hit, then store the number in that cell.
*
IF HITS<1> = 1 THEN
IF BIG.ARRAY<HITS<3>,HITS<4>> = '' THEN
BIG.ARRAY<HITS<3>,HITS<4>> = NUMBER
END ELSE
PRINT 'Good work, Loser!'
INPUT TI
END
END
*
* If there were multiple hits, then store the 'possible' hits in
the possible array
*
IF HITS<1> > 1 THEN
FOR I = 1 TO HITS<1>
POSSIBLE.ARRAY<HITS<3,I>,HITS<4,I>> := HITS<2,I>
NEXT I
END
NEXT POSITION
RETURN
************
CHECK.ARRAY:
************
ERROR.FLAG = 0
FOR I = 1 TO 9
*
* Check row I
*
STRING = ''
FOR J = 1 TO 9
STRING := BIG.ARRAY<I,J>
NEXT J
GOSUB CHECK.STRING
*
* Check column I
*
STRING = ''
FOR J = 1 TO 9
STRING := BIG.ARRAY<J,I>
NEXT J
GOSUB CHECK.STRING
NEXT I
FOR I = 0 TO 2
FOR J = 0 TO 2
STRING = ''
FOR K = 1 TO 3
FOR L = 1 TO 3
STRING := BIG.ARRAY<I * 3 + K,J * 3 + L>
NEXT L
NEXT K
GOSUB CHECK.STRING
NEXT J
NEXT I
IF NOT(ERROR.FLAG) THEN
PRINT 'You made it!'
END
RETURN
*************
CHECK.STRING:
*************
*
* Must be numeric, must have nine characters
*
IF LEN(STRING) # 9 OR NOT(NUM(STRING)) THEN
ERROR.FLAG = 1
END
*
* The sum must be 45, cannot have a number repeat
*
CHECK.SUM = 0
FOR POSITION = 1 TO 9
CHECK.SUM += STRING[POSITION,1]
IF COUNT(STRING,POSITION) # 1 THEN
ERROR.FLAG = 2
END
NEXT POSITION
IF CHECK.SUM # 45 THEN
ERROR.FLAG = 3
END
RETURN
-------
u2-users mailing list
[email protected]
To unsubscribe please visit http://listserver.u2ug.org/