Найкоротша гра життя


59

Гра життя Конуея - класичний приклад клітинної автоматизації. Клітини утворюють квадратну сітку і кожен має два стани: живий або мертвий. На кожному кроці кожна клітинка одночасно оновлюється відповідно до свого стану та стану восьми сусідів:

  • Жива клітина залишається живою, якщо вона має рівно двох-трьох живих сусідів
  • Мертва клітина стає живою, якщо в ній рівно три живі сусіди

Якщо ви вирішите прийняти це, ваша місія полягає в тому, щоб кодувати найкоротшу реалізацію Game of Life улюбленою мовою.

Правила:

  • Сітка повинна бути не менше 20х20
  • Сітка повинна обертатися навколо (так, сітка схожа на поверхню Тору)
  • Ваша реалізація повинна дозволяти користувачеві вводити власні стартові схеми
  • GoL трохи безглуздий, якщо ви не бачите, що відбувається, тому повинен бути візуальний вихід автоматичного запуску, при цьому результат кожного повороту відображається досить довго, щоб його можна було побачити!

8
Раніше на стеку Overflow: Code Golf: Гра життя Конуей , і обов’язково дивіться посилання на реалізацію APL у коментарях.
dmckee

1
Ах, я цього не бачив. Але це дещо інакше ні (врятуйте мене, щоб видалити роботу, яка склала виклик разом?
Гриффін

6
Це не проблема. Багато головоломок, які вже виконуються на Stack Overflow, також були зроблені тут, але люди скажуть вам, що я нав'язливо ставлюсь до подібних викликів.
dmckee

@Griffin: Ви можете видалити всі ті, хто ;раніше, ніж }s. Також vars може бути усунено часом (якщо він не порушує ваш код). А для одного рядка forз, ifs і т.д., ви можете усунути { }повністю: for(...) for(...) dosomething().
pimvdb

@pimvdb, ура, я ще не повністю грав у нього, не мав часу. просто хотів показати, що я теж ходив, а не склав руки. Скоро буде гольф на максимум.
Гріффін

Відповіді:


27

Полотно HTML5 з JavaScript, 940 639 586 519 символів

<html><body onload="k=40;g=10;b=[];setInterval(function(){c=[];for(y=k*k;y--;){n=0;for(f=9;f--;)n+=b[(~~(y/k)+k+f%3-1)%k*k+(y+k+~~(f/3)-1)%k];c[y]=n==3||n-b[y]==3;r.fillStyle=b[y]?'red':'tan';r.fillRect(y%k*g,~~(y/k)*g,g-1,g-1)}if(v.nextSibling.checked)b=c},1);v=document.body.firstChild;v.width=v.height=g*k;v.addEventListener('click',function(e){b[~~((e.pageY-v.offsetTop)/g)*k+~~((e.pageX-v.offsetLeft)/g)]^=1},0);r=v.getContext('2d');for(y=k*k;y--;)b[y]=0"><canvas></canvas><input type="checkbox"/>Run</body></html>

Я завжди хотів щось зробити з полотном, тому ось моя спроба (оригінальна версія в Інтернеті ). Ви можете переключити клітинки, натиснувши (також можливо в запущеному режимі).

Тепер ви також можете спробувати нову версію тут .

На жаль, є проблема, над якою я ще не міг обійтись. Інтернет-версія на 11 символів довша, оскільки jsFiddle ставить текстовий вузол безпосередньо перед полотном (чому?), І таким чином полотно вже не є першою дочірньою.

Правка 1: Багато оптимізацій та реструктуризації.

Редагувати 2: Кілька менших змін.

Редагування 3: Накреслений повний блок сценарію плюс незначні зміни.


Приємно, але зміна інтервалу затримки 1зробить його таким же швидким, як і моє, а не повільним кроком. Крім того, якщо ви хочете реалізувати малювання (а не клацання на кожному квадраті), ви можете округлити положення миші до найближчого розміру і заповнити прямокутник у цій точці. Більше символів, але більше очок.
Гриффін

Ви можете замінити new Array('#FFF','#800')на ['#FFF','#800'].
Lowjacker

Хоча кажучи, що щодо малювання, мій супер-гольф не дозволяє малювати і некрасивий, як гріх. Ха-ха. Ви можете встановити два кольори в sмасиві tanі, redоскільки вони є двома кольорами з найкоротшими поданнями - економить два символи. Також, якщо можливо, введіть jв інтервал буквальну версію . Я впевнений, що ще багато чого можна видавити.
Гріффін

@Griffin та Lowjacker: велике спасибі Я також впевнений, що ви можете гольфувати це набагато більше (і вже маєте кілька ідей). На жаль, я не знайшов часу для цього. Краща версія для гольфу відбудеться завтра - я сподіваюся ...
Говард

2
Ви можете видалити html та теги body. Він буде функціонувати так само
arodebaugh

32

Пітон, 219 символів

Я пішов на максимальний гольф, маючи достатньо інтерфейсу, щоб задовольнити питання.

import time
P=input()
N=range(20)
while 1:
 for i in N:print''.join(' *'[i*20+j in P]for j in N)
 time.sleep(.1);Q=[(p+d)%400 for d in(-21,-20,-19,-1,1,19,20,21)for p in P];P=set(p for p in Q if 2-(p in P)<Q.count(p)<4)

Ви запускаєте його так:

echo "[8,29,47,48,49]" | ./life.py

Числа у списку представляють координати вихідних комірок. Перший ряд - 0-19, другий ряд - 20-39 тощо.

Запустіть його в терміналі з 21 рядом, і це виглядає досить запаморочливо.


1
Це повністю повинно було виграти. Я думаю, що «простота введення» була зважена досить високою.
прим

@primo Я б навіть зайшов, щоб припустити, що мама повинна мати окрему конкуренцію.
luser droog

2
Так це життя Пі тоді?
Крістофер Вірт

Ви завжди можете зберегти ще один char ... 2-(p in P)== 2-({p}<P). Але тоді вам доведеться змінити свої дані на {8,29,47,48,49}:)
JBernardo

21

TI-BASIC, 96 байт (87 для неконкурентного вступу)

Для вашого графічного калькулятора серії TI-84 (!). Це було досить складною задачею, так як не існує простий спосіб , щоб написати буферну графічну рутину (безумовно нічого не вбудоване), і на екрані графіка має команди тільки чотири відповідних графічні: Pxl-On(), Pxl-Off(), Pxl-Change(), і pxl-Test().

Використовує кожен доступний піксель на екрані та правильно перегортає його. Кожна комірка має один піксель, і програма оновлює лінію за рядком по горизонталі праворуч по екрану. Оскільки у калькуляторів є лише 15 МГц процесор z80, а BASIC - мова повільно інтерпретована, код отримує лише один кадр кожні п’ять хвилин.

Введення користувача легко: перед запуском програми використовуйте інструмент «Перо», щоб намалювати свою фігуру на екрані графіка.

Адаптований під час мого вступу на змагання з кодового гольфу на форумі калькуляторів Omnimaga .

