Reading Sudokus from text file and applying backtracking

Question:

I have just begun with python, so excuse me if these are noob questions or if the questions are already answered.
I am trying to read multiple sudoku puzzles and apply the algorithm I found online. The code utilizes a grid(list[list[int]]) setup. I have tried looking for a solution online, but all I found was that I should convert the .txt file to a JSON file and continue from there.

The .txt file looks like this:

AME: sudoku
TYPE: SUD
COMMENT: 5 sudokus

SUDOKU 1
034000600
002600080
068300007
003001005
059060072
000520046
205906000
000408050
000007004

SUDOKU 2
000504000
000089020
785000000
002346008
040290050
860000000
030007042
400060805
608005030

SUDOKU 3
040000300
036072000
078060400
083000600
000300005
025008070
300004800
000000024
764089530

SUDOKU 4
000074900
000000046
079000300
600728009
980503000
037940050
200000000
008030060
060490023

SUDOKU 5
026030470
000200510
700900020
509000000
000050000
000000307
080009001
034006000
095070640

EOF 

Code from online:

def is_valid(grid, r, c, k):
    not_in_row = k not in grid[r]
    not_in_column = k not in [grid[i][c] for i in range(9)]
    not_in_box = k not in [grid[i][j] for i in range(r//3*3, r//3*3+3) for j in range(c//3*3, c//3*3+3)]
    return not_in_row and not_in_column and not_in_box


def solve(grid, r=0, c=0):
    if r == 9:
        return True
    elif c == 9:
        return solve(grid, r+1, 0)
    elif grid[r][c] != 0:
        return solve(grid, r, c+1)
    else:
        for k in range(1, 10):
            if is_valid(grid, r, c, k):
                grid[r][c] = k
                if solve(grid, r, c+1):
                    return True
                grid[r][c] = 0
        return False
        
grid = [
    [0, 0, 4, 0, 5, 0, 0, 0, 0],
    [9, 0, 0, 7, 3, 4, 6, 0, 0],
    [0, 0, 3, 0, 2, 1, 0, 4, 9],
    [0, 3, 5, 0, 9, 0, 4, 8, 0],
    [0, 9, 0, 0, 0, 0, 0, 3, 0],
    [0, 7, 6, 0, 1, 0, 9, 2, 0],
    [3, 1, 0, 9, 7, 0, 2, 0, 0],
    [0, 0, 9, 1, 8, 2, 0, 0, 3],
    [0, 0, 0, 0, 6, 0, 1, 0, 0]
]
solve(grid)
print(*grid, sep='n')

Instead of the static grid that needs to be inputted, I would instead use the .txt file. I just couldn’t find anything to help me solve the issue at hand. This might be because I am new to python or I need help understanding how to convert to JSON files.

How to convert txt file into json using python? I have looked at this, but I am unsure if this is even the right approach.

Any feedback is appreciated, or even a nod in the right direction is also helpful.

Asked By: zellez

||

Answers:

Here’s an example of how you could read the sudoku text file into a dictionary of list[list[int]], i.e. dict[str, list[list[int]]]:

def read_sudokus(fn: str) -> dict[str, list[list[int]]]:
    sudokus = {}
    with open(fn) as f:
        [next(f) for _ in range(4)]  # skip the header
        while True:
            name = next(f).strip()
            if name == 'EOF':
                break
            sudokus[name] = [list(map(int, next(f).strip())) for _ in range(9)]
            next(f)  # skip blank line
    return sudokus


ss = read_sudokus('sudoku.txt')
print(ss)

Output:

{'SUDOKU 1': [[0, 3, 4, 0, 0, 0, 6, 0, 0], [0, 0, 2, 6, 0, 0, 0, 8, 0], [0, 6, 8, 3, 0, 0, 0, 0, 7], [0, 0, 3, 0, 0, 1, 0, 0, 5], [0, 5, 9, 0, 6, 0, 0, 7, 2], [0, 0, 0, 5, 2, 0, 0, 4, 6], [2, 0, 5, 9, 0, 6, 0, 0, 0], [0, 0, 0, 4, 0, 8, 0, 5, 0], [0, 0, 0, 0, 0, 7, 0, 0, 4]], 'SUDOKU 2':  etc.

This assumes a standard sudoku size of 9×9 of course.

Answered By: Grismar

The simple answer would be to read the lines of the txt file out and then search for the sudokus.
It would look something like this:

with open('sudoku.txt', 'r') as f:
    lines = f.readlines()

puzzles = []

for i, line in enumerate(lines):
    sudoku = []
    if line.startswith('SUDOKU'):
        # next 9 lines will be our puzzle
        for j in range(1, 10):
            sudoku.append([*lines[i+j].strip()]) # strip gets rid of the newline character, the * splits the string into a list of characters
        puzzles.append(sudoku)

The puzzles list now contains a list of lists, but all of the characters are strings right now, I will leave the conversion into integers to you.

Answered By: watrgoat