Crab & ChatGPT
Crab Crab
Я тут уже полчаса на судоку смотрю, пытаюсь сократить количество переборов. Может, ты про constraint propagation или более умный порядок переменных что-нибудь пробовала, чтобы ускорить вычисления?
ChatGPT ChatGPT
Привет! Отличная идея с откатом — эти вызовы реально убивают производительность. Начни, пожалуй, с добавления классического слоя прямой проверки: как только ты устанавливаешь число, сразу удаляй его из списка кандидатов у всех остальных. Это, по сути, простейшая форма распространения ограничений. Дальше, забудь про свой наивный порядок слева направо — переходи на MRV (minimum remaining values): выбирай ячейку с наименьшим количеством оставшихся возможных цифр. Обычно именно там и возникают пробки. Если и дальше натыкаешься на проблемы, попробуй использовать эвристику степени: среди ячеек MRV выбирай ту, что наиболее связана с другими нерешёнными ячейками. Сочетание MRV и эвристики степени даёт более сильный выбор "наиболее ограниченной" ячейки. И не забудь про обрезку, специфичную для домена: для сетки 9x9 приёмы вроде "X-wing" или "Swordfish" могут устранить варианты ещё до того, как ты начнешь откатывать. Добавь эти приёмы, и существенно уменьшишь количество вызовов. Попробуй — скажи, помогло или сетка всё равно устраивает истерику.
Crab Crab
Отличные предложения, спасибо. Добавлю forward-checking и переключусь на MRV с разрешением по степени приоритета. Если появятся X-wing или Swordfish, добавлю их в следующий раз. Сообщу, сколько вызовов будет после изменений.
ChatGPT ChatGPT
Звучит здорово – проверка вперёд – это самое простое, а MRV с привязкой к степени обычно попадает прямо в точку. Сообщи новый лимит вызовов, я буду замерять время, ожидая этого падения. Удачи!
Crab Crab
Запускаю обновлённый решатель, засеку кол-во вызовов и сообщу, как будут цифры. Спасибо за подсказки.
ChatGPT ChatGPT
Поняла, давай цифры, когда будешь готова. Удачи!
Crab Crab
Запустила на стандартной головоломке 9x9. Простой перебор сделал около двух с половиной миллионов рекурсивных вызовов. С проверкой вперёд и эвристиками MRV/степени, это упало примерно до полутора миллионов — снижение на 45 процентов. Если ты тестируешь на более сложной сетке, разница будет ещё заметнее. Скажи, если понадобится подробнее разобраться.
ChatGPT ChatGPT
Отличный результат – почти половину вызовов отсечь – это впечатляет! Если захочешь копнуть глубже, расскажи, какие эвристики ты сначала применила или как дерево поиска изменилось. Или, если тебе интересно добавить ещё более жёсткую обрезку, например, как в X‑wing или Swordfish, можем вместе поразмышляем, как это поможет ещё сильнее сократить дерево. Просто дай знать!
Crab Crab
Привет, как дела? Я начала с проверки допустимости, чтобы сразу отсеивать заведомо неверные варианты, как только число ставится на место. Это сократило глубину дерева на несколько уровней и убрало массу ветвей в самом начале. Потом я поменяла порядок переменных с левого направо на MRV – и это сразу же уменьшило коэффициент ветвления, потому что сначала заполнялись самые ограниченные ячейки. Когда MRV выдавал ничью, я использовала эвристику степени, выбирая ячейку, которая влияет на большее количество пустых ячеек – это сэкономило ещё 5-10 процентов вызовов. Дерево отката после этих двух шагов стало гораздо уже и мельче, и многие глубокие рекурсивные пути были устранены вовсе. Если хочешь посмотреть точное количество вызовов для каждого шага эвристики или схемы деревьев – дай знать. Могу и набросать, как добавление X-wing или Swordfish помогло бы сократить список кандидатов до того, как начнется откат.
ChatGPT ChatGPT
Отлично разобрала—кажется, ты превращаешь этот хаос в аккуратную бонсайку. Если тебе нужны точные цифры по каждому этапу, я могу быстро набросать табличку или даже выдать фрагмент трассировки рекурсии. Или, если готова подключать X‑wing и Swordfish, просто скажи, какие паттерны хотим прицельно обрабатывать в первую очередь, и я покажу, как подрезать эти наборы кандидатов до того, как начнётся перебор.
Crab Crab
Начнём с X-wing. Сначала реализую детектор шаблонов для строк, потом перейдём к столбцам. Если это сработает, тогда возьмёмся за Swordfish. Не стесняйся скидывать трейс или любые фрагменты кода, которые мне понадобятся для интеграции.
ChatGPT ChatGPT
Привет! Вот простой детектор «истребителя X», который ты можешь добавить в свой решатель. Он перебирает пары строк, выделяет столбцы, где может стоять цифра, и проверяет, есть ли ровно два таких столбца для конкретной цифры в обеих строках. Если есть, то ты можешь убрать эту цифру из этих двух столбцов в остальных строках. Сначала покажу версию для строк; когда разберешься, просто переверни логику на столбцы. ```def xwing_rows(board, candidates): # board is 9x9 list of ints (0 for empty) # candidates is a 9x9 list of sets of possible digits for each cell for d in range(1, 10): rows_with_two = [] for r in range(9): cols = [c for c in range(9) if d in candidates[r][c]] if len(cols) == 2: rows_with_two.append((r, cols)) # now look for pairs of rows that share the same two columns for i in range(len(rows_with_two)): r1, cols1 = rows_with_two[i] for j in range(i + 1, len(rows_with_two)): r2, cols2 = rows_with_two[j] if cols1 == cols2: c1, c2 = cols1 # strip digit d from all other rows in these two columns for r in range(9): if r != r1 and r != r2: if d in candidates[r][c1]: candidates[r][c1].remove(d) # you might also want to push a callback to update the board if you keep it in sync if d in candidates[r][c2]: candidates[r][c2].remove(d) ``` Несколько важных моментов: 1. **Следи за кандидатскими множествами**: Каждый раз, когда ты ставишь цифру, нужно сразу удалять её из соответствующей строки, столбца и блока. Этот код для "истребителя X" предполагает, что множества актуальны. 2. **Запускай очистку**: После запуска `xwing_rows` можно пройтись по доске ещё раз и заполнить те клетки, в которых теперь только один кандидат. Это классический шаг "распространения одиночных значений". 3. **Совет по производительности**: Двойной цикл для пар строк — это не затратно (максимум 81 итерация). Основная работа уже выполняется при проверке допустимости, ты просто добавляешь поверх фильтр. Как только версия для строк будет работать, версия для столбцов — это просто транспонирование: меняй местами `r` и `c` везде, и всё будет хорошо. Если возникнут проблемы или захочешь увидеть более компактную версию, которая возвращает список принудительных удалений, дай знать. Приятного "подрезания"!