Согласно Википедии, судоку — это логическая комбинаторная головоломка с размещением чисел. В классическом судоку цель состоит в том, чтобы заполнить сетку 9 × 9 цифрами так, чтобы каждый столбец, каждая строка и каждая из девяти подсеток 3 × 3, составляющих сетку (также называемые ящиками, блоками или регионы) содержат все цифры от 1 до 9.

Это правила обычного судоку:

  • Каждая строка должна содержать каждое число от 1 до 9 ровно один раз.
  • Точно так же в каждом столбце требуется по одному каждому числу от 1 до 9.
  • Каждая «область» 3x3 должна следовать одному и тому же шаблону 1–9.

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

ШАГ 1. Определите, как хранить судоку

Есть много способов сохранить доску судоку в Python. Вы можете использовать кортежи, наборы или даже словари для хранения чисел для каждой ячейки сетки.

В этом руководстве мы создадим список, содержащий 9 строк, который содержит 9 чисел для каждой строки на доске судоку.

Например:

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

Ниже представлена ​​предыдущая доска судоку, устроенная иначе:

Необязательно, но в качестве лучшей практики вы можете использовать эту функцию, чтобы проверить, является ли полученный вами список действительным отправкой:

ШАГ 2. Напишите повторно используемую функцию для проверки повторяющихся значений в строке.

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

Мы можем написать функцию, которая принимает список (доска судоку), перебирает его элементы (строки), проверяет, есть ли повторяющиеся значения, и возвращает True, если есть повторяющиеся значения, или False, если нет.

Чтобы использовать эту функцию, мы определим две функции для извлечения значений судоку в разном порядке.

ШАГ 3: Напишите функцию, которая получает доску и возвращает список со столбцами

В зависимости от того, как хранится судоку, первая цифра каждого элемента в списке представляет первый столбец, вторая цифра представляет второй столбец и так далее.

Эта функция будет получать доску судоку, перебирать каждую строку на доске и сохранять n-ю цифру каждой строки в списке. После сохранения столбца мы добавим список к родительскому списку и продолжим со следующими цифрами.

Вот как выглядит функция:

Если мы вызовем эту функцию с нашим образцом судоку в качестве аргумента, мы получим следующий список:

print(to_column_list(sample1))
>> [['2', '4', '8', '3', '6', '5', '7', '9', '1'], 
    ['9', '3', '7', '8', '1', '4', '6', '2', '5'], 
    ['5', '1', '6', '7', '2', '9', '3', '8', '4'], 
    ['7', '8', '1', '4', '3', '2', '5', '6', '9'], 
    ['4', '6', '9', '5', '8', '1', '2', '7', '3'], 
    ['3', '5', '2', '9', '7', '6', '4', '1', '8'], 
    ['8', '9', '5', '2', '4', '7', '1', '3', '6'], 
    ['6', '2', '4', '1', '9', '3', '8', '5', '7'], 
    ['1', '7', '3', '6', '5', '8', '9', '4', '2']]

Если вы хотите вернуть список строк вместо списков, вы можете заменить код в строке 11 следующим:

return [''.join(row) for row in nth_digit]

Новый вывод:

print(to_column_list(sample1))
>> ['248365791', 
    '937814625', 
    '516729384', 
    '781432569', 
    '469581273', 
    '352976418', 
    '895247136', 
    '624193857', 
    '173658942']

Независимо от того, какой оператор возврата вы используете, программа может использовать оба результирующих списка.

Забавный факт: вложение одной и той же функции четное количество раз вернет исходный список.

Посмотри:

print(to_column_list(to_column_list(sample1)))
>> ['295743861',
    '431865927',
    '876192543',
    '387459216',
    '612387495',
    '549216738',
    '763524189',
    '928671354',
    '154938672']

ШАГ 4: Напишите функцию, которая получает доску и возвращает список с регионами

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

Во-первых, давайте сохраним верхние регионы вручную и проверим, есть ли шаблон, который мы могли бы использовать.

Если присмотреться, функция диапазона получает два параметра: начальное и конечное числа. Вложенные циклы for увеличивают эти числа на 3, чтобы перейти к следующему региону.

Зная это, мы можем поместить эти циклы for в другой цикл for, возвращающий 0–3–6, и добавить эти значения к параметрам диапазона.

Именно так:

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

Опять же, функции диапазона в строках 10, 22 и 34 каждый раз увеличивают свои параметры на 3. Наконец, мы можем создать цикл for для возврата 0–3–6, чтобы мы могли перейти к следующему ряду регионов.

Взгляните на окончательный код для этого шага:

ШАГ 5: Соберите все вместе

На данный момент у нас есть:

  1. Функция, проверяющая наличие повторяющихся значений в строке матрицы.
  2. Функция, которая проверяет, действительна ли доска судоку. (НЕОБЯЗАТЕЛЬНО)
  3. Функция, которая возвращает n-е значение строк в матрице.
  4. Функция, которая возвращает список с каждой областью судоку в виде списка.

Давайте определим функцию, которая принимает судоку, проверяет, является ли она допустимой доской, и решает, является ли это допустимым решением судоку или нет.

Поздравляем! У вас есть программа Python, которая проверяет решения судоку.