Я пишу алгоритм на PHP для решения заданной головоломки Судоку. Я установил несколько объектно-ориентированную реализацию с двумя классами: класс Square
для каждой отдельной плитки на плате 9x9 и класс Sudoku
, который имеет матрицу Square
s для представления платы.
Реализация алгоритма, который я использую, является своего рода трехуровневым подходом. Первый шаг, который решит только самые основные головоломки (но является наиболее эффективным), состоит в том, чтобы заполнить любые квадраты, которые могут принимать только одно значение на основе начальной настройки доски, и соответствующим образом скорректировать ограничения для остальных нерешенные квадраты.
Обычно, этот процесс «постоянного распространения» не решает всю доску полностью, но он решает значительную часть. Затем включается второй уровень. Он анализирует каждую единицу (или 9 квадратов, которые должны иметь уникальные присвоения чисел, например, строку или столбец) для «возможных» значений каждого нерешенного квадрата. Этот список возможных значений представлен в виде строки в классе Square
:
class Square {
private $name; // 00, 01, 02, ... , 86, 87, 88
private $peers; // All squares in same row, col, and box
private $number; // Assigned value (0 if not assigned)
private $possibles; // String of possible numbers (1-9)
public function __construct($name, $p = 0) {
$this->name = $name;
$this->setNumber($p);
if ($p == 0) {
$this->possibles = "123456789";
}
}
// ... other functions
Учитывая целый массив нерешенных квадратов в единице (как описано во втором уровне выше), второй уровень объединит все строки «возможных» в одну строку. Затем он будет искать в этой единственной строке любые уникальные символьные значения - значения, которые не повторяются. Это будет означать, что в единице квадратов есть только один квадрат, который может принимать это конкретное значение.
Мой вопрос: для реализации этого второго уровня, как я могу проанализировать эту строку всех возможных значений в единице и легко обнаружить уникальные значения? Я знаю, что могу создать массив, в котором каждый индекс представлен числами 1-9, и я могу увеличить значение соответствующего индекса на 1 для каждого возможного значения этого числа, которое я найду, а затем снова просканировать массив на предмет любых значения 1, но это кажется крайне неэффективным, требующим двух линейных сканирований массива для каждой единицы, и в головоломке Судоку есть 27 единиц.