Реализуйте игру жизни в 3D

17

Задача состоит в том, чтобы найти самую короткую реализацию игры жизни в 3D ( пример ). Это правила:

Клетки (в данном случае, кубики), имеющие только 1 или менее соседей, погибают, как будто от одиночества.
Если ровно 5 клеток окружают пустую клетку, они размножаются и заполняют ее.
Если ячейка имеет 8 или более соседей, она умирает от переполненности.

Сделайте это по крайней мере 10x10x10, где слои выводятся индивидуально, как это:

0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 X 0 0 X 0 0 0 0 0
0 0 X X X 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0

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

Самый короткий код в символах выигрывает!

Я сделал свою собственную реализацию этого для любого (кубического) размера: http://jensrenders.site88.net/life3D.htm Вы можете использовать это для тестирования, и вы можете основывать свой код на моем, хотя я не комментировал это ,

Йенс Рендерс
источник
1
Подразумевается, что тег code-golf из вашего утверждения найдет самую короткую реализацию . Пожалуйста, проверьте, если это то, что вы хотите. Вы должны также дать некоторые подробности о том, как вводить, сколько циклов, анимации да / нет, ... потому что для кода-гольфа важно иметь надежную спецификацию.
Говард
@Howard Я добавил еще несколько спецификаций и, да, забыл тег code-golf;) спасибо за это.
Jens Renders
@PeterTaylor Да, ровно 5, я его отредактирую.
Jens Renders
Я бы добавил детали о формате вывода (например, каждая ячейка должна быть разделена пробелом, как в вашем примере, одна новая строка между каждым слоем сетки вывода, живая и мертвая ячейки должны быть представлены разными символами, и это должны быть видимые символы .) Кроме того, имейте в виду, что если оформить код-гольф, вы вряд ли получите графическое моделирование.
Джонатан Ван Матр
Вы действительно хотели запретить все лазейки, обсуждаемые в этой мета-ветке, или только те, которые удовлетворяют (не) критериям одобрения (+5 баллов, как минимум вдвое больше голосов против голосов)? Потому что я уверен , что я мог полностью придумать некоторые довольно интересные «лазейки» , чтобы обсудить ... ;-)
Илмари Karonen

Ответы:

14

Mathematica - 120 байт

