sudoku subsquare generation

Question:

I have a 9×9 sudoku board. I have to create 9 subsquare lists. I store each of these lists as a row in another list called sub_square.

CODE:

sub_square = []
sub_list = []
for x in range(0,3):
    for y in range(0,3):
        sub_list.append(sudoku[x][y])

sub_square.append(sub_list)
sub_list = []

for x in range (0,3):
    for y in range(3,6):
        sub_list.append(sudoku[x][y])

sub_square.append(sub_list)
sub_list = []

for x in range (0,3):
    for y in range(6,9):
        sub_list.append(sudoku[x][y])

sub_square.append(sub_list)
sub_list = []

I do the same for the other 6 sub squares. Is there any other way that is much simpler.

SUDOKU:

 [0, 9, 4, 3, 0, 0, 0, 0, 0],
 [0, 0, 7, 5, 0, 0, 0, 0, 0],
 [0, 0, 1, 4, 0, 0, 0, 2, 0],

 [4, 6, 0, 8, 0, 0, 0, 0, 3],
 [0, 0, 0, 0, 0, 0, 0, 0, 0],
 [2, 0, 0, 0, 0, 3, 0, 6, 9],

 [0, 5, 0, 0, 0, 6, 2, 0, 0],
 [0, 0, 0, 0, 0, 5, 1, 0, 0],
 [0, 0, 0, 0, 0, 1, 6, 4, 0]

so the first sub square list is:

[0, 9, 4, 0, 0, 7, 0, 0, 1]
Asked By: Wasi

||

Answers:

If you are not opposed to 3rd-party libraries, use numpy:

import numpy as np

board = np.array([
    [0, 9, 4, 3, 0, 0, 0, 0, 0],
    [0, 0, 7, 5, 0, 0, 0, 0, 0],
    [0, 0, 1, 4, 0, 0, 0, 2, 0],
    [4, 6, 0, 8, 0, 0, 0, 0, 3],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [2, 0, 0, 0, 0, 3, 0, 6, 9],
    [0, 5, 0, 0, 0, 6, 2, 0, 0],
    [0, 0, 0, 0, 0, 5, 1, 0, 0],
    [0, 0, 0, 0, 0, 1, 6, 4, 0]])

print(board)
print()
print(board[3,1])     # 4th row, 2nd column
print()
print(board[3])       # 4th row
print()
print(board[...,2])   # 3rd column
print(board[:,2:3])   # 3rd column (another way)
print()
print(board[0:3,0:3]) # first sub-square
print(board[0:3,0:3].flatten()) # another way

Output

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

6

[4 6 0 8 0 0 0 0 3]

[4 7 1 0 0 0 0 0 0]
[[4]
 [7]
 [1]
 [0]
 [0]
 [0]
 [0]
 [0]
 [0]]

[[0 9 4]
 [0 0 7]
 [0 0 1]]
[0 9 4 0 0 7 0 0 1]
Answered By: Mark Tolonen

Yes, there is an easier way:

subsquares = [[sudokuSquare[j][i] for j in range(x, x + w) for i in range(y, y + h)] for x in range(0, 9, 3) for y in range(0, 9, 3)]

Where h and w would be the height and width of each subsquare, respectively. (For your purposes, h and w would both equal 3.

Answered By: Joel Cornett
for y in range(0,3):

for y in range(3,6):

for y in range(6,9):

If you look at your three blocks of code they are identical apart from the above quoted lines. This means that you can replace them by a single block of code inside another loop which you use as a parameter to the range of the y loop. You then need a fourth loop which you use as a parameter to the range of the x loop. You would then end up with something along the lines of Joel’s answer, although he has used iterators so that he can collapse it all down to a single line of code.

Answered By: Neil

Improving upon the numpy answer of Mark Tolonen, you can automate the process. I assume you’ve already created the numpy object board:

def subsquare(A,k,i,j):
    return A[i*k:(i+1)*k, j*k:(j+1)*k].flatten().tolist()

def sub_itr(A,block_size):
    assert A.shape[0]%block_size == 0  # Make sure block fits
    k = A.shape[0]/block_size
    for i in xrange(k):
        for j in xrange(k):
            yield subsquare(A,k,i,j)

for block in sub_itr(board,3):
    print block

Giving:

[0, 9, 4, 0, 0, 7, 0, 0, 1]
[3, 0, 0, 5, 0, 0, 4, 0, 0]
...
[2, 0, 0, 1, 0, 0, 6, 4, 0]
Answered By: Hooked
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.