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
u2-users@listserver.u2ug.org
To unsubscribe please visit http://listserver.u2ug.org/

Reply via email to