g=CellularAutomaton[{(l=Flatten@#;c=l[[14]];n=Total@Drop[l,{14}];Which[n<2||n>7,0,n==5||c==1,1,0<1,0])&,{},{1,1,1}},##]&

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

animateGol3d[size_, i_, n_] := 
  ListAnimate[
    Graphics3D[
      Cuboid /@ Position[#, 1], 
      PlotRange -> {{0, size}, {0, size}, {0, size}} + 1
    ] & /@ g[i, n]
  ];

И после экспериментов с кучей начальных условий, я получил такие вещи:

введите описание изображения здесь

И вот один с размером сетки 20x20x20. Для моделирования и рендеринга потребовалось несколько секунд:

введите описание изображения здесь

Кстати, это предполагает периодические граничные условия.

Мартин Эндер
источник
Те, кто действительно входит в состояние равновесия, или это просто остановка анимации? Если первое, вы дали мне несколько
интересных
1
@Kroltan Это было давно, но я почти уверен, что они достигли равновесия.
Мартин Эндер
1
Здорово спасибо Отдельные кусочки равновесия выглядят очень по-комнатному, например, как румяна.
Kroltan
12

APL, 46

Это заняло у меня некоторое время, но я сократил его до 46 символов:

{(5=m)∨⍵∧3>|5.5-m←⊃+/,i∘.⌽i∘.⊖(i←2-⍳3)⌽[2]¨⊂⍵}

Это функция, которая принимает булеву трехмерную матрицу любого размера и вычисляет следующее поколение в соответствии с заданными правилами. Граничные условия не были указаны, поэтому я выбрал обтекание с другой стороны, как в тороидальном пространстве.

объяснение

{                           ⊂⍵}   Take the argument matrix and enclose it in a scalar
               (i←2-⍳3)           Prepare an array with values -1 0 1 and call it i
                       ⌽[2]¨      Shift the matrix along the 2nd dim. by each of -1 0 1
           i∘.⊖                   Then for each result do the same along the 1st dimension
       i∘.⌽                       And for each result again along the 3rd dimension
 m←⊃+/,                           Sum element-wise all 27 shifted matrices and call it m

Промежуточный результат mпредставляет собой матрицу с той же формой, что и исходная матрица, которая подсчитывает для каждого элемента, сколько клеток живет в его окрестности 3 × 3 × 3, включая себя. Потом:

           |5.5-m   For each element (x) in m, take its distance from 5.5
       ⍵∧3>         If that distance is <3 (which means 3≤x≤8) and the original cell was 1,
 (5=m)∨             or if the element of m is 5, then the next generation cell will be 1.

пример

Определить случайную матрицу 4 × 4 × 4 с примерно 1/3 ячейки = 1 и вычислить ее 1-го и 2-го поколения. ⊂[2 3]На фронте это просто уловка , чтобы напечатать плоскости горизонтально , а не вертикально:

      ⊂[2 3] m←1=?4 4 4⍴3
 1 0 0 0  1 0 1 0  1 0 1 0  0 0 0 1 
 1 1 0 0  0 0 0 0  0 0 0 1  1 0 1 0 
 0 0 0 0  0 1 0 0  0 0 0 0  0 0 1 0 
 1 1 0 0  0 0 0 1  1 0 0 1  0 0 1 0 
      ⊂[2 3] {(5=m)∨⍵∧3>|5.5-m←⊃+/,i∘.⌽i∘.⊖(i←2-⍳3)⌽[2]¨⊂⍵} m
 0 0 0 0  0 0 1 0  1 0 1 0  0 0 0 0 
 1 0 0 0  0 0 1 0  0 0 0 0  1 0 1 0 
 0 0 0 0  0 1 0 0  0 0 0 0  0 0 1 0 
 1 1 0 0  0 0 0 0  1 0 0 0  0 0 1 0 
      ⊂[2 3] {(5=m)∨⍵∧3>|5.5-m←⊃+/,i∘.⌽i∘.⊖(i←2-⍳3)⌽[2]¨⊂⍵}⍣2⊢ m
 0 0 1 0  1 0 1 0  1 0 1 0  0 0 0 0 
 1 0 1 0  0 0 1 1  0 0 0 0  1 0 1 0 
 1 0 0 0  1 1 0 0  0 0 1 0  1 0 1 0 
 1 1 1 0  1 0 0 1  1 0 1 0  0 0 1 0 
Тобия
источник
+1 Очень хороший ответ! и действительно, границы не были определены, так что обтекание допускается.
Jens Renders
9

J - 42 символа

Мы предполагаем, что тороидальная доска (оборачивается) во всех трех измерениях. Автоматическое отображение результатов J, по-видимому, соответствует спецификации вывода, используя 1для живых клеток и 0для мертвых. Этот код работает на досках любой ширины, длины и высоты (может быть 10x10x10, 4x5x6 и т. Д.).

(((1&<*<&8)@-*]+.5=-)~[:+/(,{3#<i:1)|.&><)

Объяснение следующее:

  • ,{3#<i:1 - Субэкспресс списка смещений для ячейки и всех ее соседей.
    • <i:1 - Список целых чисел от 1 до -1 включительно.
    • ,{3#- Сделайте три копии списка ( 3#) и возьмите декартово произведение ( ,{).
  • (,{3#<i:1)|.&><- Для каждого набора смещений 3D сдвиньте массив. По стоимости 3 -х символов, вы можете изменить , |.&>чтобы |.!.0&>не иметь наматывается вокруг.
  • [:+/ - Подведите все сдвинутые доски вместе.
  • ((1&<*<&8)@-*]+.5=-)~- Длинный внешний глагол был крюком, поэтому он получал доску слева и справа, а сторону справа мы сдвигали и суммировали. В ~свопы это вокруг для этого внутреннего глагола.
    • 5=- - 1 в каждой ячейке, что сумма сдвинутых досок минус исходная доска (то есть число соседей) равна 5, и 0 во всех остальных.
    • ]+. - Логическое ИЛИ выше с оригинальной платой.
    • (1&<*<&8) - 1, если число сравнивается между 1 и 8, исключая, 0 в противном случае.
    • (1&<*<&8)@-* - Сравните (как указано выше) количество соседей и умножьте (т. Е. Логическое И, когда домен только 1 или 0) на результат логического ИЛИ.

Использование аналогично APL, просто примените функцию к начальной плате для каждого шага. У J есть оператор функциональной мощности, ^:чтобы сделать это легко.

   life =: (((1&<*<&8)@-*]+.5=-)~[:+/(,{3#<i:1)|.&><)  NB. for convenience
   board =: 1 = ?. 4 4 4 $ 4  NB. "random" 4x4x4 board with approx 1/4 ones
   <"2 board  NB. we box each 2D plane for easier viewing
+-------+-------+-------+-------+
|0 0 0 0|1 1 0 0|0 1 0 0|0 0 1 0|
|0 1 0 0|0 0 0 0|0 0 0 1|1 0 0 0|
|0 0 0 0|0 0 1 0|0 1 0 0|0 0 0 1|
|1 1 0 0|1 0 0 0|0 0 0 1|0 1 1 0|
+-------+-------+-------+-------+
   <"2 life board
+-------+-------+-------+-------+
|0 0 0 0|0 1 0 1|0 1 0 0|0 0 1 0|
|1 1 1 1|0 0 0 0|0 0 0 1|1 1 0 0|
|0 0 0 0|0 0 1 1|0 1 0 0|0 0 0 1|
|1 0 0 0|1 0 0 1|0 0 0 1|0 1 1 1|
+-------+-------+-------+-------+
   <"2 life^:2 board  NB. two steps
+-------+-------+-------+-------+
|0 0 0 0|0 1 0 0|0 1 0 0|0 0 0 0|
|0 1 0 0|0 0 0 0|0 0 0 1|0 1 0 0|
|0 0 0 0|0 0 0 0|0 1 0 0|0 0 0 0|
|0 0 0 0|0 0 0 1|0 0 0 0|0 1 1 1|
+-------+-------+-------+-------+
   <"2 life^:3 board  NB. etc
+-------+-------+-------+-------+
|0 1 0 0|1 1 1 0|0 1 0 0|0 1 0 0|
|0 1 0 0|1 0 1 0|1 0 1 0|1 1 1 0|
|1 0 0 0|0 0 0 0|0 1 0 0|0 1 0 0|
|0 0 1 0|0 0 0 0|0 1 0 0|0 1 1 0|
+-------+-------+-------+-------+

Я говорю «случайный», потому что ?.примитив дает воспроизводимые случайные результаты, каждый раз используя фиксированное начальное число. ?это настоящий RNG.

algorithmshark
источник
Проклятие J и его грязный |.глагол !! Молодец.
Tobia