⍝⍝ ⍟⍟⍟⍟⍟⍟⍟⍟⍟⍟⍟ CONWAY'S GAME OF LIFE ⍟⍟⍟⍟⍟⍟⍟⍟⍟⍟⍟⍟⍟⍟ ⍝⍝
_life←{((⍵×9)+⊃+/+/¯1 0 1∘.⊖¯1 0 1∘.⌽⊂⍵)∊⍺}
life←{12 13 3 _life ⍵}
mylife←{((⍵×9)+⊃+/+/¯1 0 1∘.⊖¯1 0 1∘.⌽⊂⍵)∊12 13 3}
⍝ Dyalog APL:
⎕io←0
⎕ml←3
⍝ NGN APL (and Dyalog):
zborder← ({⍉⊖{⌈/0⌷⍵:(-1 0+⍴⍵)↑⍵⋄⍵}{⌈/0⌷⍵:⍵⋄1↓⍵}⍵}⍣4){(3 3⌈(⍴⍵))↑⍵}
⍝ запобігти помилці порожнього поля⍝
zbordertl← ({⍉{⌈/0⌷⍵:(-1 0+⍴⍵)↑⍵⋄⍵}{⌈/0⌷⍵:⍵⋄1↓⍵}⍵}⍣2){(-2 2⌈(⍴⍵))↑⍵}
zborderv← ({⊖{⌈/0⌷⍵:(-1 0+⍴⍵)↑⍵⋄⍵}{⌈/0⌷⍵:⍵⋄1↓⍵}⍵}⍣2){(3 1⌈(⍴⍵))↑⍵}
zborderh←{⍉zborderv⍉⍵}
inf←{ ⍺⍺ zborder ⍵}
__play←{map←⍵ ⋄ ⍺⍺ {⊂'.≢'[( ⍺⍺ ⍣⍵) map]}¨⍺}
_play←{map←⍵ ⋄ ⍺⍺ {⊂'.≢'[zborder ( ⍺⍺ ⍣⍵) map]}¨⍺}
inflife←mylife zborder
_inflife←{⍺ _life zborder ⍵}
play←{map←⍵ ⋄ {⊂'.≢'[zborder (inflife⍣⍵) map]}¨⍺}
play_←{(⊂⍵)∘.{⍺⍺ zborder (inflife⍣⍵) ⊃⍺}⍺} ⍝ те ж саме, але з можливістю задавати зовнішній вигляд функцією
_play_←{map←⍵ ⋄ ⍵⍵¨⍺⍺ {⊂zborder ( ⍺⍺ ⍣⍵) map}¨⍺}
⍝ NARS2000:
⎕io←0
rep←{⍺>0:⍺⍺((⍺-1)⍺⍺ ∇∇ ⍵)⋄ ⍵} ⍝ замінник відсутнього в цій реалізації оператора ⍣
⍝ N f rep A ←→ (f⍣N)A
zborder←{4 {⍉⊖{(- (↑⌈/⍵) 0+⍴⍵)↑⍵}{(~↑⌈/⍵) 0↓⍵}⍵} rep (3 3⌈(⍴⍵))↑⍵}
inflife←{mylife zborder ⍵}
play←{map←⍵ ⋄ {⊂'∘≢'[zborder ⍵ inflife rep map]}¨⍺}
⍝ GNU APL:
⎕io←0
zborder←{({⍉⊖{(- (↑⌈/⍵) 0+⍴⍵)↑⍵}{(~↑⌈/⍵) 0↓⍵}⍵}⍣4) (3 3⌈(⍴⍵))↑⍵}
inflife←{mylife zborder ⍵}
play←{(⊂⍵)∘.{⊂'.≢'[zborder (inflife⍣⍵) ⊃⍺]}⍺}
bplay←{(⊂⍵)∘.{braille zborder (inflife⍣⍵) ⊃⍺}⍺}
⍝ ⍺⍺ — несумісно з GNU APL, ⍶ — несумісно з NARS2000 та Dyalog. Що робити?
⍝ нижче — код для NGN APL (має також працювати в Dyalog)
⍝ перетворення з форматів:
bitmap←{⍺⍴⍉(16⍴2)⊤⍵}
⍝ http://conwaylife.com/wiki/RLE
⍝ видубути патерн:
⍝ викинути коментарі та параметри, об'єднати в один рядок, звільнити від пробілів та тексту після ! ......
⍝ розбити по $
⍝ перетв. рядок виду ob99o99b на вираз 1,0,(99⍴1),(99⍴0)
⍝ обчислити вирази, зв'язати все в матрицю
rle←{⍎⍎"«'⊃(⊂", ⍵, ")'.replace(/!/, '').replace(/([0-9]+)\$/g, '),(($1-1)⍴0),(⊂').replace(/\$/g,'),(⊂').replace(/([0-9]+)([ob])/g, ',($1⍴$2)').replace(/o/g,',1').replace(/b/g,',0')»"}⍝NGN APL only!
⍝ TODO: to_rle:
⍝ remove all final 'b' before each '$'.......
⍝ replace last '$' with '!'....
{,'$',⍨'bo'[⍵]}
⍝ number of repeats...
⍝ TODO: http://www.conwaylife.com/wiki/Apgsearch_format .....
⍝ конструктори фігур:
over←{max←(⍴⍺)⌈⍴⍵⋄(max↑⍺) ⍺⍺ max↑⍵}
join←∨over
without←∧∘~over
shift←{(- ⍺+⍴⍵)↑⍵}
grow←{(⍺+⍴⍵)↑⍵}
symmv←⊢⍪⊖
symmh←⊢,⌽
symm4←symmv symmh
oddv←{(y x)←(⍴⍵)÷¯2 ⋄ y⊖1 0↓y⊖⍵}
oddh←{(y x)←(⍴⍵)÷¯2 ⋄ x⌽0 1↓x⌽⍵}
odd4←{(y x)←(⍴⍵)÷¯2 ⋄ x⌽y⊖1 1↓x⌽y⊖⍵}
oddsymmv←oddv symmv
oddsymmh←oddh symmh
oddsymm4←odd4 symm4
symmd←⍉join⊢
dsymm←⊢∨(⌽⊖)
rdsymm←dsymm (⊢join(⌽⍉))
dsymmv←⌽⍪⊖
dsymmh←⊖,⌽
rsymm←{dsymmv(⊢,(⍉⊖))(¯1 1×(⌽⍴⍵)⌈⍴⍵)↑⍵}
stair←{(n y x)←⍺ ⋄ n≤1:⍵ ⋄ ⍵ join y x shift (n-1) y x∇⍵}
fuse←{(n y x)←⍺ ⋄ (head mid tail)←⍵ ⋄ head join (y x+(⍴head) - ⍴mid) shift ⌽⊖(⌽⊖tail) join (y x+(⍴tail) - ⍴mid)shift ⊖⌽n y x stair mid}
agar←{⍉(⌽⍺)⍴⍉⍺[0] (⍴⍵)[1]⍴⍵}⍝ ⍺ — в кількості клітинок
eight←{{(⍉⍵),⍉⌽⍵}(⍵ ⍵⍴1),⍵ ⍵⍴0}
mkship←{⊃(3⍴1)(1 0 0 1),(⍵⍴1),⊂(0 1)}⍝ 2≤⍵≤4
pyramid←{oddsymmv⊃1⍴⍨¨1+⍳⍵}
triangle←{⊃1⍴⍨¨1+⍳⍵}
diag←{⍵ ⍵⍴1,⍵⍴0} ⍝ ←→ {=/¨⍳2⍴⍵}
⍝ допоміжні прийоми:
halfv←{(⌈2 1÷⍨⍴⍵)↑⍵}¨
halfh←{(⌈1 2÷⍨⍴⍵)↑⍵}¨
⍝ обрамлення клітинок таблиці:
cross←{(¯1↓⍵)⍪'-++'['-|+'⍳,¯1↑⍵]}
border←{(×⍺){(⌽⍣⍺[1])((cross⊖)⍣(2-⍺[0]))({⌽⍵,'|'}⍣(2-⍺[1]))({⊖⍵⍪'-'}⍣(2-⍺[0]))⍵}⍵}
justify←{⍵↑⍨¨⊃{(⌈/⍺)∘.,(⌈⌿⍵)}/⊂[0 1]⊃⍴¨⍵}⍕¨
boxed←{⊃⍪/,/((⍳⍴)border¨justify)⍵}
⍝ Брайль для відображення великих мап
⍝ підгнати розмір до кратного сітці брайлеформ
⍝ розбити на підмасиви 4х2
⍝ кожен підмасив вирівняти в лінію й переставити цифри для відповідності з кодами символів
⍝ 1 4 (де 1 — молодший біт, 8 — старший біт)
⍝ 2 5
⍝ 3 6
⍝ 7 8
⍝ перекодувати підмасиви в числа, далі {⎕ucs 0x2800+⍵}:
braille←{{⎕ucs 10240+(8⍴2)⊥(,⍵)[7 6 5 3 1 4 2 0]}¨{⊂[1 3](4÷⍨0⌷⍴⍵) 4 (2÷⍨1⌷⍴⍵) 2⍴⍵}⍵↑⍨4 2×⌈4 2÷⍨⍴⍵}
bplay←{(⊂⍵)∘.{braille zborder (inflife⍣⍵) ⊃⍺}⍺}
unbraille←{⊃⍪/,/{⍵[4 2⍴7 4 6 3 5 2 1 0]}¨{(8⍴2)⊤⍵}¨{⍵×(⍵<256)∧⍵≥0}¯10240+⎕ucs ⍵}⍝ перетв. назад у матрицю 0-в та 1-ць. ⢺→4 2⍴0 1 1 1 0 1 0 1
⍝ TODO: turn45deg (45° поворот для карт, де всі події відбуваються на діагональній лінії)......
⍝ TODO: косий зріз (для більш компактного відображення серії ходів в аналогічному випадку — кращий варіант).....
⍝ norm — нормалізація патерну:
⍝ позбутися нулів навколо, повернути ширшою стороною по горизонталі, з усіх варіантів відображення вибрати той, де на початку було більше одиниць
norm←{⊃(↑∘⍒⌷⊢) {⍵,⊖¨⍵}{⍵,⌽¨⍵} ⊂{(⍉⍣(>/⍴⍵))⍵}1 1↓¯1¯1↓zborder⍣≡⍵}
⍝ unnorm — повернути вектор top left bottom right vmirr hmirr transp для перетворення нормалізованої форми в поточну.....
⍝ TODO: декомпозиція/пошук патернів у патернах...
⍝ TODO: collide — випадково комбінувати вибрані фігури, виявляти результати за заданим критерієм....
⍝ TODO: brief - ф-я для скороченого відображення завеликих фігур.....
gliderL←⊃1(1 0 1)(1 1)
gliderY←⊃(1 0 1)(1 1)(0 1)
gun←⊃(0 0 0 0 1 1)(0 0 0 0 1 1)0 0 0 0 0 0 0 0(0 0 0 1 1 1)(0 0 1 0 0 0 1)(0 1 0 0 0 0 0 1)(0 1 0 0 0 0 0 1)(0 0 0 0 1)(0 0 1 0 0 0 1)(0 0 0 1 1 1)(0 0 0 0 1) 0 0 (0 0 0 0 0 1 1 1)(0 0 0 0 0 1 1 1)(0 0 0 0 1 0 0 0 1)0(0 0 0 1 1 0 0 0 1 1)0 0 0 0 0 0 0 0 0(0 0 0 0 0 0 1 1)(0 0 0 0 0 0 1 1)
prepulsar←⊃9⍴6↑3⍴(1 1 1)(1 0 1)
prepulsar1←⊃0(11⍴6↑5⍴1)
clock←⊃(0 0 1)(1 1)(0 0 1 1)(0 1)
biclock←clock join (-3 3+⍴clock)↑clock
queenbee←⊃(1 1 0 0 0 1 1)(0 0 1 1 1)(0 1 0 0 0 1)(0 0 1 0 1)(0 0 0 1)
eater1←4 4 bitmap 0x31E8
eater2←rle'3bob2o$b3ob2o$o6b$b3ob2o$3bobob$3bobob$4bo!'
eater3←rle'9b2ob$4b2o2bo2bo$bo2bo4bobo$obobo5bob$bo2bob2o4b$4bo2bo4b$5bo4bob$6b5ob2$8bo3b$7bobo2b$8bo!'
eater4←rle'3b2o9b$3bo10b$2obo10b$o2b2o9b$b2o4bo6b$3b5o6b$3bo4b2o4b$4b2o2bo5b$6bobo5b$6bobobo2bo$7b2ob4o$9bo4b$9bobo2b$10b2o!'
eater5←rle'7b2o$3bo3b2o$2bobo4b$bobo5b$bo7b$2o!'
corder←⊖⍉6 4 bitmap 0x2509 0xC800 ⍝ corder engine, switch engine
rpento←⊃(0 1 1)(1 1)(0 1)
century←'*'=⊃'..**' '***' '.*'
herschel←4 3↑unbraille'⠗⡆'
bhepto←rle'ob2o$3ob$bo!'