Возникли проблемы с созданием того, что должно быть простым дополнением к Sudoku solver

#python

#питон

Вопрос:

У меня возникли проблемы с адаптацией решателя судоку отсюдаhttps://techwithtim.net/tutorials/python-programming/sudoku-solver-backtracking / для включения диагонального ограничения

Это исходный код:

 board = [
    [0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0]
]

def solve(bo):
    find = find_empty(bo)
    if not find:
        return True
    else:
        row, col = find

    for i in range(1,10):
        if valid(bo, i, (row, col)):
            bo[row][col] = i

            if solve(bo):
                return True

            bo[row][col] = 0

    return False


def valid(bo, num, pos):
    
    # Check row
    for i in range(len(bo[0])):
        if bo[pos[0]][i] == num and pos[1] != i:
            return False

    # Check column
    for i in range(len(bo)):
        if bo[i][pos[1]] == num and pos[0] != i:
            return False

    # Check box
    box_x = pos[1] // 3
    box_y = pos[0] // 3

    for i in range(box_y*3, box_y*3   3):
        for j in range(box_x * 3, box_x*3   3):
            if bo[i][j] == num and (i,j) != pos:
                return False
                
    return True


def print_board(bo):
    for i in range(len(bo)):
        if i % 3 == 0 and i != 0:
            print("- - - - - - - - - - - - - ")

        for j in range(len(bo[0])):
            if j % 3 == 0 and j != 0:
                print(" | ", end="")

            if j == 8:
                print(bo[i][j])
            else:
                print(str(bo[i][j])   " ", end="")


def find_empty(bo):
    for i in range(len(bo)):
        for j in range(len(bo[0])):
            if bo[i][j] == 0:
                return (i, j)  # row, col

    return None

print_board(board)
solve(board)
print("______________________")
print_board(board)
  

Теперь это пустая доска, на ней, очевидно, есть почти бесконечное количество допустимых решений, и код просто вернет первое найденное, но он также быстро найдет уникальное решение, когда вы введете несколько реальных чисел.

В качестве проблемы с кодированием я решил посмотреть, могу ли я добавить диагональное ограничение: т. е. ни одно число не повторяется в bo [i] [i] от i = 0 до i = 8 включительно (т. е. диапазон (0,9) или range (9) — смотрите, я знаю некоторый код!)

Итак, это казалось довольно простым — мне просто нужно добавить дополнительный цикл в действительную функцию — насколько это может быть сложно?

Я пытался:

 for i in range(9):
        if bo[i][i] == num and (i,i) != pos:
            return False
  

и множество подобных его вариаций — и поэтому такая удача. Я не могу заставить это работать. Для этого варианта кажется, что он выполняется вечно, но если вы введете, скажем

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

Которое должно легко возвращать допустимое диагональное решение судоку — оно просто возвращает ту же введенную доску, что и «решение», т. Е. с 72 пустыми ячейками!

Очевидно, мне не хватает чего-то очень простого, но я схожу с ума, выясняя, что это такое.

Я новичок в python, и это мой первый пост здесь — поэтому приношу извинения, если мой этикет на форуме неправильный. Я ценю все отзывы!

Спасибо!

редактировать: ОК. У меня есть решение, которое почти работает, но я хотел бы знать, почему есть одно исключение, и я все еще хотел бы знать, почему мой оригинал этого не сделал. Вот что я сделал

Первый:

 def main_diagonal(bo):
    main_diagonal = []
    for i in range(0,9):
        main_diagonal  = str(bo[i][i])
    for i in range(0,9):
        main_diagonal[i] = int(main_diagonal[i])
    return main_diagonal
  

Затем в пределах допустимой функции добавьте:

 for i in range(1,10):
        if main_diagonal(bo).count(i) > 1:
            return False
  

Теперь это очень хорошо помогает остановить повторение чисел по диагоналям, однако есть исключение! 81-я ячейка, то есть bo[8][8], которая появляется на главной диагонали, может содержать повторяющееся число. Может быть, это связано с тем, что исходный алгоритм предполагает (правильно), что если первые 80 ячеек допустимы, то и 81-я тоже, тогда как здесь это не так? Как мне устранить эту ошибку?

Этот способ подсчета, если количество появлений определенного числа больше 1, для меня гораздо более интуитивно понятен, чем исходный код, но мне все еще нужно узнать, почему моя первая попытка не сработала, чтобы не попасть в подобную ситуацию в дальнейшем.

Комментарии:

1. Ваш вопрос, хотя и хорошо сформулирован, безусловно, слишком длинный для большинства читателей. SO предоставляется бесплатно, и вы хотите, чтобы мы прочитали весь ваш код целиком. Можете ли вы сузить круг ваших проблем?

2. Спасибо. К сожалению, я действительно не знаю, какие части кода следует удалить. Возможно, если кто-то ответит, он сможет предложить обратную связь относительно того, какие части кода я должен был включить. Спасибо.