Имитация любого 1D клеточного автомата

14

Соревнование

Вы должны написать полную программу, которая берет семь чисел из STDIN и печатает двумерную историю клеточного автомата (CA) в STDOUT. Это код гольф.

Форматирование ввода На входе будет семь целых чисел / строк, разделенных запятыми. Первое число - это номер правила в соответствии с кодом Wolfram (стандартное имя для каждого правила). Второе - начальная начальная конфигурация. Третий и четвертый описывают, какой шаблон и сколько раз он должен быть добавлен слева от начальной конфигурации. в качестве дополнения. Пятый и шестой делают то же самое для правой стороны. Последнее число - это число поколений, которые запускают симуляцию.

Итак, пример ввода 90,11,0,4,0,4,5. Это должно сказать вашей программе, что вы используете правило 90 . Он также должен сообщить программе, что вы хотите, чтобы начальная конфигурация была 11со строкой, 0добавленной 4 раза к обоим концам, поэтому фактический начальный шаблон - это 0000110000. Это также говорит вашей программе запускать эту симуляцию в течение 5 поколений.

Выходные данные Ваша программа должна печатать весь массив ячеек каждого поколения (разделенных новыми строками), чтобы выходные данные представляли собой диаграмму пространства-времени ЦС. Для каждого поколения состояние каждой ячейки определяется ее состоянием и состояниями ячеек непосредственно слева и справа в соответствии с правилом, предоставленным в качестве входных данных. Симуляция должна обтекать края. Первое, что должно быть напечатано, это начальный массив как gen. 0.

Ввод 90,11,0,4,0,4,5должен привести к следующему выводу как можно точнее.

0000110000
0001111000
0011001100
0111111110
1100000011
0110000110

Обратите внимание, что начальное состояние не входит в пять поколений. Также обратите внимание, что симуляция оборачивается по краям.

Больше примеров

вход:

184,1100,01,2,01,1,4

выход:

0101110001
1011101000
0111010100
0110101010
0101010101

вход:

0,1011,1,0,0,1,2

выход:

10110
00000
00000

Больше информации о том, как работает 1D CA и как они пронумерованы

PhiNotPi
источник
Хорошо сделано для включения правила 0 в качестве контрольного примера.
Питер Тейлор
Я очарован тем, что правило 90 - это прокладка Серпинского. Тем более, что это было частью тестирования, которое я провел для другого проекта Codegolf .
JoeFish
@JoeFish Именно твое изображение заставило меня попробовать этот. Я хотел ответить 8086 - убить 2 птиц - но, вероятно, потребуются строковые операции, поэтому мой эмулятор не сможет его запустить (пока).
luser droog 13.12.12
Кто-то уже сделал это: pouet.net/prod.php?which=60478
luser droog 18.12.12

Ответы:

5

Golfscript, 77 73 70 символов

','/)~\(~:?;~~*@@~*@+\+{1&}/]({[.,{.[3<?256+]{2base}/\~=\(+}*])n@)\+}*

Спасибо @Howard, который указал, как сохранить 4 символа.

Питер Тейлор
источник
Вы можете сохранить очевидный 48--> 1&и я думаю, что еще три. Вы можете опустить )перед блоком (не увеличивать счетчик) и, следовательно, также сохранить последние два всплывающих окна.
Говард
@ Говард, спасибо. Эти всплывающие окна в конце были полезны на более ранней итерации, но вы правы, что их устранение имеет смысл сейчас.
Питер Тейлор
5

APL (153 символа)

∇ cellularautomaton
  i               ← ⍞
  s               ← (i=',') / ⍳ ⍴i
  (b a x c)       ← {i[s[⍵]↓⍳s[⍵+1]-1]} ¨ ⍳4
  (z x x l x r n) ← ⍎i
  y               ← ⍎ ¨ ⊃ ,/ (l / ⊂a) , b , r / ⊂c
  (n+1) (⊃⍴,y) ⍴ '01'[1+⊃ ,/ y,{({(z ⊤⍨ 8/2)[8 - 2⊥¨ 3 ,/ (⊃⌽⍵),⍵,⊃⍵]}⍣⍵)y} ¨ ⍳n]
