How to automate dictionary creation in Python
Question: 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?


Answer: 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.

