일반적인 삶의 게임 패턴 계산


21

여기서 작업은 .rle파일 이름이 제공 되는 Golly 또는 일반 텍스트 파일 (선택한 파일) (STDIN 또는 명령 줄 인수로)을 읽고 그 안에 인코딩 된 그리드에서 공통 패턴을 식별하고 계산하는 것입니다.

또는 파일의 내용을 STDIN을 통해 직접 제공하도록 선택할 수도 있습니다.

귀하의 프로그램은 최소한 15 개의 가장 일반적인 엄격한 정물5 개의 가장 일반적인 오실레이터글라이더 를 식별하고 구별 할 수 있어야합니다 .

글라이더의 모든 4 단계와 마찬가지로이 발진기의 모든 단계를 인식해야합니다.

각 패턴의 최종 개수와 각 패턴의 이름과 수량을 별도의 줄에 포함하는 목록을 출력해야합니다. 프로그램은 이러한 모든 패턴 또는 하나 이상을 찾은 패턴을 출력 목록에 포함 할 수 있습니다.

계산되는 다른 패턴의 일부인 패턴은 계산되지 않아야합니다. (예를 들어, 비콘의 8 셀 단계는 2 개의 블록으로 계산되어서는 안되며, 선박 타이는 2 개의 선박으로 간주되어서는 안됩니다)

입력이 이미 안정화되었으며 위에서 언급 한 세트에없는 패턴이 없다고 가정 할 수 있습니다. 입력 그리드가 1024x1024 상자에 맞는다고 가정 할 수도 있습니다.

이것은 이므로 가장 짧은 프로그램이 승리합니다.

RLE 파일 형식 설명

RLE 파일에는 실행 길이 인코딩 된 라이프 그리드가 있습니다. 로 시작하는 모든 줄 #은 주석이므로 무시해야합니다.

비어 있지 않은, 주석이없는 첫 줄은 형식 x=<width>,y=<height>,rule=<rule>입니다. 이 작업의 목적 상 규칙은 항상입니다 B3/S23. 이 행을 처리하기 전에 제거해야하는 공백이 포함될 수 있습니다 (물론이 행을 전혀 처리 할 필요는 없습니다).

첫 줄 이후의 주석이 아닌 행은 단일 문자열로 처리해야합니다. 이것은 단지 소수점 숫자, 문자로 구성되어야합니다 $, b그리고 o, 줄 바꿈 및 숫자로 끝나지 않을 것입니다. 줄 바꿈은 무시해야하지만 줄 바꿈이 문자열을 방해하지 않는다고 가정 할 수 있습니다.

이것은 단일로 종료 될 수 있습니다 !.

b는 죽은 셀을 o나타내고 라이브 셀을 $나타내며 행의 끝을 나타냅니다. 십진수는 다음 기호가 여러 번 반복되는 것으로 취급됨을 나타냅니다.

평문 패턴 인코딩

다른 옵션은 여기에 설명 된 다른 일반 텍스트 형식으로 패턴을 읽는 것입니다. 이 인코딩에서 오프 셀은 하이픈으로 표시되고 온 셀은 대문자 Os로 표시되며 줄 바꿈은 행으로 구분됩니다.

주석이 아닌 모든 행은 하이픈으로 같은 길이로 채워 진다고 가정 할 수 있습니다.

로 시작하는 줄 !은 주석이므로 무시해야합니다.

일부 테스트 사례

RLE :

#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

RLE :

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

RLE :

#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

RLE :

# 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

보너스

입력 형식을 모두 지원 하는 경우 (파일 확장자 [ .rlerle 파일 및 .cells다른 확장자를 읽는 방법은 정의되지 않음] 또는 명령 줄 플래그를 사용하여 구별 할 수 있음)를 사용하면 점수에서 5 %를 뺄 수 있습니다.


어떻습니까OOO.OO\n....OO
Akangka

@ChristianIrwan 글쎄, 그건 안정적인 패턴이 아니기 때문에 어쨌든 입력으로 주어지지 않을 것입니다.
SuperJedi224

답변:


13

하스켈, 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])

다음은 haskell 프로그램에서 압축을 푼 형식으로 0.1의 배열을 포장하는 데 사용되는 Mathematica 코드입니다.

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 이상으로 인상적입니다!
고양이
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.