∇

И в менее читаемой, немного более короткой форме:

i←⍞⋄s←(i=',')/⍳⍴i⋄b a x c←{i[s[⍵]↓⍳s[⍵+1]-1]}¨⍳4⋄z x x l x r n←⍎i⋄y←⍎¨⊃,/(l/⊂a),b,r/⊂c⋄'01'[1+⊃,/y,{({(z⊤⍨8/2)[8-2⊥¨3,/(⊃⌽⍵),⍵,⊃⍵]}⍣⍵)y}¨⍳n]⍴⍨(1+n),⊃⍴,y

Пример:

      cellularautomaton
26,00110,01,4,10,6,7
0101010100110101010101010
1000000011100000000000001
0100000110010000000000011
0010001101101000000000110
0101011001000100000001101
0000010110101010000011000
0000100100000001000110100
0001011010000010101100010

Я уверен, что есть возможности для улучшения (я даже обнаружил несколько изменений при написании этого поста!), Но некоторые из них могут повлечь за собой фундаментальные изменения, и я не могу больше смотреть на APL. Используемый здесь вариант APL - Dyalog APL .

Диллон Кауэр
источник
4

Рубин, 165 159 знаков

a=gets.split ?,
b=a.map &:to_i
c=(x=a[2]*b[3]+a[1]+a[4]*b[5]).chars.map &:hex
(0..b[6]).map{puts c*''
c=(1..w=x.size).map{|i|b[0]>>c[i-1]*2+c[i%w]+c[i-2]*4&1}}

Изменить: я нашел несколько мест для небольших улучшений.

Пример выполнения:

> 30,1,0,20,0,20,20
00000000000000000000100000000000000000000
00000000000000000001110000000000000000000
00000000000000000011001000000000000000000
00000000000000000110111100000000000000000
00000000000000001100100010000000000000000
00000000000000011011110111000000000000000
00000000000000110010000100100000000000000
00000000000001101111001111110000000000000
00000000000011001000111000001000000000000
00000000000110111101100100011100000000000
00000000001100100001011110110010000000000
00000000011011110011010000101111000000000
00000000110010001110011001101000100000000
00000001101111011001110111001101110000000
00000011001000010111000100111001001000000
00000110111100110100101111100111111100000
00001100100011100111101000011100000010000
00011011110110011100001100110010000111000
00110010000101110010011011101111001100100
01101111001101001111110010001000111011110
11001000111001111000001111011101100010001
Говард
источник
3

С 303 305 301 294 292

305 Редактировать: упс. Забыл, что calloc()требуется два аргумента. Это было взрывом на большем входе.

301 Редактировать: Ах, ха! Использовал мою calloc()бу-бу, чтобы сохранить еще 2 байта, увеличив размер блока запрошенной памяти.

294 Редактировать: Сломал 300! Устранен один из strcat()s и подправлен несколько петель. Нужно использовать максимальный хруст, который так же весело, как и использовать.

292 Редактировать: не требуется +2выделение памяти.

Я использовал ответ luser droog в качестве базовой идеи, но изменил алгоритм обтекания, а также много настроек и вычленения констант.

r,A,C,n,j;main(){char*s,*p,*t,a[9],b[9],c[9];scanf("%d,%[01],%[01],%d,%[01],%d,%d",&r,b,a,&A,c,&C,&n);for(s=calloc(A+++C,9);A--;)strcat(s,A?a:b);for(;C--;)strcat(s,c);p=strdup(s);for(C=strlen(s);A++<n;puts(s),t=p,p=s,s=t)for(j=C;j--;)p[j]=(1<<(s[j?j-1:C-1]*4+s[j]*2+s[(j+1)%C])-336)&r?49:48;}

