Правильная структура данных для представления головоломки судоку? - PullRequest
5 голосов
/ 01 ноября 2010

Какую интеллектуальную структуру данных можно использовать для представления головоломки Судоку?Т.е. квадрат 9X9, где каждая «ячейка» содержит либо число, либо пробел.

Особые соображения включают в себя:

  • Возможность сравнения по строке, столбцу и в группе 3X3 "
  • Простота реализации (в частности, в Python)
  • Эффективность (не первостепенная)

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

Ответы [ 4 ]

10 голосов
/ 01 ноября 2010

На самом деле, я создал такого зверя, как решатель и генератор, и я использовал 2D-массив. Работало нормально.

Вы просто должны были понять индексы и где они были, и это не было слишком сложно освоить.

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

Иногда менее «элегантное» решение вполне подойдет. Действительно, иногда это предпочтительнее: -)


Возможно, вас заинтересуют алгоритмы, которые я использовал для решателя / генератора.

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

  • если ячейка представляла собой конкретное значение в подсказках, установите для него это значение.
  • если в строке осталась только одна ячейка (или столбец или мини-квадрат), вы можете установить для нее оставшееся значение.
  • , если ячейка помечена как возможно N и N существует в ее строке / столбце / мини-квадрате в другом месте, удалите эту возможность.
  • если в строке / столбце / мини-квадрате есть две ячейки и они имеют одинаковые две возможности (и других возможностей нет), то для всех остальных ячеек в этой строке / столбце / мини-квадрате эта возможность должна быть удалена.

И так далее, добавляя каждое правило, которое я использую при решении реальных головоломок.

Для генератора я начал с:

123 456 789
456 789 123
789 123 456

234 567 891
567 891 234
891 234 567

345 678 912
678 912 345
912 345 678

, а затем, в цикле переменного размера (не менее 500), приступил к обмену строк и столбцов таким образом, чтобы он никогда не создавал неверную головоломку. Другими словами, поменяйте местами строки или столбцы с группой, в которой они находятся (например, строки 1, 2 и 3 являются группой, как и столбцы 4, 5 и 6).

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

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

Это не позволило мне получить головоломку, которая была логически неразрешима.

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

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

Неплохая схема, возможно, есть и лучшие, но эта сработала хорошо для меня.

Теперь, если бы я только мог разобраться с этими вещами Какуро, я мог бы умереть счастливым: -)

7 голосов
/ 01 ноября 2010

Читать Питер Норвиг * эссе Решение каждой головоломки судоку .Вам вряд ли удастся найти более элегантное решение, и вы, вероятно, узнаете несколько новых вещей о структурах данных, Python и анализе производительности.

2 голосов
/ 01 ноября 2010

Другие обоснованно предложили просто использовать 2D-массив.

Я отмечаю, что двумерный массив в большинстве языковых реализаций (все, что реализовано как «массив массива X») страдает дополнительными затратами времени доступа (один доступ к массиву верхнего уровня, второй к вложенному массиву).

Я предлагаю вам абстрактно реализовать структуру данных в виде двумерного массива (возможно, даже продолжая использовать 2 индекса), но реализовать массив как отдельный блок из 81 ячейки, классически проиндексированный с помощью i * 9 + j. Это дает вам концептуальную ясность и несколько более эффективную реализацию, исключая второй доступ к памяти.

Вы должны иметь возможность скрывать доступ к массиву 1D за сеттерами и геттерами, которые принимают двумерные индексы. Если у вашего языка есть возможность (не знаю, правда ли это для Python), такие небольшие методы могут быть встроены для дополнительной скорости.

0 голосов
/ 01 ноября 2010

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

Подробнее о типах данных Python можно прочитать здесь .

...