Порахуйте загальні моделі життя


21

Завдання тут полягає в тому, щоб прочитати з .rleфайлу Golly або Plaintext (на ваш вибір), ім'я якого файлу надано (на STDIN або як аргумент командного рядка) та визначити та підрахувати загальні шаблони в закодованій в ньому сітці.

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

Ваша програма повинна вміти визначати та розрізняти принаймні п’ятнадцять найпоширеніших суворих натюрмортів та п’ять найпоширеніших генераторів , а також планери .

Усі фази цих осциляторів повинні бути розпізнані, як і всі чотири фази планера.

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

Шаблони, що входять до складу інших шаблонів, що підраховуються, не повинні рахуватися. (наприклад, 8-елементна фаза маяка також не повинна вважатися двома блоками, а корабельна зв'язка також не повинна вважатися двома кораблями)

Ви можете припустити, що вхід вже стабілізується і не містить шаблонів, не в аформованому наборі. Ви також можете припустити, що вхідна сітка поміститься у вікні 1024x1024.

Це , тому найкоротша програма виграє.

Опис формату файлу RLE

Файл RLE містить сітку життя, закодовану довжиною. Усі рядки, що починаються з #коментарів, повинні бути проігноровані.

Перший не порожній рядок без коментарів має форму x=<width>,y=<height>,rule=<rule>. Для цілей цього завдання завжди буде правило B3/S23. Він може містити пробіли, які слід викреслити перед обробкою цього рядка (звичайно, цей рядок взагалі не потрібно обробляти.)

Рядки без коментарів після першого слід розглядати як єдиний рядок. Він повинен складатися лише з десяткових цифр, символів $, bі oта розривів рядків, а не закінчуватись цифрою. Розриви рядків слід ігнорувати, але ви можете припустити, що розриви рядків не перебиватимуть рядки цифр.

Це може бути припинено одним !.

bявляє собою мертву клітинку, oявляє собою живу клітинку і $представляє кінець ряду. Будь-яке десяткове число вказує на те, що наступний символ слід розглядати як такий, що повторюється багато разів.

Кодування зразкового тексту

Інший варіант - прочитати візерунок в іншому форматі простого тексту, описаному тут. У цьому кодуванні клітини представлені дефісами, а на клітинках представлені великими літерами Os, з новими рядками, що розділяють рядки.

Ви можете припустити, що всі рядки без коментарів будуть зафіксовані однаковою довжиною з дефісами.

Рядки, що починаються з !коментарів, повинні бути проігноровані.

Деякі тестові випадки

ПРАВИЛА:

#This is a comment
x = 35, y = 16, rule = B3/S23
bo$2o$obo5$22bo$22bo$22bo2$18b3o3b3o2$22bo$22bo10b2o$22bo10b2o!

Простий текст:

!This is a comment
-O---------------------------------
OO---------------------------------
O-O--------------------------------
-----------------------------------
-----------------------------------
-----------------------------------
-----------------------------------
----------------------O------------
----------------------O------------
----------------------O------------
-----------------------------------
------------------OOO---OOO--------
-----------------------------------
----------------------O------------
----------------------O----------OO
----------------------O----------OO

Результати:

Glider 1
Blinker 4
Block 1

ПРАВИЛА:

x = 27, y = 15, rule = B3/S23
5b2o$5b2o9$11bo$o9bobo$o9bobo$o10bo12b3o!
#Here's a comment at the end

Простий текст:

-----OO--------------------
-----OO--------------------
---------------------------
---------------------------
---------------------------
---------------------------
---------------------------
---------------------------
---------------------------
---------------------------
-----------O---------------
O---------O-O--------------
O---------O-O--------------
O----------O------------OOO
!Here's a comment at the end

Результати:

Block 1
Blinker 2
Beehive 1

ПРАВИЛА:

#You may have multiple comments
#As shown here
x = 13, y = 11, rule = B3/S23
2o$2o2$12bo$12bo$12bo$2b2o$2b2o4b2o$7bo2bo$7bobo$8bo!

Простий текст:

!You may have multiple comments
!As shown here
OO-----------
OO-----------
-------------
------------O
------------O
------------O
--OO---------
--OO----OO---
-------O--O--
-------O-O---
--------O----

Результати:

Block 2
Blinker 1
Loaf 1

ПРАВИЛА:

# Pentadecathlon
# Discovered by John Conway
# www.conwaylife.com/wiki/index.php?title=Pentadecathlon
x = 10, y = 3, rule = B3/S23
2bo4bo2b$2ob4ob2o$2bo4bo!

Простий текст:

! Pentadecathlon
! Discovered by John Conway
! www.conwaylife.com/wiki/index.php?title=Pentadecathlon
--O----O--
OO-OOOO-OO
--O----O--

Результати:

Pentadecathlon 1

Бонус

Якщо ви підтримуєте обидва вхідні формати (використовуючи розширення файлу [ .rleдля файлів rle та .cellsдля простого тексту - як не визначено інші розширення], або прапор командного рядка для їх розрізнення), ви можете відняти 5% від вашої оцінки.


Як щодоOOO.OO\n....OO
Акангка

@ChristianIrwan Ну, це не є стійкою схемою, тому ви все одно не отримаєте її як вклад.
SuperJedi224

Відповіді:


13

Haskell, 2417 байт

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

Примітки:

  • Він приймає лише формат простого тексту, переданий STDIN
  • Це займає щось на кшталт часу O (n ^ 20)
  • Я припускав, що кількість символів у рядках без коментарів є постійною (у межах конкретного введення), як це відбувається у прикладах
  • Найбільш божевільний трюк полягав у тому, як шаблони розпаковуються, витягуючи елементи в позиціях (номер стовпця) за модулем (довжина виводу) для створення масиву.

Він поєднує в собі кілька основних ідей:

  • візерунки та симетрії можна попередньо обчислити
  • один шаблон може бути упакований у ціле число, з розмірами відомих
  • знайти всі підматриці легко
  • порахувати рівності легко

Ось код:

r=[1..20]
a!0=a!!0
a!x=tail a!(x-1)
u[_,x,y,l]=[[odd$div l$2^i|i<-[0..y],mod i x==j]|j<-[0..x-1]]
main=interact(\s->let q=[map(=='O')l|l<-lines s,l!0/='!']in let g=[i|i<-[[[0,3,11,3339,0,4,11,924,0,4,11,3219,0,3,11,1638,1,4,15,19026,1,4,15,9636,2,3,11,1386,2,4,11,1686,3,7,48,143505703994502,3,7,48,26700311308320,3,7,48,213590917399170,3,7,48,8970354435120,4,2,3,15,5,3,8,171,5,3,8,174,5,3,8,426,5,3,8,234,6,4,15,36371,6,4,15,12972,6,4,15,51313,6,4,15,13644,6,4,15,50259,6,4,15,12776,6,4,15,51747,6,4,15,6028,7,4,15,26962,7,4,15,9622,7,4,15,19094,7,4,15,27044,8,5,24,9054370,8,5,24,2271880,9,4,15,51794,9,4,15,13732,9,4,15,19027,9,4,15,9644,10,4,19,305490,10,5,19,206412,10,5,19,411942,10,4,19,154020,11,3,8,427,11,3,8,238,12,6,35,52217012547,12,6,35,3306785328,13,3,8,170,14,3,8,428,14,3,8,458,14,3,8,107,14,3,8,167,14,3,8,482,14,3,8,302,14,3,8,143,14,3,8,233,14,3,8,241,14,3,8,157,14,3,8,286,14,3,8,370,14,3,8,181,14,3,8,115,14,3,8,346,14,3,8,412,15,4,15,51219,15,4,15,12684,15,4,15,52275,15,4,15,13260,16,1,2,7,16,3,2,7,17,3,29,313075026,17,10,29,139324548,17,3,23,16252911,17,8,23,16760319,17,5,49,152335562622276,17,10,49,277354493774076,17,7,69,75835515713922895368,17,10,69,138634868908666122360,17,9,89,135722011765098439128942648,17,10,89,58184575467336340020006960,17,5,59,160968502306438596,17,12,59,145347113669124612,17,5,59,524156984170595886,17,12,59,434193401052698118,17,5,69,164495599269019571652,17,14,69,222245969722444385292,17,5,69,517140479305239282702,17,14,69,222262922122170485772,17,3,47,83020951028178,17,16,47,39740928107556,17,3,35,62664969879,17,12,35,40432499049,17,3,41,1581499314234,17,14,41,1293532058322,17,3,41,4349006881983,17,14,41,3376910168355,17,3,47,92426891685930,17,16,47,83780021865522,17,3,47,79346167206930,17,16,47,11342241794640,18,13,168,166245817041425752669390138490014048702557312780060,18,15,224,1711376967527965679922107419525530922835414769336784993839766570000,18,13,168,141409121010242927634239017227763246261766273041932,19,2,7,126,19,4,7,231,19,4,7,126,19,2,7,189,19,4,15,24966,19,4,15,18834,19,4,15,10644,19,4,15,26646]!p|p<-[h..h+3]]|h<-[0,4..424]],j<-[[[q!y!x|x<-[a..a+c]]|y<-[b..b+d]]|c<-r,d<-r,a<-[0..(length$q!0)-c-1],b<-[0..length q-d-1]],u i==j]in show[(words"aircraftcarrier barge beehive biloaf1 block boat eater1 loaf longbarge longboat mango ship shiptie tub glider beacon blinker pentadecathlon pulsar toad"!(e!0),sum[1|f<-g,e!0==f!0])|e<-g])

Ось код Mathematica, який використовується для упаковки масиву 0,1 у формат, розпакований пізніше програмою haskell:

rotate[m_]:=Transpose[Map[Reverse,m]]
findInversePermutation[m_]:=Block[{y=Length[First[m]], x=Length[m]}, InversePermutation[FindPermutation[Flatten[m], Flatten[Table[Table[Flatten[m][[i+1]], {i, Select[Range[0, x * y - 1], Mod[#, x]==j&]}], {j, 0, x - 1}]]]]]
enumShape[m_]:=Partition[Range[1, Length[Flatten[m]]], Length[m[[1]]]]
pack[m_]:={Length[rotate[rotate[m]]], Length[Flatten[rotate[rotate[m]]]], FromDigits[Permute[Flatten[rotate[rotate[m]]], findInversePermutation[enumShape[rotate[rotate[m]]]]], 2]}

Ось набагато більш повне скасування коду:

range = [1..16]          -- all of the patterns fall within this range

list ! 0        = list !! 0           -- this is a simple generic (!!)
list ! position = (tail list) ! (position - 1)

unpack [_, unpackedLength, unpackedSize, packed] = [ [odd $ div packed (2^i) | i <- [0..unpackedSize], (mod i unpackedLength) == j] | j <- [0..unpackedLength - 1]]

main=interact doer

doer input = show $ tallyByFirst (words nameString) foundPatterns -- this counts equalities between the list of patterns and the submatrices of the input
  where
    parsed = parse input -- this selects the non-comment lines and converts to an array of Bool's
    foundPatterns = countOccurrences partitioned subArrays
    subArrays     = allSubArrays parsed
    partitioned   = modPartition compressed 428 4 -- this partitions the compressed patterns into the form [name number, x length, x length * y length, packed integer]

countOccurrences patterns subArrays = [pattern | pattern <- patterns, subArray <- allSubArrays q, unpack pattern == subArray]

subArray m offsetX subSizeX offsetY subSizeY = [[m ! y ! x | x <- [offsetX..offsetX + subSizeX]] | y <- [offsetY..offsetY + subSizeY]]

allSubArrays m = [subArray m offsetX subSizeX offsetY subSizeY | subSizeX <- range, subSizeY <- range, offsetX <- [0.. (length $ head m) - subSizeX - 1], offsetY <- [0..(length m) - subSizeY - 1]]

tallyByFirst names list = [ (names ! (a ! 0), sum [1 | a <- list, (head a) == (head b)]) | b <- list]

parse string = [map (=='O') line | line <- lines string, head line /= '!']

modPartition list chunksize = [ [list ! position | position <- [offset..offset + chunksize - 1]] | offset <- [0, chunksize..(length list) - chunksize]]

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

Це більш ніж вражаюче, +1!
кіт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.