Задача: Напишите самую короткую программу, реализующую игру Джона Х. Конвея Game of Life клеточный автомат. [ link ]
РЕДАКТИРОВАТЬ: Примерно через неделю после соревнования я выбрал победителя: pdehaan , за то, что ему удалось победить решение Matlab одним . персонаж с перлом.
Для тех, кто не слышал об Игре Жизни, вы берете сетку (в идеале бесконечную) квадратных ячеек. Клетки могут быть живыми (заполненными) или мертвыми (пустыми). Мы определяем, какие клетки живы в следующем шаге времени, применяя следующие правила:
Ваша программа будет читать текстовый файл ASCII размером 40x80 символов, указанный как команда: аргумент строки, а также количество итераций (N) для выполнения. Наконец, он выведет в ASCII-файл out.txt состояние системы после N итераций.
Вот пример запуска с соответствующими файлами:
in.txt:
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
..................................XX............................................
..................................X.............................................
.......................................X........................................
................................XXXXXX.X........................................
................................X...............................................
.................................XX.XX...XX.....................................
..................................X.X....X.X....................................
..................................X.X......X....................................
...................................X.......XX...................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
Итерация 100 раз:
Q:\>life in.txt 100
Результирующий вывод (out.txt)
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
..................................XX............................................
..................................X.X...........................................
....................................X...........................................
................................XXXXX.XX........................................
................................X.....X.........................................
.................................XX.XX...XX.....................................
..................................X.X....X.X....................................
..................................X.X......X....................................
...................................X.......XX...................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
Правила:
Победитель будет определяться количеством символов .
Удачи!
Удалось удалить еще пару символов ...
$/=pop;@b=split'',<>;map{$n=-1;@b=map{++$n;/
/?$_:($t=grep/X/,@b[map{$n+$_,$n-$_}1,80..82])==3|$t+/X/==3?X:'.'}@b}1..$/;print@b
a=process.argv
f=require('fs')
m=46
t=f.readFileSync(a[2])
while(a[3]--)t=[].map.call(t,function(c,i){for(n=g=0;e=[-82,-81,-80,-1,1,80,81,82][g++];)t[i+e]>m&&n++
return c<m?c:c==m&&n==3||c>m&&n>1&&n<4?88:m})
f.writeFile('out.txt',t)
Обновление 1 : первый StringBuffer
заменен на Добавляемый
, а второй - на char []
. Сохранено 24 символа.
Обновление 2: нашел более короткий способ чтения файла в char []
. Сохранено 15 символов.
Обновление 3: заменил одно if / else
на ?:
и объединил объявления char []
и int
. Сохранено 21 символ.
Обновление 4: заменены (int) f.length ()
и c.length
на s
. Сохранено 24 символа.
Обновление 5: внесены улучшения в соответствии с подсказками Molehill. Основным из них было жесткое кодирование длины символа, чтобы я мог избавиться от File
. Сохранено 39 символов.
Обновление 6: незначительный рефакторинг. Сохранено 6 символов.
Обновление 7: заменено Integer # valueOf ()
на new Integer ()
и переработан цикл for. Сохранено 8 символов.
Обновление 8: Улучшено вычисление соседей. Сохранено 2 символа.
Обновление 9: Оптимизировано чтение файла, поскольку длина файла уже жестко задана. Сохранено 37 символов.
import java.io.*;class L{public static void main(String[]a)throws Exception{int i=new Integer(a[1]),j,l,s=3240;int[]p={-82,-81,-80,-1,1,80,81,82};char[]o,c=new char[s];for(new FileReader(a[0]).read(c);i-->0;c=o)for(o=new char[j=s];j-->0;){l=0;for(int n:p)l+=n+j>-1&n+j<s?c[n+j]/88:0;o[j]=c[j]>13?l==3|l+c[j]==90?88:'.':10;}Writer w=new FileWriter("out.txt");w.write(c);w.close();}}
Более читаемая версия:
import java.io.*;
class L{
public static void main(String[]a)throws Exception{
int i=new Integer(a[1]),j,l,s=3240;
int[]p={-82,-81,-80,-1,1,80,81,82};
char[]o,c=new char[s];
for(new FileReader(a[0]).read(c);i-->0;c=o)for(o=new char[j=s];j-->0;){
l=0;for(int n:p)l+=n+j>-1&n+j<s?c[n+j]/88:0;
o[j]=c[j]>10?l==3|l+c[j]==90?88:'.':10;
}
Writer w=new FileWriter("out.txt");w.write(c);w.close();
}
}
Закрытие после записи является устаревшим обязательным, иначе файл останется пустым. В противном случае было бы сэкономлено еще 21 символ.
Кроме того, я мог бы также сохранить еще один символ, если использую 46
вместо '.'
, но и javac, и Eclipse дергаются с ошибкой компиляции Возможная потеря точности . Странные вещи.
Примечание: при этом ожидается входной файл с \ n
новыми строками, а не \ r \ n
, как Windows по умолчанию использует!
Scala - 467 364 339 символов
object G{def main(a:Array[String]){val l=io.Source.fromFile(new java.io.File(a(0)))getLines("\n")map(_.toSeq)toSeq
val f=new java.io.FileWriter("out.txt")
f.write((1 to a(1).toInt).foldLeft(l){(t,_)=>(for(y<-0 to 39)yield(for(x<-0 to 79)yield{if(x%79==0|y%39==0)'.'else{val m=t(y-1)
val p=t(y+1);val s=Seq(m(x-1),m(x),m(x+1),t(y)(x-1),t(y)(x+1),p(x-1),p(x),p(x+1)).count('X'==_)
if(s==3|(s==2&t(y)(x)=='X'))'X'else'.'}})toSeq)toSeq}map(_.mkString)mkString("\n"))
f.close}}
Я думаю, что есть много возможностей для улучшения ...
[Изменить] Да, это:
object G{def main(a:Array[String]){var l=io.Source.fromFile(new java.io.File(a(0))).mkString
val f=new java.io.FileWriter("out.txt")
var i=a(1).toInt
while(i>0){l=l.zipWithIndex.map{case(c,n)=>if(c=='\n')'\n'else{val s=Seq(-83,-82,-81,-1,1,81,82,83).map(_+n).filter(k=>k>=0&k<l.size).count(l(_)=='X')
if(s==3|(s==2&c=='X'))'X'else'.'}}.mkString
i-=1}
f.write(l)
f.close}}
[Edit] И у меня такое чувство, что есть еще кое-что, что нужно выжать ...
object G{def main(a:Array[String]){val f=new java.io.FileWriter("out.txt")
f.write(((1 to a(1).toInt):\(io.Source.fromFile(new java.io.File(a(0))).mkString)){(_,m)=>m.zipWithIndex.map{case(c,n)=>
val s=Seq(-83,-82,-81,-1,1,81,82,83)count(k=>k+n>=0&k+n<m.size&&m(k+n)=='X')
if(c=='\n')c else if(s==3|s==2&c=='X')'X'else'.'}.mkString})
f.close}}
Просто поигрался с решением BalusC. Ограниченная репутация означает, что я не мог добавить ничего в качестве комментария к его.
class M{public static void main(String[]a)throws Exception{int t=3240,j=t,i=new Integer(a[1])*t+t;char[]b=new char[i+t],p={1,80,81,82};for(new java.io.FileReader(a[0]).read(b,t,t);j<i;){char c=b[j],l=0;for(int n:p)l+=b[j+n]/88+b[j-n]/88;b[j+++t]=c>10?(l==3|l+c==90?88:'.'):c;}new java.io.FileWriter("out.txt").append(new String(b,j,t)).close();}}
Более читаемая (?) Версия:
class M{
public static void main(String[]a)throws Exception{
int t=3240,j=t,i=new Integer(a[1])*t+t;
char[]b=new char[i+t],p={1,80,81,82};
for(new java.io.FileReader(a[0]).read(b,t,t);j<i;){
char c=b[j],l=0;
for(int n:p)l+=b[j+n]/88+b[j-n]/88;
b[j+++t]=c>10?(l==3|l+c==90?88:'.'):c;
}
new java.io.FileWriter("out.txt").append(new String(b,j,t)).close();
}
}
Ruby 1.8: 178 175 символов
f,n=$*;b=IO.read f
n.to_i.times{s=b.dup
s.size.times{|i|t=([82,1,-80].map{|o|b[i-o,3]||''}*'').count 'X'
s[i]=t==3||b[i]-t==?T??X:?.if s[i]>13};b=s}
File.new('out.txt','w')<<b
Новые строки значимы (хотя все они могут быть заменены точками с запятой.)
Изменить: исправлен перевод строки выпуск и обрезал 3 символа.
Я мог бы значительно уменьшить это, но мне это нравится, так как он все еще находится на стадии приближения и довольно удобочитаем.
open System.IO
let mutable a:_[,]=null
let N y x=
[-1,-1;-1,0;-1,1;0,-1;0,1;1,-1;1,0;1,1]
|>Seq.sumBy(fun(i,j)->try if a.[y+i,x+j]='X' then 1 else 0 with _->0)
[<EntryPoint>]
let M(r)=
let b=File.ReadAllLines(r.[0])
a<-Array2D.init 40 80(fun y x->b.[y].[x])
for i=1 to int r.[1] do
a<-Array2D.init 40 80(fun y x->
match N y x with|3->'X'|2 when a.[y,x]='X'->'X'|_->'.')
File.WriteAllLines("out.txt",Array.init 40(fun y->
System.String(Array.init 80(fun x->a.[y,x]))))
0
РЕДАКТИРОВАТЬ
По запросу, вот мой следующий удар:
open System
let mutable a,k=null,Array2D.init 40 80
[<EntryPoint>]
let M r=
a<-k(fun y x->IO.File.ReadAllLines(r.[0]).[y].[x])
for i=1 to int r.[1] do a<-k(fun y x->match Seq.sumBy(fun(i,j)->try if a.[y+i,x+j]='X'then 1 else 0 with _->0)[-1,-1;-1,0;-1,1;0,-1;0,1;1,-1;1,0;1,1]with|3->'X'|2 when a.[y,x]='X'->'X'|_->'.')
IO.File.WriteAllLines("out.txt",Array.init 40(fun y->String(Array.init 80(fun x->a.[y,x]))))
0
Это снижение на 14% с некоторыми базовыми играми в гольф. Я не могу не чувствовать, что проигрываю, используя 2D-массив / массив строк, а не 1D-массив, но сейчас мне не хочется делать это преобразование. Обратите внимание, как я элегантно прочитал файл 3200 раз, чтобы инициализировать свой массив :)
f,n=$*
c=IO.read f
n.to_i.times{i=0;c=c.chars.map{|v|i+=1
v<?.?v:('...X'+v)[[83,2,-79].map{|j|c[i-j,3]}.to_s.count ?X]||?.}*''}
File.new('out.txt',?w)<<c
Изменить:
Обрабатывает символы новой строки на 4 символа меньше.
Можно удалить еще 7 ( v .? V:
), если вы разрешите ему стирать новые строки, когда живые ячейки достигают краев.
Пробелы добавлены для удобства чтения
a = {2, 2, 2};
s = Экспорт ["out.txt",
CellularAutomaton [{224, {2, {a, {2, 1, 2}, a}}, {1,1}},
(ReadList [# 1, Byte, RecordLists → 2> 1] - 46) / 42, # 2] 〚# 2〛
/. {0 → ".", 1 → "X"}, "Таблица"] &
Вызов с
s["c:\life.txt", 100]
Анимация:
Вы также можете получить график средней популяции с течением времени:
Хороший шаблон для создания планеров из Википедии
AFAIK Mathematica использует Cellular Automaton для генерации случайных чисел с использованием правила 30.
мой первый гольф код;)
#include<fstream>
#define B(i,j)(b[i][j]=='X')
int main(int i,char**v){for(int n=0;n<atoi(v[2]);++n){std::ifstream f(v[1]);v[1]="out.txt";char b[40][83];for(i=0;i<40;++i)f.getline(b[i],83);std::ofstream g("out.txt");g<<b[0]<<'\n';for(i=1;i<39;++i){g<<'.';for(int j=1;j<79;++j){int k=B(i-1,j)+B(i+1,j)+B(i,j-1)+B(i,j+1)+B(i-1,j-1)+B(i+1,j+1)+B(i+1,j-1)+B(i-1,j+1);(B(i,j)&&(k<2||k>3))?g<<'.':(!B(i,j)&&k==3)?g<<'X':g<<b[i][j];}g<<".\n";}g<<b[0]<<'\n';}}
Несколько переработанная версия, заменяющая часть логики поиском по таблице + несколько других мелких приемов:
#include<fstream>
#define B(x,y)(b[i+x][j+y]=='X')
int main(int i,char**v){for(int n=0;n<atoi(v[2]);++n){std::ifstream f(v[1]);*v="out.txt";char b[40][83], O[]="...X.....";for(i=0;i<40;++i)f>>b[i];std::ofstream g(*v);g<<b[0]<<'\n';for(i=1;i<39;++i){g<<'.';for(int j=1;j<79;++j){O[2]=b[i][j];g<<O[B(-1,0)+B(1,0)+B(0,-1)+B(0,1)+B(-1,-1)+B(1,1)+B(1,-1)+B(-1,1)];}g<<".\n";}g<<b[0]<<'\n';}}
Просто интересно, насколько меньше и уродливее мое java-решение могло бы быть на C. Уменьшается до 300, включая новые строки для бит препроцессора. Освобождает память ОС! Можно сэкономить ~ 20, если предположить, что ОС закроется и файл тоже будет сброшен.
#include<stdio.h>
#include<stdlib.h>
#define A(N)j[-N]/88+j[N]/88
int main(int l,char**a){
int t=3240,i=atoi(a[2])*t+t;
char*b=malloc(i+t),*j;
FILE*f;
fread(j=b+t,1,t,fopen(a[1],"r"));
for(;j-b-i;j++[t]=*j>10?l==3|l+*j==90?88:46:10)
l=A(1)+A(80)+A(81)+A(82);
fwrite(j,1,t,f=fopen("out.txt","w"));
fclose(f);
}
import System
main=do f:n:_<-getArgs;s<-readFile f;writeFile"out.txt"$t s$read n
p '\n'_='\n'
p 'X'2='X'
p _ 3='X'
p _ _='.'
t r 0=r
t r n=t[p(r!!m)$sum[1|d<-1:[80..82],s<-[1,-1],-m<=d*s,m+d*s<3240,'X'==r!!(m+d*s)]|m<-[0..3239]]$n-1
Хорошо, 210-символьный код - это своего рода обман.
#coding:l1
exec'xÚ=ŽA\nÂ@E÷sŠº1ƒÆscS‰ØL™Æª··âî¿GÈÿÜ´1iÖ½;Sçu.~H®J×Þ-‰Ñ%ª.wê,šÖ§J®d꘲>cÉZË¢V䀻Eîa¿,vKAËÀå̃<»Gce‚ÿ‡ábUt¹)G%£êŠ…óbÒüíÚ¯GÔ/n×Xši&ć:})äðtÏÄJÎòDˆÐÿG¶'.decode('zip')
Вероятно, вы не сможете скопировать и вставить этот код и заставить его работать. Предполагается, что это Latin-1 (ISO-8859-1), но я думаю, что где-то в процессе это было извращено в Windows-1252. Кроме того, ваш браузер может воспринимать некоторые символы, отличные от ASCII.
Так что, если это не сработает, вы можете сгенерировать файл из старых 7-битных символов:
s = """
23 63 6F 64 69 6E 67 3A 6C 31 0A 65 78 65 63 27 78 DA 3D 8E 41 5C 6E C2
40 0C 45 F7 73 8A BA 31 13 AD 83 15 11 11 C6 73 08 63 17 05 53 89 D8 4C
99 C6 AA B7 B7 AD E2 EE BF 47 C8 FF DC B4 31 69 D6 BD 3B 53 E7 75 2E 7E
48 AE 4A D7 DE 90 8F 2D 89 AD D1 25 AA 2E 77 16 EA 2C 9A D6 A7 4A AE 64
EA 98 B2 3E 63 C9 5A CB A2 56 10 0F E4 03 80 BB 45 16 0B EE 04 61 BF 2C
76 0B 4B 41 CB C0 E5 CC 83 03 3C 1E BB 47 63 65 82 FF 87 E1 62 55 1C 74
B9 29 47 25 A3 EA 03 0F 8A 07 85 F3 62 D2 FC ED DA AF 11 47 D4 2F 6E D7
58 9A 69 26 C4 87 3A 7D 29 E4 F0 04 74 CF C4 4A 16 CE F2 1B 44 88 1F D0
FF 47 B6 27 2E 64 65 63 6F 64 65 28 27 7A 69 70 27 29
"""
with open('life.py', 'wb') as f:
f.write(''.join(chr(int(i, 16)) for i in s.split()))
Результатом является допустимый 210-символьный исходный файл Python. Все, что я здесь сделал, - это использование сжатия zip в исходном коде Python. Настоящая уловка заключается в том, что в результирующей строке я использую символы, отличные от ASCII. Это все еще действующий код, он просто громоздкий.
Несжатая версия весит 234 символа, что, на мой взгляд, все еще неплохо.
import sys
f,f,n=sys.argv
e=open(f).readlines()
p=range
for v in p(int(n)):e=[''.join('.X'[8+16*(e[t][i]!='.')>>sum(n!='.'for v in e[t-1:t+2]for n in v[i-1:i+2])&1]for i in p(80))for t in p(40)]
open('out.txt','w').write('\n'.join(e))
Извините за горизонтальную прокрутку, но все перечисленные выше символы новой строки являются обязательными, и я посчитал их как один символ каждый.
Я бы не стал читать код игры в гольф. Имена переменных выбираются случайным образом для достижения наилучшего сжатия. Да я серьезно. Ниже следует версия с лучшим форматированием и комментариями:
# get command-line arguments: infile and count
import sys
ignored, infile, count = sys.argv
# read the input into a list (each input line is a string in the list)
data = open(infile).readlines()
# loop the number of times requested on the command line
for loop in range(int(count)):
# this monstrosity applies the rules for each iteration, replacing
# the cell data with the next generation
data = [''.join(
# choose the next generation's cell from '.' for
# dead, or 'X' for alive
'.X'[
# here, we build a simple bitmask that implements
# the generational rules. A bit from this integer
# will be chosen by the count of live cells in
# the 3x3 grid surrounding the current cell.
#
# if the current cell is dead, this bitmask will
# be 8 (0b0000001000). Since only bit 3 is set,
# the next-generation cell will only be alive if
# there are exactly 3 living neighbors in this
# generation.
#
# if the current cell is alive, the bitmask will
# be 24 (8 + 16, 0b0000011000). Since both bits
# 3 and 4 are set, this cell will survive if there
# are either 3 or 4 living cells in its neighborhood,
# including itself
8 + 16 * (data[y][x] != '.')
# shift the relevant bit into position
>>
# by the count of living cells in the 3x3 grid
sum(character != '.' # booleans will convert to 0 or 1
for row in data[y - 1 : y + 2]
for character in row[x - 1 : x + 2]
)
# select the relevant bit
& 1
]
# for each column and row
for x in range(80)
)
for y in range(40)
]
# write the results out
open('out.txt','w').write('\n'.join(data))
Извините, Pythonistas, за форматирование скобок C-ish, но я пытался прояснить, что закрывает каждая скобка.
Следующее решение использует мой собственный язык программирования, специфичный для домена, который я назвал NULL:
3499538
Если вам интересно, как это работает: Мой язык состоит только из одного утверждения на программу. Это утверждение представляет собой идентификатор потока StackOverflow, принадлежащий потоку code golf. Мой компилятор компилирует это в программу, которая ищет лучшее решение javascript (с SO API), загружает его и запускает в веб-браузере.
Время выполнения могло бы быть лучше для новых потоков (может потребоваться некоторое время, чтобы появился первый проголосовавший Javascript-ответ), но, с другой стороны, это требует лишь очень небольших навыков кодирования.
Синтаксис функции: (124 символа)
Вот более легкая для чтения версия (с ненужными символами новой строки и пробелами, добавленными для лучшего форматирования):
function l(f,N),
b=char(importdata(f))>46;
for c=1:N,
b=~fix(filter2(ones(3),b)-b/2-3);
end;
dlmwrite('out.txt',char(b*42+46),'')
И вот как программа запускается из Командного окна MATLAB:
l('in.txt',100)
Синтаксис команды: (130 символов)
После комментария о вызове функций с помощью синтаксиса команд, я копнул немного глубже и обнаружил, что функции MATLAB могут фактически вызывать с формат командной строки (с некоторыми ограничениями). Ты узнаешь что-то новое каждый день!
function l(f,N),
b=char(importdata(f))>46;
for c=1:eval(N),
b=~fix(filter2(ones(3),b)-b/2-3);
end;
dlmwrite('out.txt',char(b*42+46),'')
И вот как программа запускается из командного окна MATLAB:
l in.txt 100
Я подумал, ради забавы, я посмотрю, смогу ли я вместо этого выгрузить вывод в файл GIF текстового файла, сохраняя при этом количество символов ниже 140 (т. е. «чирикать»). Вот красиво отформатированный код:
function l(f,N),
b=char(importdata(f))>46;
k=ones(3);
for c=1:N+1,
a(:,:,:,c)=kron(b,k);
b=~fix(filter2(k,b)-b/2-3);
end;
imwrite(~a,'out.gif')
Хотя IMWRITE должен создавать GIF, который по умолчанию зацикливается бесконечно, мой GIF зацикливается только один раз. Возможно, это ошибка, которая была исправлена в более новых версиях MATLAB. Итак, чтобы анимация длилась дольше и было легче увидеть этапы эволюции, я оставил для задержки кадра значение по умолчанию (которое, кажется, составляет около полсекунды).Вот результат в формате GIF с использованием шаблона Gosper Glider Gun :
b
изменена с логического (т. Е. «Логического») типа. к числовому, чтобы избавиться от нескольких преобразований. ~~ b + 0
на b / 42
и заменил 'то же'
на 's'
в качестве аргумента для CONV2 (и, на удивление, он все еще работал!). b
обратно в логическую матрицу. b
и переработана логика цикла, чтобы сохранить 1 дополнительный символ. cell2mat
на char
, сохранив 4 символа. Спасибо, Эрик! с таким же успехом может сдвинуть с мертвой точки ...
import sys
_,I,N=sys.argv;R=range(3e3);B=open(I).read();B=set(k for k in R if'A'<B[k])
for k in R*int(N):
if k<1:b,B=B,set()
c=sum(len(set((k+o,k-o))&b)for o in(1,80,81,82))
if(c==3)+(c==2)*(k in b):B.add(k)
open('out.txt','w').write(''.join('.X\n'[(k in B)-(k%81<1)]for k in R))
Один из классических шаблонов
***
..*
.*
Мой аватар был создан с использованием моей версии Игры Жизни с использованием этого шаблона и правила (обратите внимание, что это не 23/3):
#D Thanks to my daughter Natalie
#D Try at cell size of 1
#R 8/1
#P -29 -29
.*********************************************************
*.*******************************************************.*
**.*****************************************************.**
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
****************************.*.****************************
***********************************************************
****************************.*.****************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
**.*****************************************************.**
*.*******************************************************.*
.*********************************************************
IMHO - как я узнал «Игру жизни» Конвея, уловка заключалась не в написании короткого кода, а в коде, который мог быстро создавать сложные формы жизни. Используя классический образец выше и обернутый мир из 594 441 ячейки, лучшее, что я мог когда-либо сделать, было около 1000 поколений в секунду.
Другой простой узор
**********
.
................*
.................**
................**.......**********
И планеры
........................*...........
......................*.*...........
............**......**............**
...........*...*....**............**
**........*.....*...**..............
**........*...*.**....*.*...........
..........*.....*.......*...........
...........*...*....................
............**......................
Что, записей о Perl еще нет?
$i=pop;@c=<>;@c=map{$r=$_;$u='';for(0..79)
{$K=$_-1;$R=$r-1;$u.=((&N.(&N^"\0\W\0").&N)=~y/X//
|(substr$c[$r],$_,1)eq'X')==3?'X':'.';}$u}keys@c for(1..$i);
sub N{substr$c[$R++],$K,3}open P,'>','out.txt';$,=$/;print P@c
Запустите с:
conway.pl infile #times
Еще одна попытка на Java, 361 символ
class L{public static void main(final String[]a)throws Exception{new java.io.RandomAccessFile("out.txt","rw"){{int e=88,p[]={-1,1,-80,80,-81,81,-82,82},s=3240,l=0,i=new Byte(a[1])*s+s,c;char[]b=new char[s];for(new java.io.FileReader(a[0]).read(b);i>0;seek(l=++l%s),i--){c=b[l];for(int n:p)c+=l+n>=0&l+n<s?b[l+n]/e:0;write(c>13?(c==49|(c|1)==91?e:46):10);}}};}}
И немного более читабельно
class L {
public static void main(final String[]a) throws Exception {
new java.io.RandomAccessFile("out.txt","rw"){{
int e=88, p[]={-1,1,-80,80,-81,81,-82,82},s=3240,l=0,i=new Byte(a[1])*s+s,c;
char[] b = new char[s];
for (new java.io.FileReader(a[0]).read(b);i>0;seek(l=++l%s),i--) {
c=b[l];
for (int n:p)
c+=l+n>=0&l+n<s?b[l+n]/e:0;
write(c>13?(c==49|(c|1)==91?e:46):10);
}
}};
}
}
Очень похоже на версию Molehill. Я пытался использовать другой FileWriter и считать соседей ячейки без дополнительной переменной.
К сожалению, RandomAccessFile
- довольно длинное имя, и требуется передать режим доступа к файлу.
R 340 символов
cgc<-function(i="in.txt",x=100){
require(simecol)
z<-file("in.txt", "rb")
y<-matrix(data=NA,nrow=40,ncol=80)
for(i in seq(40)){
for(j in seq(80)){
y[i,j]<-ifelse(readChar(z,1) == "X",1,0)
}
readChar(z,3)
}
close(z)
init(conway) <- y
times(conway)<-1:x
o<-as.data.frame(out(sim(conway))[[100]])
write.table(o, "out.txt", sep="", row.names=FALSE, col.names=FALSE)
}
cgc()
Я чувствую, что это немного жульничество иметь дополнительный пакет, который делает фактические автоматы для вас, но я иду на это, потому что мне все еще пришлось возиться с матрицами и прочим, чтобы прочитать в файле с 'X' вместо 1.
Это мой первый "кодовый гольф", интересно....
list(,$n,$l) = $_SERVER["argv"];
$f = file( $n );
for($j=0;$j<$l;$j++){
foreach($f as $k=>$v){
$a[$k]="";
for($i=0;$i < strlen( $v );$i++ ){
$t = 0;
for($m=-1;$m<2;$m++){
for($h=-1;$h<2;$h++){
$t+=ord($f[$k + $m][$i + $h]);
}
}
$t-=ord($v[$i]);
$a[$k] .= ( $t == 494 || ($t == 452 && ord($v[$i])==88)) ? "X" : "." ;
}
}
$f = $a;
}
file_put_contents("out.txt", implode("\n", $a ));
Я уверен, что это можно улучшить, но мне было любопытно, как это будет выглядеть в PHP. Может быть, это вдохновит кого-то, у кого есть немного больше опыта игры в код-гольф.
MUMPS: 314 символов
L(F,N,R=40,C=80)
N (F,N,R,C)
O F:"RS" U F D C F
.F I=1:1:R R L F J=1:1:C S G(0,I,J)=($E(L,J)="X")
F A=0:1:N-1 F I=1:1:R F J=1:1:C D S G(A+1,I,J)=$S(X=2:G(A,I,J),X=3:1,1:0)
.S X=0 F i=-1:1:1 F j=-1:1:1 I i!j S X=X+$G(G(A,I+i,J+j))
S F="OUT.TXT" O F:"WNS" U F D C F
.F I=1:1:R F J=1:1:C W $S(G(N,I,J):"X",1:".") W:J=C !
Q