0

I have been trying to write a program that generates a Sudoku puzzle but my program doesn't seem to work. It would seem that the program takes too long to run as my 4X4 is able to generate results. The 2 print statements inserted are indeed printing '1's and '2's.

import random

board = []
for nine in range(9):
    board.append([0, 0, 0, 0, 0, 0, 0, 0, 0])

def sudoku():
    for index in range(81):
        row = index // 9
        col = index % 9
        while board[row][col] == 0:
            chosen = random.randint(1, 9)
            print(1)
            if chosen not in board[row]:
                if check_col(col, chosen) != 1:
                    if row < 3:
                        if col < 3:
                            if check_square(0, 0, chosen) != 1:
                                board[row][col] = chosen
                        elif col < 6:
                            if check_square(0, 3, chosen) != 1:
                                board[row][col] = chosen
                        else:
                            if check_square(0, 6, chosen) != 1:
                                board[row][col] = chosen
                                print(2)
                    elif row < 6:
                        if col < 3:
                            if check_square(3, 0, chosen) != 1:
                                board[row][col] = chosen
                        elif col < 6:
                            if check_square(3, 3, chosen) != 1:
                                board[row][col] = chosen
                        else:
                            if check_square(3, 6, chosen) != 1:
                                board[row][col] = chosen
                    else:
                        if col < 3:
                            if check_square(6, 0, chosen) != 1:
                                board[row][col] = chosen
                        elif col < 6:
                            if check_square(6, 3, chosen) != 1:
                                board[row][col] = chosen
                        else:
                            if check_square(6, 6, chosen) != 1:
                                board[row][col] = chosen


def check_col(col, chosen):
    check = 0
    for c_row in range(9):
        if chosen == board[c_row][col]:
            check = 1
    return check

def check_square(starting_row, starting_col, chosen):
    check = 0
    for c_add in range(3):
        if chosen in board[starting_row + c_add][starting_col:starting_col + 3]:
            check = 1
    return check

sudoku()
for printing in range(9):
    print(board[printing])
2
  • "Doesn't seem to work" -- so determine if it does or does not. Insert print statements all along your code so you can see if it does do something or not. Commented Apr 16, 2020 at 14:44
  • Hi! Thanks for the advice. I have edited the code to the above and they are indeed printing a lot of '1's and some '2's. Commented Apr 16, 2020 at 14:56

1 Answer 1

0

You can generate a random sudoku solution board where all numbers are filled in and then remove some of them to create the puzzle. This will ensure that the puzzle always has a solution. Making sure that it has exactly one solution is a bit more challenging (hint: you must leave at least 17 numbers for a 9x9 sudoku)

The algorithm below will generate a NxN random sudoku solution board instantly for N < 1000.

base  = 3
side  = base*base

# pattern for a baseline valid solution
def pattern(r,c): return (base*(r%base)+r//base+c)%side

# randomize rows, columns and numbers (of valid base pattern)
from random import sample
def shuffle(s): return sample(s,len(s)) 
rBase = range(base) 
rows  = [ g*base + r for g in shuffle(rBase) for r in shuffle(rBase) ] 
cols  = [ g*base + c for g in shuffle(rBase) for c in shuffle(rBase) ]
nums  = shuffle(range(1,base*base+1))

# produce board using randomized baseline pattern
board = [ [nums[pattern(r,c)] for c in cols] for r in rows ]

for line in board: print(line)

[6, 2, 5, 8, 4, 3, 7, 9, 1]
[7, 9, 1, 2, 6, 5, 4, 8, 3]
[4, 8, 3, 9, 7, 1, 6, 2, 5]
[8, 1, 4, 5, 9, 7, 2, 3, 6]
[2, 3, 6, 1, 8, 4, 9, 5, 7]
[9, 5, 7, 3, 2, 6, 8, 1, 4]
[5, 6, 9, 4, 3, 2, 1, 7, 8]
[3, 4, 2, 7, 1, 8, 5, 6, 9]
[1, 7, 8, 6, 5, 9, 3, 4, 2]

You can then remove some of the numbers from the sudoku solution to create the puzzle:

squares = side*side
empties = squares * 3//4
for p in sample(range(squares),empties):
    board[p//side][p%side] = 0

numSize = len(str(side))
for line in board: print("["+"  ".join(f"{n or '.':{numSize}}" for n in line)+"]")

[6  .  .  .  .  3  .  .  1]
[.  9  .  .  .  .  .  .  3]
[4  .  3  .  .  .  6  .  .]
[.  .  .  5  9  .  2  .  6]
[.  .  .  .  .  .  .  .  .]
[.  .  7  .  .  .  .  .  4]
[.  .  .  .  .  .  1  7  .]
[.  .  2  .  .  8  .  .  .]
[.  .  8  .  .  .  .  4  2]

For 4x4 up to 36x36 puzzles, you could make a nicer print of the board like this:

def expandLine(line):
    return line[0]+line[5:9].join([line[1:5]*(base-1)]*base)+line[9:13]
line0  = expandLine("╔═══╤═══╦═══╗")
line1  = expandLine("║ . │ . ║ . ║")
line2  = expandLine("╟───┼───╫───╢")
line3  = expandLine("╠═══╪═══╬═══╣")
line4  = expandLine("╚═══╧═══╩═══╝")

symbol = " 1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ"
nums   = [ [""]+[symbol[n] for n in row] for row in board ]
print(line0)
for r in range(1,side+1):
    print( "".join(n+s for n,s in zip(nums[r-1],line1.split("."))) )
    print([line2,line3,line4][(r%side==0)+(r%base==0)])

╔═══╤═══╤═══╦═══╤═══╤═══╦═══╤═══╤═══╗
║ 6 │   │   ║   │   │ 3 ║   │   │ 1 ║
╟───┼───┼───╫───┼───┼───╫───┼───┼───╢
║   │ 9 │   ║   │   │   ║   │   │ 3 ║
╟───┼───┼───╫───┼───┼───╫───┼───┼───╢
║ 4 │   │ 3 ║   │   │   ║ 6 │   │   ║
╠═══╪═══╪═══╬═══╪═══╪═══╬═══╪═══╪═══╣
║   │   │   ║ 5 │ 9 │   ║ 2 │   │ 6 ║
╟───┼───┼───╫───┼───┼───╫───┼───┼───╢
║   │   │   ║   │   │   ║   │   │   ║
╟───┼───┼───╫───┼───┼───╫───┼───┼───╢
║   │   │ 7 ║   │   │   ║   │   │ 4 ║
╠═══╪═══╪═══╬═══╪═══╪═══╬═══╪═══╪═══╣
║   │   │   ║   │   │   ║ 1 │ 7 │   ║
╟───┼───┼───╫───┼───┼───╫───┼───┼───╢
║   │   │ 2 ║   │   │ 8 ║   │   │   ║
╟───┼───┼───╫───┼───┼───╫───┼───┼───╢
║   │   │ 8 ║   │   │   ║   │ 4 │ 2 ║
╚═══╧═══╧═══╩═══╧═══╧═══╩═══╧═══╧═══╝
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you so much for this!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.