2

I am trying to write a python code that solves a Sudoku puzzle. My code starts by making a list of each row/column combination, or the coordinates of each box. Next, I want to find a way to, for each box, reference its location. This is my current code:

boxes = []
for i in range(1, 10):
    for x in range(1,10):
        boxes = boxes + ['r'+str(i)+'c'+str(x)]
for box in boxes:

Next, I was going to create a dictionary for each one, but I would want each to be named by the list item. The dictionaries would be, for example, r1c1 = {'row': '1', 'Column': 1}.

What is the best way to separate and store this information?

4
  • 2
    There's definitely a better solution. What's the point of creating those dictionaries? Commented Jul 24, 2016 at 21:53
  • 3
    boxes = boxes + ['r'+str(i)+'c'+str(x)] is a somewhat expensive way of spelling boxes.append('r'+str(i)+'c'+str(x)) or even boxes.append('r{}c{}'.fromat(i, c)). Commented Jul 24, 2016 at 21:54
  • There is no point in creating that many dictionaries. You'd be much better off just storing (i, c) (a tuple) in your list. That way you don't have to map back to the row, column format at all, you'd already have the coordinates. Don't use strings as intermediaries. Commented Jul 24, 2016 at 21:55
  • Thanks. I am very new to python and am still learning how to use it. Commented Jul 24, 2016 at 21:59

2 Answers 2

1

You don't need to create all those dictionaries. You already have your coordinates, just don't lock them up in strings:

boxes = []
for i in range(1, 10):
    for x in range(1,10):
        boxes.append((i, x))

would create a list of (row, column) tuples instead, and you then wouldn't have to map them back.

Even if you needed to associate strings with data, you could do so in a nested dictionary:

coordinates = {
    'r1c1': {'row': 1, 'column': 1},
    # ...
}

but you could also parse that string and extract the numbers after r and c to produce the row and column numbers again.

In fact, I wrote a Sudoku checker on the same principles once; in the following code block_indices, per9() and zip(*per9(s)) produce indices for each block, row or column of a puzzle, letting you verify that you have 9 unique values in each. The only difference is that instead of a matrix, I used one long list to represent a puzzle, all elements from row to row included in sequence:

from itertools import product

block_indices = [[x + y + s for s in (0, 1, 2, 9, 10, 11, 18, 19, 20)]
                 for x, y in product(range(0, 81, 27), range(0, 9, 3))]

def per9(iterable):
    # group iterable in chunks of 9
    return zip(*([iter(iterable)] * 9))

def is_valid_sudoku(s):
    return (
        # rows
        all(len(set(r)) == 9 for r in per9(s)) and
        # columns
        all(len(set(c)) == 9 for c in zip(*per9(s))) and
        # blocks
        all(len(set(s[i] for i in ix)) == 9 for ix in block_indices)
    )

So row 1, column 4 is 1 * 9 + 4 = index 13 in a flat list.

Sign up to request clarification or add additional context in comments.

Comments

0

While Martijn's answer is probably better from a "what you should do" perspective, for completeness, you could build that structure pretty easily using dictionary comprehension:

The below annotated code will output your desire data structure:

boxes = {
    "r%sc%s"%(i,j):         # build the keys in the form "r1c2" 
      {'row':i,"column":j}  # build the dictionary of values - {'row':1, 'column': 2}
    for i in range(1,10)    # first level of loop
    for j in range(1,10)    # second level of loop
}    
print boxes

This will output in your desired format:

{   'r1c1': {   'column': 1, 'row': 1},
    'r1c2': {   'column': 2, 'row': 1},
    'r1c3': {   'column': 3, 'row': 1},
    'r1c4': {   'column': 4, 'row': 1},
 ....
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.