0
While 1
For(X,0,94
Ans/7+49seq(pxl-Test(remainder(Y,63),remainder(X+1,95)),Y,62,123
For(Y,0,62
If 1=pxl-Test(Y,X)+int(3fPart(3cosh(fPart(6ֿ¹iPart(sum(Ans,Y+1,Y+3
Pxl-Change(Y,X
End
End
End

Версія Omnimaga (87 байт)

Цей код має додаткову функцію: він виявляє, чи він запускається вперше, і якщо рандомізує стан екрана. У наступних запусках воно автоматично продовжує моделювання, якщо його зупиняють після завершення кадру. Однак це не конкуруючий запис, оскільки він не обертає екран; комірки на зовнішній межі завжди вважатимуться мертвими, якщо заздалегідь очистити екран графіків.

0
While 1
For(X,0,93
Ans/7+49seq(pxl-Test(Y,X+1),Y,0,62
For(Y,1,61
If 2rand>isClockOn=pxl-Test(Y,X)+int(3fPart(3cosh(fPart(6ֿ¹iPart(sum(Ans,Y,Y+2
Pxl-Change(Y,X
End
End
ClockOff
End

Ця версія, мабуть, самий гольф-код, який я коли-небудь писав, і містить кілька справді неприємних обманливих оптимізацій:

  • Я використовую стан годинника як прапор. На початку програми ввімкнено годинник дати / часу, і я використовую значення глобального прапора isClockOn, щоб визначити, чи є це першою ітерацією. Після того, як намальовано перший кадр, я вимикаю годинник. Економить один байт за найкоротшим іншим методом і близько чотирьох за очевидний метод.

  • Я зберігаю стани трьох стовпців поруч із тим, що оновлюється, у 63-елементному масиві чисел base-7. 49 місце займає стовпчик праворуч, 7 місце займає середній стовпчик, а одиничне місце займає лівий стовпчик - 1 для живої комірки і 0 для мертвої комірки. Тоді я беру решту мод 6 суми трьох чисел навколо модифікованої комірки, щоб знайти загальну кількість живих сусідніх клітин (це подібно поділу на 9 трюків - у базі 7, решта мод 6 дорівнює сумі цифри). Економить близько 10 байт самостійно і дає можливість використовувати наступні дві оптимізації. Приклад діаграми (скажімо, у певному стовпчику Y = 45 розміщено планер:

    Row # | Cell State       | Stored number | Mod 6 = cell count
    ...
    44      Live, Live, Live   49+7+1 = 57     3
    45      Dead, Dead, Live   49+0+0 = 49     1
    46      Dead, Live, Dead   0+7+0  = 7      1
    ...
    

    Центральна клітина залишиться мертвою, оскільки вона оточена рівно п’ятьма живими клітинами.

  • Після завершення кожного рядка номери в масиві оновлюються шляхом ділення існуючих чисел на 7, відкидання десяткової частини та додавання 49-кратних значень комірок у новому стовпчику. Зберігання всіх трьох стовпців щоразу через було б набагато повільніше та менш елегантним, візьміть принаймні 20 байтів і використовуйте три списки, а не один, тому що значення осередків у кожному рядку повинні зберігатися до оновлення комірок. Це далеко не найменший спосіб зберігання позицій комірок.

  • Фрагмент int(3fPart(3cosh(дає, 1коли вхід дорівнює 3/6, 2коли він дорівнює 4/6, а 0коли дорівнює 0, 1/6, 2/6 або 5/6. Економить близько 6 байт.


19

Математика - 333

Особливості:

  • Інтерактивний інтерфейс: натисніть клітинки, щоб зробити свої шаблони

  • Приємна сітка

  • Кнопки: RUN, PAUSE, CLEAR

Код нижче.

Manipulate[x=Switch[run,1,x,2,CellularAutomaton[{224,{2,{{2,2,2},{2,1,2},{2,2,2}}},
{1,1}},x],3,Table[0,{k,40},{j,40}]];EventHandler[Dynamic[tds=Reverse[Transpose[x]];
ArrayPlot[tds,Mesh->True]],{"MouseClicked":>(pos=Ceiling[MousePosition["Graphics"]];
x=ReplacePart[x,pos->1-x[[Sequence@@pos]]];)}],{{run,3,""},{1->"||",2->">",3->"X"}}]

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

Якщо ви хочете зрозуміти, як це працює, другий приклад у цьому блозі - це лише більш досконала версія (живий аналіз Фур’є, кращий інтерфейс) наведеного вище коду. Приклад повинен працювати прямо у вашому браузері після завантаження безкоштовного плагіна.


2
+1, приємний за те, що ходив. Так, це проблема з цим сайтом, є тони старих питань, які, як правило, не пропускають.
Гриффін

@Griffin дякую за те, що його взагалі помітили;)
Віталій Кауров

15

C 1063 символи

Як завдання, я зробив це в C, використовуючи непривітний для гольфу API для роботи в режимі реального часу. Якщо увімкнено заглушку, моделювання запуститься. Він буде залишатися нерухомим, якщо вимкнено затиск. Намалюйте візерунки за допомогою миші; клацання лівою кнопкою миші відновлює клітини, а правою кнопкою миші вбиває клітини.

#include <windows.h>
#include<process.h>
#define K ][(x+80)%20+(y+80)%20*20]
#define H R.Event.MouseEvent.dwMousePosition
#define J R.Event.MouseEvent.dwButtonState
HANDLE Q,W;char*E[3],O;Y(x,y){return E[0 K;}U(x,y,l,v){E[l K=v;}I(){E[2]=E[1];E[1]=*E;*E=E[2];memset(E[1],0,400);}A(i,j,k,l,P){while(1){Sleep(16);for(i=0;i<20;++i)for(j=0;j<20;++j){COORD a={i,j};SetConsoleCursorPosition(Q,a);putchar(E[0][i+j*20]==1?'0':' ');}if(O){for(i=0;i<20;++i)for(j=0;j<20;++j){for(k=i-1,P=0;k<i+2;++k)for(l=j-1;l<j+2;++l){P+=Y(k,l);}U(i,j,1,P==3?1:Y(i,j)==1&&P==4?1:0);}I();}}}main(T,x,y,F,D){for(x=0;x<21;++x)puts("#####################");E[0]=malloc(800);E[1]=E[0]+400;I();I();W=GetStdHandle(-10);Q=GetStdHandle(-11);SetConsoleMode(W,24);INPUT_RECORD R;F=D=O=0;COORD size={80,25};SetConsoleScreenBufferSize(Q,size);_beginthread(A,99,0);while(1){ReadConsoleInput(W,&R,1,&T);switch(R.EventType){case 1:O=R.Event.KeyEvent.dwControlKeyState&128;break;case 2:switch(R.Event.MouseEvent.dwEventFlags){case 1:x=H.X;y=H.Y;case 0:F=J&1;D=J&2;}if(F)U(x,y,0,1);if(D)U(x,y,0,0);}}}

Складений EXE можна знайти тут

Редагувати: я прокоментував джерело. Він доступний тут


Я б хотів побачити коментовану версію цього!
luser droog

1
Звичайно, якщо я можу пригадати, що я думав ... = p
Каслай

1
@luserdroog Ось це pastebin.com/BrX6wgUj
Каслай

Це просто приголомшливо.
rayryeng

12

J (39 символів)

l=:[:+/(3 4=/[:+/(,/,"0/~i:1)|.])*.1,:]

На основі цієї версії APL (той же алгоритм, тороїдальна згортка).

Приклад використання:

   r =: (i.3 3) e. 1 2 3 5 8
   r
0 1 1          NB. A glider!
1 0 1
0 0 1

   R =: _1 _2 |. 5 7 {. r
   R
0 0 0 0 0 0 0  NB. Test board
0 0 0 1 1 0 0
0 0 1 0 1 0 0
0 0 0 0 1 0 0
0 0 0 0 0 0 0

   l R
0 0 0 0 0 0 0  NB. Single step
0 0 0 1 1 0 0
0 0 0 0 1 1 0
0 0 0 1 0 0 0
0 0 0 0 0 0 0

10

Математика, 123 символів

Дуже рудиментарна реалізація, яка не використовує вбудовану функцію CellularAutomaton в Mathematica.

ListAnimate@NestList[ImageFilter[If[3<=Total@Flatten@#<=3+#[[2]][[2]],1,0]&,#,1]&,Image[Round/@RandomReal[1,{200,200}]],99]

8

Ruby 1.9 + SDL (380 325 314)

EDIT : 314 символів, і виправлено помилку з додатковими клітинками, які з’являються живими під час першої ітерації. Збільшили розмір сітки до 56, оскільки рутовий колір має лише найнижчі 8 біт.

EDIT : Golfed до 325 символів. Ширина / висота сітки зараз становить 28, оскільки 28 * 9 є найбільшою, яку ви можете мати, використовуючи значення як колір тла. Він також обробляє лише одну подію SDL за ітерацію, яка повністю усуває внутрішній цикл. Дуже щільно я думаю!

Моделювання починається призупинено, коли всі клітини відмерли. Ви можете натиснути будь-яку клавішу, щоб увімкнути паузу / скасувати паузу, і клацніть будь-яку клітинку, щоб переключити її між живою та мертвою. Виконує ітерацію кожні десяту частину секунди.

Обгортання трохи химерне.

require'sdl'
SDL.init W=56
R=0..T=W*W
b=[]
s=SDL::Screen.open S=W*9,S,0,0
loop{r="#{e=SDL::Event.poll}"
r['yU']?$_^=1:r[?Q]?exit: r['nU']?b[e.y/9*W+e.x/9]^=1:0
b=R.map{|i|v=[~W,-W,-55,-1,1,55,W,57].select{|f|b[(i+f)%T]}.size;v==3||v==2&&b[i]}if$_
R.map{|i|s.fillRect i%W*9,i/W*9,9,9,[b[i]?0:S]*3}
s.flip
sleep 0.1}

Виглядає так:

Знімок екрана програми в дії

Веселий виклик! Я вітаю будь-які вдосконалення, які кожен може побачити.


Приємна спроба, але я відразу бачу, що ти помилився. Ви не можете мати такий зразок в GoL. Ще читайте правила: en.wikipedia.org/wiki/Conway%27s_Game_of_Life#Rules
Griffin

@Griffin Я думаю, що знімок екрана був зроблений після паузи та перемикання деяких комірок вручну - хоча я ще раз перевірю правила. Дякую!
Пол Престидж

7
@Griffin не може бути в будь-якій можливій конфігурації схемою насіння?
ardnew

7

Скала, 1181 1158 1128 1063 1018 1003 999 992 987 символів

import swing._
import event._
object L extends SimpleSwingApplication{import java.awt.event._
import javax.swing._
var(w,h,c,d,r)=(20,20,20,0,false)
var x=Array.fill(w,h)(0)
def n(y:Int,z:Int)=for(b<-z-1 to z+1;a<-y-1 to y+1 if(!(a==y&&b==z)))d+=x((a+w)%w)((b+h)%h)
def top=new MainFrame with ActionListener{preferredSize=new Dimension(500,500)
menuBar=new MenuBar{contents+=new Menu("C"){contents+={new MenuItem("Go/Stop"){listenTo(this)
reactions+={case ButtonClicked(c)=>r= !r}}}}}
contents=new Component{listenTo(mouse.clicks)
reactions+={case e:MouseClicked=>var p=e.point
x(p.x/c)(p.y/c)^=1
repaint}
override def paint(g:Graphics2D){for(j<-0 to h-1;i<-0 to w-1){var r=new Rectangle(i*c,j*c,c,c)
x(i)(j)match{case 0=>g draw r
case 1=>g fill r}}}}
def actionPerformed(e:ActionEvent){if(r){var t=x.map(_.clone)
for(j<-0 to h-1;i<-0 to w-1){d=0
n(i,j)
x(i)(j)match{case 0=>if(d==3)t(i)(j)=1
case 1=>if(d<2||d>3)t(i)(j)=0}}
x=t.map(_.clone)
repaint}}
val t=new Timer(200,this)
t.start}}

Безголівки:

import swing._
import event._

object Life extends SimpleSwingApplication
{
    import java.awt.event._
    import javax.swing._
    var(w,h,c,d,run)=(20,20,20,0,false)
    var x=Array.fill(w,h)(0)
    def n(y:Int,z:Int)=for(b<-z-1 to z+1;a<-y-1 to y+1 if(!(a==y&&b==z)))d+=x((a+w)%w)((b+h)%h)
    def top=new MainFrame with ActionListener
    {
        title="Life"
        preferredSize=new Dimension(500,500)
        menuBar=new MenuBar
        {
            contents+=new Menu("Control")
            {
                contents+={new MenuItem("Start/Stop")
                {
                    listenTo(this)
                    reactions+=
                    {
                        case ButtonClicked(c)=>run= !run
                    }
                }}
            }
        }
        contents=new Component
        {
            listenTo(mouse.clicks)
            reactions+=
            {
                case e:MouseClicked=>
                    var p=e.point
                    if(p.x<w*c)
                    {
                        x(p.x/c)(p.y/c)^=1
                        repaint
                    }
            }
            override def paint(g:Graphics2D)
            {
                for(j<-0 to h-1;i<-0 to w-1)
                {
                    var r=new Rectangle(i*c,j*c,c,c)
                    x(i)(j) match
                    {
                        case 0=>g draw r
                        case 1=>g fill r
                    }
                }
            }
        }
        def actionPerformed(e:ActionEvent)
        {
            if(run)
            {
                var t=x.map(_.clone)
                for(j<-0 to h-1;i<-0 to w-1)
                {
                    d=0
                    n(i,j)
                    x(i)(j) match
                    {
                        case 0=>if(d==3)t(i)(j)=1
                        case 1=>if(d<2||d>3)t(i)(j)=0
                    }
                }
                x=t.map(_.clone)
                repaint
            }
        }
        val timer=new Timer(200,this)
        timer.start
    }
}

Більшу частину коду тут складають GUI-файли Swing. Сама гра полягає в actionPerformedметоді, який запускається функцією Timerі помічником, nякий рахує сусідів.

Використання:

Скомпілюйте його, scalac filenameа потім запустіть scala L.
Клацання квадрата перевертає його з "живого" в "мертве", і опція меню запускає та зупиняє гру. Якщо ви хочете змінити розмір сітки, змініть перші три значення в рядку: var(w,h,c,d,r)=(20,20,20,0,false)вони відповідно ширини, висоти та розміру комірки (у пікселях).


Я знайшов 2 поліпшення в гольфі: import java.awt.event._і contents+=m("Go",true)+=m("Stop",false)}}, що призвело до 1093 символів.
користувач невідомий

@user невідомо Дякую Я знайшов декілька вдосконалень - до 1063 зараз.
Гарет

Чорт ти зайнятий. Тримай! Я буду тестувати відповіді, коли ще кілька людей опублікують їх.
Гриффін

7

Чистий баш, 244 байти

Працює в тороїдально укутаному всесвіті 36x24:

mapfile a
for e in {0..863};{
for i in {0..8};{
[ "${a[(e/36+i/3-1)%24]:(e+i%3-1)%36:1}" == O ]&&((n++))
}
d=\ 
c=${a[e/36]:e%36:1}
[ "$c" == O ]&&((--n==2))&&d=O
((n-3))||d=O
b[e/36]+=$d
n=
}
printf -vo %s\\n "${b[@]}"
echo "$o"
exec $0<<<"$o"

Оскільки це скрипт оболонки, метод введення узгоджується з іншими командами оболонки - тобто зі stdin:

$ ./conway.sh << EOF

   O 
    O 
  OOO 

EOF


  O O                                                       
   OO                                                       
   O                                                        

















    O                                                       
  O O                                                       
   OO                                                       

... тощо

Ми можемо перенаправляти введення з будь-якого джерела тексту, прокладеного через trфільтр, щоб отримати цікаві початкові покоління, наприклад

man tr | tr [:alnum:] O | ./conway.sh

6

JavaScript, 130

Не повністю відповідаючи на виклик, але для запису, ось движок Game of Life у 130 байтах, зроблений Subzey і I у 2013 році.

http://xem.github.io/miniGameOfLife/

/* Fill an array with 0's and 1's, and call g(array, width, height) to iterate */
g=function(f,c,g,d,e,b,h){g=[];e=[c+1,c,c-1,1];for(b=c*c;b--;g[b]=3==d||f[b]&&2==d,d=0)for(h in e)d+=f[b+e[h]]+f[b-e[h]];return g}

Здається, це має деякі проблеми з першим рядом. Наприклад встановлення @@\n@@(2 на 2 квадрата у верхньому лівому куті) або .@\n.@\n.@. (1 на 3 колонку)
Аннан

5

C # - 675 символів

Я завжди хотів написати версію цієї програми. Ніколи не знав, що для швидкої та брудної версії знадобиться лише ледачий півгодини. (Гольф, звичайно, займає набагато більше часу.)

using System.Windows.Forms;class G:Form{static void Main(){new G(25).ShowDialog();}
public G(int z){var g=new Panel[z,z];var n=new int [z,z];int x,y,t;for(int i=0;i<z;
i++)for(int j=0;j<z;j++){var p=new Panel{Width=9,Height=9,Left=i*9,Top=j*9,BackColor
=System.Drawing.Color.Tan};p.Click+=(s,a)=>p.Visible=!p.Visible;Controls.Add(g[i,j]=
p);}KeyUp+=(s,_)=>{for(int i=0;i<99;i++){for(x=0;x<z;x++)for(y=0;y<z;y++){t=0;for(int 
c=-1;c<2;c++)for(int d=-1;d<2;d++)if(c!=0||d!=0){int a=x+c,b=y+d;a=a<0?24:a>24?0:a;b=
b<0?24:b>24?0:b;t+=g[a,b].Visible?0:1;}if(t==3||t>1&&!g[x,y].Visible)n[x,y]=1;if(t<2
||t>3)n[x,y]=0;}for(x=0;x<z;x++)for(y=0;y<z;y++)g[x,y].Visible=n[x,y]<1;Update();}};}}

Використання

  • Введіть початковий візерунок, натиснувши клітинки, щоб увімкнути їх (живий).
  • Почніть гру, натискаючи будь-яку клавішу клавіатури.
  • Гра працює 99 поколінь щоразу, коли натискається клавіша (я міг би зробити це 9, щоб зберегти чародійку, але це здавалося занадто кульгавим).

Гольф компроміси

  • Ви можете вмикати клітинки лише мишкою, а не вимикати, тому якщо ви помилитесь, вам доведеться перезапустити програму.
  • Ліній сітки немає, але це не дуже заважає відтворюваності.
  • Швидкість оновлення пропорційна швидкості процесора, тому на дуже швидких комп'ютерах це, мабуть, буде просто розмиттям.
  • Живі клітини червоні, оскільки "чорні" використовують ще 2 символи.
  • Невелика кількість комірок і те, що вони не використовують весь простір форми, також є компромісом для збереження символів.

5

GW-BASIC, 1086 1035 байт (маркер)

У токенізованому вигляді це 1035 байт. (Форма ASCII, звичайно, трохи довша.) Ви отримуєте токенізовану форму, використовуючи SAVE"lifeкоманду, не додаючи ",aв інтерпретатора.

10 DEFINT A-Z:DEF SEG=&HB800:KEY OFF:COLOR 7,0:CLS:DEF FNP(X,Y)=PEEK((((Y+25)MOD 25)*80+((X+80)MOD 80))*2)
20 X=0:Y=0
30 LOCATE Y+1,X+1,1
40 S$=INKEY$:IF S$=""GOTO 40
50 IF S$=CHR$(13)GOTO 150
60 IF S$=" "GOTO 130
70 IF S$=CHR$(0)+CHR$(&H48)THEN Y=(Y-1+25)MOD 25:GOTO 30
80 IF S$=CHR$(0)+CHR$(&H50)THEN Y=(Y+1)MOD 25:GOTO 30
90 IF S$=CHR$(0)+CHR$(&H4B)THEN X=(X-1+80)MOD 80:GOTO 30
100 IF S$=CHR$(0)+CHR$(&H4D)THEN X=(X+1)MOD 80:GOTO 30
110 IF S$="c"THEN CLS:GOTO 20
120 GOTO 40
130 Z=PEEK((Y*80+X)*2):IF Z=42 THEN Z=32ELSE Z=42
140 POKE(Y*80+X)*2,Z:GOTO 40
150 LOCATE 1,1,0:ON KEY(1)GOSUB 320:KEY(1) ON
160 V!=TIMER+.5:FOR Y=0 TO 24:FOR X=0 TO 79:N=0
170 Z=FNP(X-1,Y-1):IF Z=42 OR Z=46 THEN N=N+1
180 Z=FNP(X,Y-1):IF Z=42 OR Z=46 THEN N=N+1
190 Z=FNP(X+1,Y-1):IF Z=42 OR Z=46 THEN N=N+1
200 Z=FNP(X-1,Y):IF Z=42 OR Z=46 THEN N=N+1
210 Z=FNP(X+1,Y):IF Z=42 OR Z=46 THEN N=N+1
220 Z=FNP(X-1,Y+1):IF Z=42 OR Z=46 THEN N=N+1
230 Z=FNP(X,Y+1):IF Z=42 OR Z=46 THEN N=N+1
240 Z=FNP(X+1,Y+1):IF Z=42 OR Z=46 THEN N=N+1
250 Z=PEEK((Y*80+X)*2):IF Z=32 THEN IF N=3 THEN Z=43
260 IF Z=42 THEN IF N<2 OR N>3 THEN Z=46
270 POKE(Y*80+X)*2,Z:NEXT:NEXT:FOR Y=0 TO 24:FOR X=0 TO 79:Z=PEEK((Y*80+X)*2):IF Z=46 THEN Z=32
280 IF Z=43 THEN Z=42
290 POKE(Y*80+X)*2,Z:NEXT:NEXT
300 IF TIMER<V!GOTO 300
310 IF INKEY$=""GOTO 160
320 SYSTEM

Це версія з максимальним полем для гольфу, але все-таки функціональна: після запуску ви отримуєте редактор, в якому можете переміщатися за допомогою клавіш курсору; простір вмикає / вимикає бактерії в поточному полі, cочищає екран, Повернення запускає ігровий режим.

Тут випливає менш затуманена версія, яка також встановлює початкову ігрову дошку з двома структурами (річ, що обертається в колах і планер):

1000 REM Conway's Game of Life
1001 REM -
1002 REM Copyright (c) 2012 Thorsten "mirabilos" Glaser
1003 REM All rights reserved. Published under The MirOS Licence.
1004 REM -
1005 DEFINT A-Z:DEF SEG=&hB800
1006 KEY OFF:COLOR 7,0:CLS
1007 DEF FNP(X,Y)=PEEK((((Y+25) MOD 25)*80+((X+80) MOD 80))*2)
1010 PRINT "Initial setting mode, press SPACE to toggle, RETURN to continue"
1020 PRINT "Press C to clear the board, R to reset. OK? Press a key then."
1030 WHILE INKEY$="":WEND
1050 CLS
1065 DATA 3,3,4,3,5,3,6,3,7,3,8,3,3,4,4,4,5,4,6,4,7,4,8,4
1066 DATA 10,3,10,4,10,5,10,6,10,7,10,8,11,3,11,4,11,5,11,6,11,7,11,8
1067 DATA 11,10,10,10,9,10,8,10,7,10,6,10,11,11,10,11,9,11,8,11,7,11,6,11
1068 DATA 4,11,4,10,4,9,4,8,4,7,4,6,3,11,3,10,3,9,3,8,3,7,3,6
1069 DATA 21,0,22,1,22,2,21,2,20,2,-1,-1
1070 RESTORE 1065
1080 READ X,Y
1090 IF X=-1 GOTO 1120
1100 POKE (Y*80+X)*2,42
1110 GOTO 1080
1120 X=0:Y=0
1125 LOCATE Y+1,X+1,1
1130 S$=INKEY$
1140 IF S$="" GOTO 1130
1150 IF S$=CHR$(13) GOTO 1804
1160 IF S$=" " GOTO 1240
1170 IF S$=CHR$(0)+CHR$(&h48) THEN Y=(Y-1+25) MOD 25:GOTO 1125
1180 IF S$=CHR$(0)+CHR$(&h50) THEN Y=(Y+1) MOD 25:GOTO 1125
1190 IF S$=CHR$(0)+CHR$(&h4B) THEN X=(X-1+80) MOD 80:GOTO 1125
1200 IF S$=CHR$(0)+CHR$(&h4D) THEN X=(X+1) MOD 80:GOTO 1125
1210 IF S$="c" THEN CLS:GOTO 1120
1220 IF S$="r" GOTO 1050
1225 IF S$=CHR$(27) THEN END
1230 GOTO 1130
1240 Z=PEEK((Y*80+X)*2)
1250 IF Z=42 THEN Z=32 ELSE Z=42
1260 POKE (Y*80+X)*2,Z
1270 GOTO 1130
1804 LOCATE 1,1,0
1900 ON KEY(1) GOSUB 2300
1910 KEY(1) ON
2000 V!=TIMER+.5
2010 FOR Y=0 TO 24
2020  FOR X=0 TO 79
2030   N=0
2040   Z=FNP(X-1,Y-1):IF Z=42 OR Z=46 THEN N=N+1
2050   Z=FNP(X  ,Y-1):IF Z=42 OR Z=46 THEN N=N+1
2060   Z=FNP(X+1,Y-1):IF Z=42 OR Z=46 THEN N=N+1
2070   Z=FNP(X-1,Y  ):IF Z=42 OR Z=46 THEN N=N+1
2080   Z=FNP(X+1,Y  ):IF Z=42 OR Z=46 THEN N=N+1
2090   Z=FNP(X-1,Y+1):IF Z=42 OR Z=46 THEN N=N+1
2100   Z=FNP(X  ,Y+1):IF Z=42 OR Z=46 THEN N=N+1
2110   Z=FNP(X+1,Y+1):IF Z=42 OR Z=46 THEN N=N+1
2120   Z=PEEK((Y*80+X)*2)
2130   IF Z=32 THEN IF N=3 THEN Z=43
2140   IF Z=42 THEN IF N<2 OR N>3 THEN Z=46
2150   POKE (Y*80+X)*2,Z
2160  NEXT X
2170 NEXT Y
2200 FOR Y=0 TO 24
2210  FOR X=0 TO 79
2220   Z=PEEK((Y*80+X)*2)
2230   IF Z=46 THEN Z=32
2240   IF Z=43 THEN Z=42
2250   POKE (Y*80+X)*2,Z
2260  NEXT X
2270 NEXT Y
2280 IF TIMER<V! GOTO 2280
2290 IF INKEY$="" GOTO 2000
2300 SYSTEM

Я написав це за 15 хвилин, коли нудьгував і чекав на товариша, котрий одночасно займався кодом з його «учнем» на «Гра життя» Конвея.

Він функціонує так: Він негайно використовує буфер екрану в текстовому режимі розміром 80x25 (змініть початковий, DEF SEGщоб використовувати, &hB000якщо ви перебуваєте на графічній картці Геркулеса; ці налаштування працюють з Qemu та (повільнішим) дозволом). Зірочка *- це бактерія.

Він працює двопрохідним: по-перше, місця народження позначені +знаками, а смерть позначає цілі .. У другому проході, +і .замінюються *і , відповідно.

TIMERСправа в тому , щоб зробити його чекати в протягом половини секунди після кожного раунду, в разі , якщо ваш хост Qemu дуже швидко ☺

Я не сподіваюся на найменшу ціну виграшів тут, але на прохолоду, особливо враховуючи початкові налаштування дошки. У мене також є версія, в якій ігровий движок був замінений на збірний код, на випадок, якщо вам цікаво ...


Зважаючи на те, що ви збільшили свої мітки на 1 у версії, що не використовується для гольфу, чи можливо це зробити на версії для гольфу? (Тобто 1, 2, 3і т.д.) Або номера рядків не розраховувати?
Zacharý

Номери рядків, коли їх називають токенізованими, рахуються як слово (16 біт), якщо я не зовсім помиляюся
mirabilos

Гаразд тоді, гадаю, я, мабуть, тоді думав про якийсь інший БАЗОВИЙ діалект.
Zacharý

@ Zacharý Клацніть на “GW-BASIC токенізований формат програми”, потім на “Формат програми”, щоб побачити, що дійсно номери рядків постійно є двома байтами, а також для отримання більш глибокої інформації про формат маркера.
mirabilos

5

Математика, 115 байт

Ось простий коп для цього:

ListAnimate[ArrayPlot/@CellularAutomaton[{224,{2,{{2,2,2},{2,1,2},
{2,2,2}}},{1,1}},{RandomInteger[1,{9,9}],0},90]]

1
Mathematica - це добре, але, згідно з правилами, програма повинна дозволяти користувачеві вводити власні шаблони. Це правило є навмисним, оскільки кілька мов дозволяють виконувати такі короткі реалізації, але без взаємодії з користувачем. Звичайно, ви можете помістити туди свій власний масив, але це не виграє.
Гриффін

"Введення" в Mathematica здебільшого здійснюється через інтерфейс ноутбука, тому я не думаю, що "взаємодія з користувачем" реально можлива. Ви просто замінюєте аргумент RandomInteger на функцію CellularAutomaton на все, що завгодно, і повторно оцінюєте код.
JeremyKun

3
Можлива взаємодія з користувачем. Найбільш спрощений метод, про який я зараз можу придумати - це масив кнопок. Віддай людину.
Гриффін

4

Java (OpenJDK 8) - 400 388 367 байт

Друга та (ймовірно) остаточна редакція. Після пошуку цих (імо) золотих копалень вдалося пограти в гольф додаткових 21 байт - безумовно, рекомендую новим людям їх прочитати (особливо якщо ви збираєтеся спробувати деякі з цих проблем за допомогою Java).

Отриманий код (напевно, в кінцевому підсумку гольф ще більше, якщо я дізнаюся, як скоротити ці подвійні вкладені петлі ...):

u->{int w=u.length,h=u[0].length,x,y,i,j,n;Stack<Point>r=new Stack<Point>();for(;;){for(Point c:r)u[c.x][c.y]=1;r.clear();for(x=0;x<w;++x)for(y=0;y<h;++y){boolean o=u[x][y]>0;n=o?-1:0;for(i=-2;++i<2;)for(j=-2;++j<2;)if(u[(w+x+i)%w][(h+y+j)%h]>0)++n;if(o&n>1&n<4|!o&n==3)r.add(new Point(x,y));System.out.print(u[x][y]+(y>h-2?"\n":""));}for(int[]t:u)Arrays.fill(t,0);}}

Спробуйте в Інтернеті!

(Оригінальна публікація починається тут.)

Я насправді на мить подумав, що мені вдасться принаймні кинути виклик найкращій відповіді Python з моїми (можливо, обмеженими) знаннями Java lol ... Це було завданням, в якому я все-таки сподобався приєднатися (незважаючи на те, що приєднався до партії, можливо, просто трохи пізно ...)

Насправді це не так багато - базове пояснення наступним чином (невольф):

/*
 * Explanation of each variable's usage:
 * w=height* of array
 * h=width* of array
 * x=y* coord of point in array
 * y=x* coord of point in array
 * i and j are counters for calculating the neighbours around a point in the array
 * n=neighbour counter
 * r=temporary array to store the cells from the current generation
 * u=the 2d array used for all the calculations (parameter from lambda expression)
 * c=temporary variable used to help populate the 2d array
 * o=boolean variable that stores the value of whether the cell is alive or not
 */
u-> // start of lambda statement with u as parameter (no need for brackets as it's only one parameter being passed)
{
    int w=u.length,h=u[0].length,x,y,i,j,n; // defines all the necessary integer variables;
    Stack<Point>r=new Stack<Point>(); // same with the only array list needed (note how I only use two data structures);
    for(;;) // notice how this is still an infinite loop but using a for loop;
    {
        for(Point c:r)u[c.x][c.y]=1; //for every point in the "previous" generation, add that to the 2D array as a live (evil?) cell;
        r.clear(); // clears the array list to be populated later on
        for(x=0;x<w;++x) // a pair of nested for loops to iterate over every cell of the 2D array;
        {
            for(y=0;y<h;++y)
            {
                // sets o to be the presence of a live cell at (x,y) then uses said value in initialising the neighbour counter;
                boolean o=u[x][y]>1;n=o?-1:0;
                for(i=-2;++i<2;) // another pair of nested for loops - this one iterates over a 3x3 grid around *each* cell of the 2D array;
                {                // this includes wrap-around (note the modulus sign in the if statement below);
                    for(j=-2;++j<2;)
                    {
                        if(u[(w+x+i)%w][(h+y+j)%h]>0)++n; // this is where the first interesting thing lies - the bit which makes wrap-around a reality;
                    }
                }
                if(o&n>1&n<4|!o&n==3)r.add(new Point(x,y)); // this is the second interesting bit of my code - perhaps more so as I use bitwise operators to calculate the number of neighbours (x,y) has;
                                                            // (since I'm technically dealing with 0s and 1s, it's not a total misuse of them imo);
                System.out.print(u[x][y]+(y>h-2?"\n":""));  // that extra part of the print statement adds a newline if we reached the end of the current 'line';
            }
        }
        // since the information about the new generation is now in the array list, this array can be emptied out, ready to receive said info on the new generation;
        for(int[]t:u)Arrays.fill(t,0);
    }
} // end of lambda statement

(більше інформації про lambda заяви на Java 8 тут )

Так, у мого підходу є улов.

Як більшість із вас, напевно, помічали, мій гольф-код, який він наразі стоїть, назавжди зациклюється. Щоб запобігти цьому, лічильник можна ввести вгорі і використовувати в циклі while лише для відображення n(у цьому випадку 5) ітерацій наступним чином (зверніть увагу на bдодану нову змінну):

u->{int b=0,w=u.length,h=u[0].length,x,y,i,j,n;Stack<Point>r=new Stack<Point>();for(;++b<6;){for(Point c:r)u[c.x][c.y]=1;r.clear();for(x=0;x<w;++x)for(y=0;y<h;++y){boolean o=u[x][y]>0;n=o?-1:0;for(i=-2;++i<2;)for(j=-2;++j<2;)if(u[(w+x+i)%w][(h+y+j)%h]>0)++n;if(o&n>1&n<4|!o&n==3)r.add(new Point(x,y));System.out.print(u[x][y]+(y>h-2?"\n":""));}for(int[]t:u)Arrays.fill(t,0);}}

Додатково варто згадати кілька моментів. Ця програма не перевіряє, чи введений текст правильний, і, отже, не вдасться (швидше за все) ArrayOutOfBoundsException; таким чином переконайтеся, що вхід є дійсним, повністю заповнивши частину масиву (скошені масиви підкидають згаданий вище виняток). Крім того, дошка як зараз виглядає «текучою» - тобто немає поділу між одним поколінням і наступним. Якщо ви хочете додати це, щоб подвійно переконатися, що покоління, що виробляються, справді дійсні, додаткові System.out.println();потрібно додати безпосередньо раніше for(int[]t:u)Arrays.fill(t,0);(див. Спробуйте це в Інтернеті! Для наочності). І останнє, але не менш важливе, враховуючи, що це мій перший гольф-код, будь-які відгуки дуже вдячні :)

Старий код з попередньої відповіді 388 байт:

u->{int w=u.length,h=u[0].length,x,y,i,j,n;ArrayList<Point>r=new ArrayList<Point>();while(true){for(Point c:r)u[c.x][c.y]=1;r.clear();for(x=0;x<w;++x){for(y=0;y<h;++y){boolean o=u[x][y]==1;n=o?-1:0;for(i=-2;++i<2;)for(j=-2;++j<2;)if(u[(w+x+i)%w][(h+y+j)%h]==1)++n;if(o&n>1&n<4|!o&n==3)r.add(new Point(x,y));System.out.print(u[x][y]);}System.out.println();}for(int[]t:u)Arrays.fill(t,0);}}

І з початкової відповіді на 400 байт:

int w=35,h=20,x,y,i,j,n;ArrayList<Point>l=new ArrayList<Point>(),r;while(true){int[][]u=new int[w][h];for(Point c:l)u[c.x][c.y]=1;r=new ArrayList<Point>();for(x=0;x<w;++x){for(y=0;y<h;++y){boolean o=u[x][y]==1;n=o?-1:0;for(i=-2;++i<2;)for(j=-2;++j<2;)if(u[(w+x+i)%w][(h+y+j)%h]==1)++n;if(o&n>1&n<4|!o&n==3)r.add(new Point(x,y));System.out.print(u[x][y]);}System.out.println();}l.clear();l.addAll(r);}

Дивовижне перше повідомлення, ласкаво просимо до PPCG!
Zacharý

Дякую, я напевно буду робити більше цього - вони веселі :)
NotBaal

Приєднуйтесь до нас, у нас є Денніс. Крім того, це не повна програма, ані функція, якою вона повинна бути, IIRC.
Zacharý

Ой, забув, частину програми, P: Редагування цього в трохи.
NotBaal

Це може бути і функція.
Zacharý

4

Трафарет , 6 байт

Чи не мій улюблений мова, але це короткий ...

4 байта коду плюс прапор nlist та Torus.

3me

Спробуйте в Інтернеті!

Є чи ...
3 3
 член
m в м oore-околиці відліку з власною або
e мавр е -окрестності відліку без себе
...?


3

Scala - 799 символів

Запустити як сценарій. Клацання миші на квадрат вмикає або вимикає, і будь-яка клавіша запускає або зупиняє генерацію.

import java.awt.Color._
import swing._
import event._
import actors.Actor._
new SimpleSwingApplication{var(y,r,b)=(200,false,Array.fill(20,20)(false))
lazy val u=new Panel{actor{loop{if(r){b=Array.tabulate(20,20){(i,j)=>def^(i:Int)= -19*(i min 0)+(i max 0)%20
var(c,n,r)=(0,b(i)(j),-1 to 1)
for(x<-r;y<-r;if x!=0||y!=0){if(b(^(i+x))(^(j+y)))c+=1}
if(n&&(c<2||c>3))false else if(!n&&c==3)true else n}};repaint;Thread.sleep(y)}}
focusable=true
preferredSize=new Dimension(y,y)
listenTo(mouse.clicks,keys)
reactions+={case e:MouseClicked=>val(i,j)=(e.point.x/10,e.point.y/10);b(i)(j)= !b(i)(j)case _:KeyTyped=>r= !r}
override def paintComponent(g:Graphics2D){g.clearRect(0,0,y,y);g.setColor(red)
for(x<-0 to 19;y<-0 to 19 if b(x)(y))g.fillRect(x*10,y*10,9,9)}}
def top=new Frame{contents=u}}.main(null)

3

J, 45

Я думав, що спробую Дж. Це ще не особливо добре гольф, але я спробую ще раз спробувати.

(]+.&(3&=)+)+/((4&{.,(_4&{.))(>,{,~<i:1))&|.

Приклад:

   f =: 5 5 $ 0 1 0 0 0   0 0 1 0 0   1 1 1 0 0   0 0 0 0 0    0 0 0 0 0
   f
0 1 0 0 0
0 0 1 0 0
1 1 1 0 0
0 0 0 0 0
0 0 0 0 0
   f (]+.&(3&=)+)+/((4&{.,(_4&{.))(>,{,~<i:1))&|. f
0 0 0 0 0
1 0 1 0 0
0 1 1 0 0
0 1 0 0 0
0 0 0 0 0

3

Обробка 536 532

int h=22,t=24,i,j;int[][]w=new int[t][t],b=new int[t][t];int[]q={1,0,-1};void draw(){if(t<9){clear();for(i=2;i<h;i++){for(j=2;j<h;j++)w[i][j]=b[i][j];w[i][1]=w[i][21];w[i][h]=w[i][2];w[1][i]=w[21][i];w[h][i]=w[2][i];}for(i=1;i<23;i++)for(j=1;j<23;j++){t=-w[i][j];for(int s:q)for(int d:q)t+=w[i+s][j+d];b[i][j]=w[i][j]>0&(t<2|t>3)?0:t==3?1:b[i][j];}a();}}void keyPressed(){t=0;}void mousePressed(){int i=mouseX/5+2,j=mouseY/5+2;w[i][j]=b[i][j]=1;a();}void a(){for(i=0;i<h-2;i++)for(j=0;j<h-2;j++)if(w[i+2][j+2]==1)rect(i*5,j*5,5,5);}

Я вважаю, що це задовольняє всі вимоги.

Безголівки:

int h=22,t=24,i,j;
int[][]w=new int[t][t],b=new int[t][t];
int[]q={1,0,-1};
void draw(){
  if(t<9){
  clear();
  for(i=2;i<h;i++){
    for(j=2;j<h;j++)
      w[i][j]=b[i][j];  
    w[i][1]=w[i][21];
    w[i][h]=w[i][2];
    w[1][i]=w[21][i];
    w[h][i]=w[2][i];
  }
  for(i=1;i<23;i++)
    for(j=1;j<23;j++){
      t=-w[i][j];
      for(int s:q)
        for(int d:q)
          t+=w[i+s][j+d];        
      b[i][j]=w[i][j]>0&(t<2|t>3)?0:t==3?1:b[i][j];  
  }
  a();
}
}
void keyPressed(){
  t=0;
}
void mousePressed(){
  int i=mouseX/5+2,j=mouseY/5+2;
  w[i][j]=b[i][j]=1;
  a();
}
void a(){
  for(i=0;i<h-2;i++)
    for(j=0;j<h-2;j++)
      if(w[i+2][j+2]==1)
        rect(i*5,j*5,5,5);
  }  

3

Матлаб (152)

b=uint8(rand(20)<0.2)
s=@(m)imfilter(m,[1 1 1;1 0 1;1 1 1],'circular')
p=@(m,n)uint8((n==3)|(m&(n==2)))
while 1
imshow(b)
drawnow
b=p(b,s(b))
end

Мені не встановлено Matlab зараз, щоб перевірити його, я просто гольф код, який я написав кілька років тому.
Безголівки:

%% initialize
Bsize = 20;
nsteps = 100;
board = uint8(rand(Bsize)<0.2); % fill 20% of the board
boardsum = @(im) imfilter(im,[1 1 1; 1 0 1; 1 1 1], 'circular');
step = @(im, sumim) uint8((sumim==3) | (im & (sumim==2)) );

%% run
for i = 1:nsteps
    imshow(kron(board,uint8(ones(4))), [])
    drawnow
    ss(p,i) = sum(board(:));
    board = step(board, boardsum(board));
end
  • Розмір бордового коду є жорстким кодом, але він може бути будь-яким
  • обгортає
  • для введення користувача можна змінити вхідну плату або жорстким кодуванням іншої матриці, або за допомогою редактора змінних. Не дуже, але це працює
  • 20 символів можна зберегти, якщо графічний вихід буде пропущений, дошка все одно буде надрукована як текст під час кожної ітерації. Однопіксельні комірки, які змінюються кожні мілісекунди, все одно не дуже корисні

працює в R2014a, щойно перевірений
masterX244

3

Perl, 218 216 211 202 байт

$,=$/;$~=AX3AAAx76;$b=pack('(A79)23',<>)x6;{print unpack'(a79)23a0',$b;select$v,$v,$v,0.1;$b=pack'(A)*',unpack'((x7a/(x13)X4Ax!18)1817@0)4',pack'((a*)17xx!18)*',unpack"x1737(AA$~Ax$~AA$~@)2222",$b;redo}

(Нічого нового рядка в кінці цього коду немає.)

Читає початковий візерунок зі стандартного введення, як текстовий файл, де живі осередки представлені у вигляді 1, мертві комірки, представлені у вигляді пробілу, рядки розділені новим рядком. На вході не повинно бути символів, окрім цих. Лінії можуть бути різної довжини і будуть прокладеними або врізаними рівно до 79 ширини. Приклад введення - планер:

                                  1
                                1 1
                      11      11            11
                     1   1    11            11
          11        1     1   11
          11        1   1 11    1 1
                    1     1       1
                     1   1
                      11









                                         11
                                         1
                                          111
                                            1

Поки програма запускає Game of Life, кожен стан скидається на стандартний вихід у форматі, подібному до вхідного, а потім затримується на 0,1 секунди. Затримку можна налаштувати, змінивши четвертий аргумент виклику вибору.

Ігрова дошка жорстко закодована до розміру 79x23. Він загорнутий у тору: якщо ви залишите дошку на дні, ви закінчите вгорі; якщо ви виїдете з правого боку, ви закінчите з лівого боку, але змістили один ряд вниз.

Ось альтернативна версія, яка не читає жодного вводу і починається з випадкової дошки:

$,=$/;$/=AX3AAAx76;$b=pack("(A)*",map{rand 3<1}0..1816)x6;{print unpack'(a79)23a0',$b;select$v,$v,$v,0.1;$b=pack'(A)*',unpack'((x7a/(x13)X4Ax!18)1817@0)4',pack'((a*)17xx!18)*',unpack"x1737(AA$/Ax$/AA$/@)2222",$b;redo}

Цей код походить від прихованої програми life perl, про яку я писав роки тому . Я дуже змінив це, щоб зробити борту toroidal і гольф код.

Це, мабуть, не найкоротший метод втілення гри в життя в perl, але це один із менш зрозумілих.

Дошка зберігається $bяк рядок '1'і ' ', по одному для кожної комірки, лише вся справа повторюється щонайменше три рази. Третій розпакуваний виклик вилучає 17 значень для кожної комірки: є одне для самої комірки та два для кожної з восьми сусідніх комірок у довільному порядку, і кожне значення є '1'або порожній рядок. Осередок повинен бути в прямому ефірі наступної ітерації, якщо кількість '1'значень серед цих 17 значень становить 5, 6 або 7. Третій виклик пакета об'єднує ці 17 значень у поле з 18 символів, вирівняне ліворуч і підкреслене нульовими байтами справа . Другий розпаковуючий виклик займає таке 18 широке поле, розсилає персонажа в позиції 7, розпаковує простір з позиції 17, якщо це'1'або розпаковує персонаж із положення 4 в іншому випадку. Цей результат є саме тим значенням, яке має мати клітина в наступному поколінні.


2

Python, 589 байт

Кнопки миші: ліворуч - поставте клітинку, праворуч - вийміть клітинку, посередині - запуск / зупинка.

з імпорту Tkinter *
імпортувати копію
z = діапазон
F = 50
T = Tk ()
S = 9
f = [F * [0] для i in'7 '* F]
c = Полотно (T, ширина = S * F, висота = S * F)
c.pack ()
def p (x, y, a): f [y] [x] = f [y] [x] або c.create_oval (x * S, y * S, x * S + S, y * S + S) якщо інше c.delete (f [y] [x])
r = 1
def R (e): глобальний r; r = 1-r
exec ("c.bind ('<Кнопка-% i>', лямбда e: p (ex / S, ey / S,% i));" * 2% (1,1,3,0))
c.bind ('<Кнопка-2>', R)
def L ():
 Т.after (99, L)
 якщо г: повернення
 g = copy.deepcopy (f)
 для y в z (F):
	для x в z (F):
	 n = 8
	 для j в z (-1,2):
		для i в z (-1,2):
		 якщо i або j: n- = не g [(y + j)% F] [(x + i)% F]
	 якщо 1 <n <4:
		якщо n == 3і не g [y] [x]: p (x, y, 1)
	 інше: p (x, y, 0)
L ()
T.mainloop ()

І ось версія, де можна перетягувати мишу, щоб малювати. Графіка трохи приємніше.

from Tkinter import*
import copy
z=range
F=50
T=Tk()
S=9
f=[F*[0]for i in'7'*F]
c=Canvas(T,bg='white',width=S*F,height=S*F)
c.pack()
def p(x,y,a):f[y][x]=f[y][x]or c.create_rectangle(x*S,y*S,x*S+S,y*S+S,fill='gray')if a else c.delete(f[y][x])
r=1
def R(e):global r;r=1-r
exec("c.bind('<Button-%i>',lambda e:p(e.x/S,e.y/S,%i));c.bind('<B%i-Motion>',lambda e:p(e.x/S,e.y/S,%i));"*2%(1,1,1,1,3,0,3,0))
c.bind('<Button-2>',R)
def L():
 T.after(99,L)
 if r:return
 g=copy.deepcopy(f)
 for y in z(F):
  for x in z(F):
   n=8
   for j in z(-1,2):
    for i in z(-1,2):
     if i or j:n-=not g[(y+j)%F][(x+i)%F]
   if 1<n<4:
    if n==3and not g[y][x]:p(x,y,1)
   else:p(x,y,0)
L()
T.mainloop()

Це не відповідає правилам гри життя.
Стівен Румбальський

1
@StevenRumbalski: О, справді?
Олег Припін

2
дійсно. У вашій другій версії помилка відступу. Розділ, що починається з, if 1<n<4:повинен бути відступним на тому ж рівні, що іfor j in z(-1,2):
Стівен Румбальський,

2

Python 2, 456 байт

Хоча я знаю, що це старий пост, я не міг не дати собі пострілу. Початкова дошка може бути будь-якого розміру до тих пір, поки ви намалюєте рамку навколо неї та матимете додатковий простір на останньому рядку.

Golf.py

import time,itertools as w,sys;t,q=map(lambda x:list(x[:-1]),sys.stdin.readlines()),list(w.product(range(-1,2),range(-1,2)));del q[4];n=map(lambda x:x[:],t[:])
while time.sleep(0.1)==None:
 for j in range(1,len(t)-1):
  for i in range(1,len(t[j])-1):x=sum(map(lambda s:1 if t[j+s[0]][i+s[1]]in'@'else 0,q));f=t[j][i];n[j][i]='@'if(f=='@'and(x==3 or x==2))or(f==' 'and x==3)else' '
 t=map(lambda x:x[:],n[:]);print'\n'.join(list(map(lambda x:''.join(x),t)))

Input.txt (відзначте додаткове місце в останньому рядку)

+----------------------------------------+
|                    @                   |
|                     @                  |
|                   @@@                  |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
+----------------------------------------+ 

Як бігати

python Golf.py < input.txt

time.sleep(0.1)==None=> not time.sleep(.1), (f=='@'and(x==3 or x==2)) або (f == '' і x == 3) =>x==3or f=='@'and x==2
CalculatorFeline

^, Ви забули одне, 1 if=> 1if.
Zacharý

2

Обробка 270 261 249 байт

Сітка - це 100 * 100 пікселів екрана, вхід надходить у вигляді PNG зображення

void setup(){image(loadImage("g.png"),0,0);}void draw(){loadPixels();int n,i=0,j,l=10000;int[]a=new int[l],p=pixels;for(;i<l;a[i]=n==5?-1<<24:n==6?p[i]:-1,i++)for(j=n=0;j<9;j++)n+=j!=4?p[(i+l-1+j%3+100*(j/3-1))%l]&1:0;arrayCopy(a,p);updatePixels();}

Безумовно

void setup() {
  image(loadImage("g.png"), 0, 0);
}
void draw() {
  loadPixels();
  int c=100, i=0, n, l=c*c, b=color(0);
  int[]a=new int[l], p=pixels;
  for (; i<l; i++) {
    n=p[(i+l-101)%l]&1;
    n+=p[(i+l-100)%l]&1;
    n+=p[(i+l-99)%l]&1;
    n+=p[(i+l-1)%l]&1;
    n+=p[(i+1)%l]&1;
    n+=p[(i+99)%l]&1;
    n+=p[(i+100)%l]&1;
    n+=p[(i+101)%l]&1;
    a[i]=n==5?b:p[i]==b&&n==6?b:-1;
  }
  arrayCopy(a, pixels, l);
  updatePixels();
}

скріншот


2

Lua + LÖVE / Love2D , 653 байти

l=love f=math.floor t={}s=25 w=20 S=1 for i=1,w do t[i]={}for j=1,w do t[i][j]=0 end end e=0 F=function(f)loadstring("for i=1,#t do for j=1,#t[i]do "..f.." end end")()end function l.update(d)if S>0 then return end e=e+d if e>.2 then e=0 F("c=0 for a=-1,1 do for b=-1,1 do if not(a==0 and b==0)then c=c+(t[((i+a-1)%w)+1][((j+b-1)%w)+1]>0 and 1 or 0)end end end g=t[i][j]t[i][j]=(c==3 or(c==2 and g==1))and(g==1 and 5 or-1)or(g==1 and 4 or 0)")F("t[i][j]=t[i][j]%2")end end function l.draw()F("l.graphics.rectangle(t[i][j]==1 and'fill'or'line',i*s,j*s,s,s)")end function l.mousepressed(x,y)S=0 o,p=f(x/s),f(y/s)if t[o]and t[o][p]then t[o][p]=1 S=1 end end

або на відстані:

l=love
f=math.floor
t={}s=25
w=20
S=1
for i=1,w do
    t[i]={}
    for j=1,w do
        t[i][j]=0
    end
end
e=0
F=function(f)
    loadstring("for i=1,#t do for j=1,#t[i] do  "..f.." end end")()
end
function l.update(d)
    if S>0 then
        return
    end
    e=e+d
    if e>.2 then
        e=0
        F([[
        c=0
        for a=-1,1 do
            for b=-1,1 do
                if not(a==0 and b==0)then
                    c=c+(t[((i+a-1)%w)+1][((j+b-1)%w)+1]>0 and 1 or 0)
                end
            end
        end
        g=t[i][j]
        t[i][j]=(c==3 or(c==2 and g==1))and(g==1 and 5 or-1) or (g==1 and 4 or 0)]])
        F("t[i][j]=t[i][j]%2")
    end
end
function l.draw()
    F("l.graphics.rectangle(t[i][j]==1 and'fill'or'line',i*s,j*s,s,s)") end
function l.mousepressed(x,y)
    S=0
    o,p=f(x/s),f(y/s)
    if t[o]and t[o][p] then
        t[o][p]=1
        S=1
    end
end

Клацніть на полі, щоб додати живі клітини. Клацніть поза полем, щоб запустити його.

Спробуйте в Інтернеті!

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


1

Постскрипт 529 515

Розпочали з прикладу з коду Rosetta . Викликайте аргумент імені файлу ( gs -- gol.ps pulsar), файл, що містить 20 * 20 двійкових чисел (розділених пробілом). Нескінченний цикл: намалюйте дошку, дочекайтеся введення, обчисліть наступне покоління.

[/f ARGUMENTS 0 get(r)file/n 20>>begin[/m
n 1 sub/b[n{[n{f token pop}repeat]}repeat]/c 400
n div/F{dup 0 lt{n add}if dup n ge{n sub}if}>>begin{0
1 m{dup 0 1 m{2 copy b exch get exch get 1 xor setgray
c mul exch c mul c c rectfill dup}for pop pop}for
showpage/b[0 1 m{/x exch def[0 1 m{/y exch def 0
y 1 sub 1 y 1 add{F dup x 1 sub 1 x
1 add{F b exch get exch get 3 2 roll add exch
dup}for pop pop}for b x get y get sub b x get y get
0 eq{3 eq{1}{0}ifelse}{dup 2 eq exch 3 eq
or{1}{0}ifelse}ifelse}for]}for]def}loop

Розміщені, з кількома коментарями стека (лише ті, що мені потрібні).

[
/f ARGUMENTS 0 get(r)file
/n 20
/sz 400
%/r{rand 2147483647 div}
>>begin
[
/m n 1 sub
/b[
%n{[n{r .15 le{1}{0}ifelse}repeat]}repeat
 n{[n{f token pop}repeat]}repeat
]
/c sz n div
/F{dup 0 lt{n add}if dup n ge{n sub}if}
>>begin
{
    0 1 m{dup % y y
    0 1 m{ % y y x
        2 copy b exch get exch get 1 xor setgray
        c mul exch c mul c c rectfill
        dup 
    }for pop pop}for
    pstack
    showpage
    /b[0 1 m{/x exch def
      [0 1 m{/y exch def
          0   
          y 1 sub 1 y 1 add{F dup %s y y
          x 1 sub 1 x 1 add{F %s y y x
              b exch get exch get %s y bxy
              3 2 roll add exch %s+bxy y
              dup %s y y
          }for pop pop}for
          b x get y get sub
          b x get y get
          0 eq{3 eq{1}{0}ifelse}{dup 2 eq exch 3 eq or{1}{0}ifelse}ifelse
      }for]
      }for]def
}loop

файл даних пульсара:

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 0 0 0 0 0
0 0 0 0 0 1 1 1 0 0 0 1 1 1 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 1 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0
0 0 0 0 0 1 1 1 0 0 0 1 1 1 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 1 1 1 0 0 0 1 1 1 0 0 0 0 0 0
0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 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 1 1 1 0 0 0 1 1 1 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 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

1

JavaScript 676

Вибачте, Гриффін, я просто не міг подивитися на ваш код і не переписати його злегка ... довелося поголити два символи, але це чорт вартує!

b=[];r=c=s=20;U=document;onload=function(){for(z=E=0;z<c;++z)for(b.push(t=[]),j=0;j<r;j++)with(U.body.appendChild(U.createElement("button")))t.push(0),id=z+"_"+j,style.position="absolute",style.left=s*j+"px",style.top=s*z+"px",onclick=a}; ondblclick=function(){A=E=E?clearInterval(A):setInterval(function(){Q=[];for(z=0;z<c;++z){R=[];for(j=0;j<r;)W=(c+z-1)%c,X=(c+z+1)%c,Y=(r+j-1)%r,Z=(r+j+1)%r,n=b[W][Y]+b[z][Y]+b[X][Y]+b[W][j]+b[X][j]+b[W][Z]+b[z][Z]+b[X][Z],R.push(b[z][j++]?4>n&&1<n:3==n);Q.push(R)}b=Q.slice();d()})};function a(e){E?0:P=e.target.id.split("_");b[P[0]][P[1]]^=1;d()}function d(){for(z=0;z<c;++z)for(j=0;j<r;)U.getElementById(z+"_"+j).innerHTML=b[z][j++]-0}

Але як кажуть, простіше просити пробачення, ніж дозволу ...;)



1

Пітон 2: 334 байт

Лише 6 років спізнюється.

import time
s='';s=map(list,iter(raw_input,s));k=len(s);l=(-1,0,1);n=int;z=range
while 1:
 r=[[0]*k for i in z(k)]
 for i in z(k*k):
  a,b=i//k,i%k
  m,g=sum([n(s[(a+c)%k][(b+d)%k])for c in l for d in l if c|d]),n(s[a][b])
  r[a][b]=n((m==2)&g or m==3)
  print'*'if r[a][b]else' ',
  if b-k+1==0:print
 s=r;time.sleep(.2);print"\033c"

Ви можете запустити його так:

python gol.py
0000000
0001000
0000100
0011100
0000000
0000000
0000000

Якщо 0 і 1 являють собою мертві і живі клітини, в кінці починається виконання додаткового нового рядка.

Сітки повинні бути квадратними.

Це легше запустити, ніж найкоротший пітон, підтримує сітки будь-якого розміру і виглядає красиво під час запуску.

Це також на 100 байт більше, так що це є.


0

PHP, 201 байт (не перевірено)

for($s=file(f);print"\n";$s=$t)foreach($s as$y=>$r)for($x=-print"
";"
"<$c=$s[$y][++$x];print$t[$y][$x]=" X"[$n<4&$n>2-$a])for($n=-$a=$c>A,$i=$x-!!$x-1;$i++<=$x;)for($k=$y-2;$k++<=$y;)$n+=$s[$k][$i]>A;

Бігайте з -nr.

зламатися

for($s=file(f);                         # import input from file "f"
    print"\n";                              # infinite loop: 1. print newline
    $s=$t)                                  # 3. copy target to source, next iteration
    foreach($s as$y=>$r)                    # 2. loop through lines
        for($x=-print"\n";"\n"<$c=$s[$y][++$x]; # print newline, loop $x/$c through line characters (before line break)
            print                                   # 5. print new cell
                $t[$y][$x]=" X"[$n>2-$a&$n<4])      # 4. new cell is alive if neighbour count<4 and >2 (>1 if alive)
            for($n=-                                # 2. init neighbour count: exclude self
                $a=$c>A,                            # 1. $a=cell is alife
                $i=$x-!!$x-1;$i++<=$x;)             # 3. loop $i from one left to one right of current position
                for($k=$y-2;$k++<=$y;)                  # loop $k from one above to one below current position
                    $n+=$s[$k][$i]>A;                       # increase neighbor count if neighbour is alife
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.