r,A,C,n,j;
main(){
    char*s,*p,*t,a[9],b[9],c[9];
    scanf("%d,%[01],%[01],%d,%[01],%d,%d",&r,b,a,&A,c,&C,&n);
    for(s=calloc(A+++C,9);A--;)
        strcat(s,A?a:b);
    for(;C--;)
        strcat(s,c);
    p=strdup(s);
    for(C=strlen(s);A++<n;puts(s),t=p,p=s,s=t)
        for(j=C;j--;)
            p[j]=(1<<(s[j?j-1:C-1]*4+s[j]*2+s[(j+1)%C])-336)&r?49:48;
}

Screenshot1

screenshot2

JoeFish
источник
1
Вы забыли, чтобы это началось C,A,! :)
luser droog
для нагрузки памяти, а что brk()? тогда p=s+C+1;где-то.
luser droog
1
+1 снова за использование +++!
Люсер Дрог
Ха - ха! Изменить все %[01]на %s! -9 (... много лет спустя)
Люзер Дрог
1
@luserdroog это не работает, потому что% s жадный и ест запятые и другие цифры.
JoeFish
2

C (487 484 418 с удаленными пробелами)

* Отбросил 66 с помощью JoeFish *

C,A,r,n,j;main(){char*s,*p,*t,a[9],b[9],c[9];
    scanf("%d,%[01],%[01],%d,%[01],%d,%d",&r,b,a,&A,c,&C,&n);
    s=malloc(strlen(a)*A+strlen(b)+strlen(c)*C+3);*s=0;
    strcat(s,"0");
    for(;A--;)strcat(s,a);
    strcat(s,b);
    for(;C--;)strcat(s,c);
    strcat(s,"0");
    p=malloc((C=strlen(s)-1)+2);
    for(;n--;){
    *s=s[C-1];
    s[C]=0;
    puts(s+1);
    s[C]=s[1];
    for(j=1;s[j+1];j++)
        p[j]=(1<<(s[j-1]-48)*4+(s[j]-48)*2+s[j+1]-48)&r?49:48;
    t=p;p=s;s=t;
    }
    s[C]=0;
    puts(s+1);
}

машинопись

Джош @ Z1 ~
$! м
сделать ок
cc ca.c -o ca
ca.c: 1: 1: предупреждение: определение данных не имеет типа или класса хранения
ca.c: В функции 'main':
ca.c: 2: 5: предупреждение: несовместимое неявное объявление встроенной функции 'scanf'
ca.c: 3: 7: предупреждение: несовместимое неявное объявление встроенной функции 'malloc'
ca.c: 3: 14: предупреждение: несовместимое неявное объявление встроенной функции 'strlen'
ca.c: 4: 5: предупреждение: несовместимое неявное объявление встроенной функции 'strcat'

Джош @ Z1 ~
$ echo 90,11,0,4,0,4,5 | Калифорния
-bash: ca: команда не найдена

Джош @ Z1 ~
$ echo 90,11,0,4,0,4,5 | ./ca
0000110000
0001111000
0011001100
0111111110
1100000011
0110000110

Люзер Дрог
источник
Ницца. Вы можете сбрить немало байтов, сделав intпеременные глобальными и удалив #include: r,A,B,C,n,i,j; main(){char *s...
JoeFish
Сохраните кучу в своих forциклах:for(;A--;)strcat(s,a);
JoeFish
И повторно Aи Cпозже, так что вам не нужно декларировать iили Bвообще. p=malloc((C=strlen(s))+1); --C; strcpy(p,s); for(A=0;A<n;A++){Извините, я сейчас остановлюсь :)
JoeFish
Хорошо, я солгал, еще один. Избавьтесь от 2 бай, устраняя --C;:p=malloc((C=strlen(s)-1)+2); . Я думаю, что код игры в гольф веселее, чем придумывать его в первую очередь!
JoeFish
Я не был уверен в удалении, #includeтак как scanfэто вариативно. Но это, вероятно, нормально, так как он вызывается только один раз. ... Моя старая машина умерла вчера, и я все еще устанавливаю Cygwin. Я включу эти изменения, как только смогу их протестировать. Благодарность!
luser droog 13.12.12