Может быть вы слышали про игру "Жизнь"? Это так называемый клеточный автомат, бесконечная или конечная клеточная доска, где каждая клетка может в момент времени находиться в одном из двух состояний - живая или мертвая (черная или белая).
Распределение живых клеток в начале игры называется первым поколением. Каждое следующее поколение рассчитывается на основе предыдущего по таким правилам:
- в пустой (мёртвой) клетке, рядом с которой ровно три живые клетки, зарождается жизнь;
- если у живой клетки есть две или три живые соседки, то эта клетка продолжает жить;
- в противном случае, если соседей меньше двух или больше трёх, клетка умирает («от одиночества» или «от перенаселённости»)
Подробнее можно прочитать в Википедии: https://ru.wikipedia.org/wiki/Игра_«Жизнь»
Сначала будет немного формул и описания, а затем два видео.
Реализуем в эксель
Жизнь соперничает с Doom, по тому где только ее не реализовывали. У нас канал про Эксель и гугл-таблицы, поэтому мы реализуем жизнь в Excel.
Первым шагом мы поменяем ширину всех колонок, так чтобы она равнялась высоте строк.
Посмотрим, расчерченная на клетки доска (два измерения) - есть. Как бы нам сделать третье измерение - время? Есть идея - если доска ограничена по вертикали, например 40 строк, то ячейки с 41 строки до 80 будут вторым моментом времени, с 81 по 120 - третьим моментом и так далее.
Есть идея еще лучше - выделим ячейку A1 и нажмем кнопку Page Down - куда нас перенесло? В моей версии эксель (вроде как это зависит и от масштаба, размера экрана и т.д.), меня перенесло в ячейку A58. Зададим размеры доски в Life по вертикали в 57 строк, тогда следующие 57 строк можно определить как вторая генерация, еще следующие - третья генерация. А перемещаться по генерациям будет легко с помощью кнопок Page Down / Page Up. Ну, и давайте, для определенности, считать что по горизонтали 70 колонок. Запишем тогда формулы для вычисления последующих поколений (эту формулу протянем по всем ячейкам начиная с A58 до BR<57*желаемое количество поколений>.
Алгоритм
Сначала напомним правила и запишем их в немного более понятном для алгоритмизации виде:
- Клетка живая, если она отмечена цветом. Будем считать это 1, а если мертвая - то 0. Предыдущее поколение P отстоит от текущей ячейки на 57 клеток вверх.
- Окружение клетки задается полностью суммой S всех ячеек вокруг нее.
- Если S = 3, то в текущей ячейке поставим 1 (есть жизнь).
- Если S = 2, то в значение текущей ячейки должно быть равно значению P.
- Во всех иных случаях значение текущей ячейки будет ноль.
Такие правила легко реализовать. Осталось, пожалуй, только разобраться с граничными случаями - первые и последние строки и столбцы нашей доски. Очевидно, что в граничных случаях окружение ячейки будет не 8 клеток, а 5 или даже всего 3 клетки.
Запишем сначала упрощенную формулу:
=ПЕРЕКЛЮЧ(<S>; 2; <P>; 3; 1; 0)
=SWITCH(<S>; 2; <P>; 3; 1; 0)
Для формулы в ячейке A58 значение P будет - значение ячейки A1, а когда мы протянем эту формулу на соседние ячейки, это значение поменяется соответственно. Нам нужно только подобрать формулу, описывающую S.
Формулы
Мы будем использовать функции:
- СМЕЩ (OFFSET) для ссылки на массив ячеек, окружающий P, включая саму P;
- функции СТРОКА (ROW) и СТОЛБЕЦ (COLUMN) для получения номера строки и столбца;
- функцию ОСТАТ (MOD) для вычисления остатка от деления - если остаток от деления номера строки на 57 равен нулю - это последняя строка доски. Если равен 1 - это первая строка доски. С столбцами аналогично;
- Наконец, функцию ЕСЛИМН (IFS) и функцию И (AND) для разбора всех возможных ситуаций с окружением нашей клетки.
S = СУМ(ЕСЛИМН((И(ОСТАТ(СТРОКА();57)>1;СТОЛБЕЦ()>1;СТОЛБЕЦ()<70);СМЕЩ(A1;-1;-1;3;3); И(ОСТАТ(СТРОКА();57)=1;СТОЛБЕЦ()>1;СТОЛБЕЦ()<70);СМЕЩ(A1;0;-1;2;3); И(ОСТАТ(СТРОКА();57)=0;СТОЛБЕЦ()>1;СТОЛБЕЦ()<70);СМЕЩET(A1;-1;-1;2;3); И(ОСТАТ(СТРОКА();57)>1;СТОЛБЕЦ()=1);СМЕЩ(A1;-1;0;3;2); И(ОСТАТ(СТРОКА();57)>1;СТОЛБЕЦ()=70);СМЕЩ(A1;-1;-1;3;2); И(ОСТАТ(СТРОКА();57)=1;СТОЛБЕЦ()=1);СМЕЩ(A1;0;0;2;2); И(ОСТАТ(СТРОКА();57)=0;СТОЛБЕЦ()=1);СМЕЩ(A1;-1;0;2;2); И(ОСТАТ(СТРОКА();57)=1;СТОЛБЕЦ()=70);СМЕЩ(A1;0;-1;2;2); И(ОСТАТ(СТРОКА();57)=0;СТОЛБЕЦ()=70);СМЕЩ(A1;-1;-1;2;2)))
S = SUM(IFS(AND(MOD(ROW();57)>1;COLUMN()>1;COLUMN()<70);OFFSET(A1;-1;-1;3;3); AND(MOD(ROW();57)=1;COLUMN()>1;COLUMN()<70);OFFSET(A1;0;-1;2;3); AND(MOD(ROW();57)=0;COLUMN()>1;COLUMN()<70);OFFSET(A1;-1;-1;2;3); AND(MOD(ROW();57)>1;COLUMN()=1);OFFSET(A1;-1;0;3;2); AND(MOD(ROW();57)>1;COLUMN()=70);OFFSET(A1;-1;-1;3;2); AND(MOD(ROW();57)=1;COLUMN()=1);OFFSET(A1;0;0;2;2); AND(MOD(ROW();57)=0;COLUMN()=1);OFFSET(A1;-1;0;2;2); AND(MOD(ROW();57)=1;COLUMN()=70);OFFSET(A1;0;-1;2;2); AND(MOD(ROW();57)=0;COLUMN()=70);OFFSET(A1;-1;-1;2;2)))
Аж зубы заболели 😂
Теперь совместим обе формулы и протянем их до конца нашей таблицы. Все, мы запрограммировали жизнь.
Ах, да, нолики и единички... Мы же не компьютеры. Сделаем нагляднее!
Шаг 1. Условное форматирование. Выделяем всю таблицу и задаем условное форматирование, если значение равно единице, то сделать заливку черным цветом (или какой вам больше по душе).
Так уже намного лучше. Теперь нужно убрать нолики и единички.
Снова выделяем всю таблицу и жмем Ctrl+1 или вот эту ма-аа-аленькую стрелочку
Выбираем пользовательский формат данных (Custom) и в строке где написано Основной (General) вбиваем три точки-запятой: ";;;"
Кстати, если не читали еще, посмотрите мою статью про пользовательские форматы данных. Там много полезного.
Точка-запятые разделяют форматы для положительных чисел, отрицательных чисел, нуля и текста. А, так как, кроме точек-запятой у нас в формате ничего нет, то и отображаться ничего не будет.
Я проставил на стартовом поле единички и задал таким образом несколько известных фигур для Life (посмотрите в википедии!)
Теперь, нажимая Page Down можно посмотреть развитие "жизни". Смотрите видео, что получилось:
Также прикладываю итоговый файл. Если у вас по нажатию Page Down скроллится не 57 строк - попробуйте поменять масштаб, свернуть "ленту". Ну или отредактировать формулы.
И для послевкусия, хотел поделиться видео с ютуба про игру "жизнь" - можно смело мотать на 1:10, если не хотите прочитать дополнительно на английском про "Жизнь". В видео можно посмотреть популярные фигуры и интересные эффекты.