Количество разрешенных предыдущих ходов в игре «Жизнь»

Учитывая текущий тик игры в игре жизни Конвея (или любой другой игре с сотовой автоматизацией), как можно найти количество легальных предыдущих тиков, которые можно было бы оценить в предоставленном тике?

Например, предполагая, что игра жизни может быть представлена ​​как:

0 0 0 0 0 ...
X 0 X 0 0 ...
0 X 0 0 0 ...
0 0 0 0 X ...
...

где X — «активен/включен/истинен», а 0 — «мертв/выключен/ложь», или, проще говоря, как boolean[][], как можно решить следующее:

public static int numberOfValidPreviousTicks(boolean[][] current) {
    return -1; // return answer
}

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

Однако должны быть какие-то очевидные способы ускорить этот процесс, чтобы он не был O(2^n) (где n — общее количество ячеек в сетке).

Кэширование, конечно, может помочь в некоторых местах, но где именно оно подходит?

Любая помощь будет оценена


person Joe Swanson    schedule 25.01.2017    source источник
comment
en.wikipedia.org/wiki/Garden_of_Eden_(cellular_automaton)   -  person Josh Lee    schedule 25.01.2017
comment
Я предполагаю, что эта проблема NP-Complete. Жизнь полна по Тьюрингу, поэтому алгоритм перемотки очень близок к поиску входных данных, которые заставляют программу возвращать истину. Посмотрите, сможете ли вы найти сокращение до 3-SAT или что-то в этом роде.   -  person Craig Gidney    schedule 25.01.2017
comment
@CraigGidney: я думаю, ты прав. Я ожидаю, что, как и во многих NP-полных задачах, большинство случайных наборов входных данных будут поддаваться решениям с полиномиальным временем, но если P = NP, никакой подход с полиномиальным временем не будет работать для всех входных данных.   -  person supercat    schedule 25.01.2017


Ответы (1)


Для платы m*m вы можете сделать это в O(m*8^m) с помощью динамического программирования.

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

Это лучше, чем 2^O(n) = 2^(O(m*m)), но довольно медленно.

Не думаю, что у тебя получится намного лучше.

person btilly    schedule 25.01.2017