폴리 스트립 계산


18

폴리 스트립은 다음 규칙을 따르는 폴리 노 미노의 하위 집합입니다.

  • 각 조각은 하나 이상의 셀로 구성됩니다.
  • 어떤 셀도 두 개 이상의 이웃을 가질 수 없습니다
  • 세포는 구멍을 둘러싸 지 않아야합니다

유리 폴리 아미노는 다른 것 (픽업 및 뒤집을 수있는 조각)의 엄격한 변형 (번역, 회전, 반사 또는 글라이드 반사)이 없을 때 구별됩니다. 유리 폴리오 미노를 반영, 번역, 회전, 반사 또는 글라이드는 모양이 변경되지 않습니다 ( Wikipedia )

예를 들어 30 개의 무료 헵타 스트립 (길이가 7 인 폴리 스트립)이 있습니다. 14x15 그리드에 모두 포함되어 있습니다.

헵타 스트립

이미지 크레디트 : Miroslav Vicher

양의 정수 n를 입력으로 사용하고 별개의 자유 n폴리 스트립을 열거 하는 프로그램 / 함수를 작성하십시오 .

  • n = 1-> 1 (단일 사각형)

  • n = 2-> 1 (2 개의 정사각형으로 구성된 2 개의 폴리 스트립은 하나만 가능합니다)

  • n = 3-> 2 (하나는 선으로 연결된 3 개의 사각형으로 구성되고 다른 하나는 L 자 모양으로 구성됨)

  • n = 4-> 3 (한 개의 직선, 한 개의 L 자형 및 한 개의 Z 자형)

  • . . .

테스트 사례 :

n   polystrips

1   1
2   1
3   2
4   3
5   7
6   13
7   30
8   64
9   150
10  338
11  794
12  1836
13  4313
14  10067
15  23621

채점

이것은 이므로 짧은 코드가 좋습니다. 알고리즘과 코드에 대한 자세한 설명을 높이 평가합니다.

J의 부분 참조 구현

각 조각을 "벡터"형식으로 설명하기로 결정하고 n- 폴리 스트립 조각을 설명하기 위해 n-2 블록 만 필요합니다 (1 개의 2- 폴리 스트립 만 있고 명시 적으로 반환됩니다). 블록은 상대 방향을 설명합니다. 0-변경 없음; 1-좌회전; 2-우회전. 어느 방향으로 시작할 것인지는 중요하지 않지만 다음 셀을 어디에 놓아야하는지 나타냅니다. 연속적인 0은 여러 개가있을 수 있지만 1과 2는 항상 단일입니다. 이 구현은 구멍을 고려하지 않기 때문에 부분적입니다. n> 6에 대한 솔루션은 구멍이있는 조각도 계산합니다.

온라인으로 사용해보십시오!


1
관련 OEIS. (그러나 구멍을 배제하지 않는다.)
마틴 청산을

@ Martin Ender 감사합니다. 몰랐습니다.
Galen Ivanov

2
확실하게, 나는 당신이 구멍으로 계산되는 중심과 한 모서리를 제외하고 3x3 격자를 채울 경우 ( 101010샘플 표기법에서)?
Ton Hospel

@Ton Hospel 네, 정확히 – 이것은 구멍이있는 유일한 헵타 스트립 조각입니다.
Galen Ivanov

1
아마도 math.SE에 대한 좋은 질문 일 것입니다.
Jonah

답변:


12

파이썬 3 , 480 433 406 364 309 299 295 바이트

내 PPCG 경력을 시작하기에 좋은 시점처럼 보였습니다.

def C(s):
 S,*a={''},0,1;n=d=r=1
 for c in s:d=c*d*1jor d;n+=d;a+=n,;r*=not{n}&S;x,*a=a;S|={x+t+u*1jfor t in A for u in A}
 return r
from itertools import*;A=-1,0,1;n,y=int(input())-2,0;x={*filter(C,product(*[A]*n))}
while x:s=x.pop();S=*(-u for u in s),;x-={s[::-1],S,S[::-1]}-{s};y+=1
print(y)

온라인으로 사용해보십시오!

편집 :

  • 인라인 DX, 골프 가능 지점을 약간 조정했습니다.
  • 더 많은 트릭, 주로 세트 관련 트릭을 적용했습니다.
  • 프로그램 형식으로 변경되었으며 임의의 숫자 대신 복소수를 사용하도록 변경되었습니다 m. (복잡한 숫자는 실제로 강력하지만 종종 무시되는 골프 기능입니다. xnor의 솔루션에서 다른 도전에 맞게 조정되었습니다 )
  • LFR문자열 표현을 -1,0,1튜플로 변경하고 미친 양의 바이트 축소 (!)에 대한 실행 시간을 희생했습니다. 이제 솔루션은 이론적으로 정확하지만 결과를 15로 출력하기 전에 시간 초과됩니다.
  • Jonathan Frech 덕분에 루프를 한 줄로 나눈 다음 계산을위한 훨씬 더 나은 대안을 찾았습니다 r. 마지막으로 300 바이트 미만 !!!
  • 놀랍게도 1j파서 (-2B)를 혼동하지 않고 다른 것에 고착 할 수 있으며, not우선 순위 (2B)는 미미합니다.

더 이상 사용되지 않는 버전 (480 바이트) :

def C(s):
 m=999;a=[0,1];n=d=1
 D={'F':{},'L':{1:m,m:-1,-1:-m,-m:1},'R':{1:-m,-m:-1,-1:m,m:1}}
 X=lambda x:{x+~m,x-m,x-m+1,x-1,x,x+1,x+m-1,x+m,x-~m}
 for c in s:
  d=D[c].get(d,d);n+=d;a+=n,
  if n in set().union(*map(X,a[:-3])):return 0
 return 1
def f(n):
 if n<3:return 1
 x={*'LF'}
 for _ in range(3,n):x={s+c for s in x for c in({*'LRF'}-{s[-1]})|{'F'}}
 y={*x}
 for s in x:
  if s in y:S=s.translate(str.maketrans('LR','RL'));y-={s[::-1],S,S[::-1]}-{s}
 return sum(map(C,y))

온라인으로 사용해보십시오!

주석이 달린 언 골프 솔루션 :

t = str.maketrans('LR','RL')

# hole checking function
def check(s):
    m = 999   # (imaginary) board size enough to fit all generated polyominoes
    a = [0,1] # previous path
    n = 1     # current cell
    d = 1     # current direction
    # dict for direction change
    D = {'F':{}, 'L':{1:m, m:-1, -1:-m, -m:1}, 'R':{1:-m, -m:-1, -1:m, m:1}}
    # used to 'blur' all cells in path into 3x3
    X = lambda x: {x-m-1,x-m,x-m+1,x-1,x,x+1,x+m-1,x+m,x+m+1}
    for c in s:
        d = D[c].get(d,d) # change direction
        n += d            # move current cell
        # the polyomino has a hole if the current cell touches previous cells (including diagonally; thus the blurring function)
        if n in set().union(*map(X,a[:-2])): return False
        a.append(n)       # add current cell to the path
    return True

# main function
def f(n):
    if n < 3: return 1
    x = {*'LF'}
    # generate all polystrips using the notation similar to the reference
    for _ in range(3, n): x = {s+c for s in x for c in ({*'LRF'}-{s[-1]})|{'F'}}
    y = {*x}
    # remove duplicates (mirror, head-to-tail, mirror of head-to-tail) but retain self
    for s in x:
        if s in y:
            S = s.translate(t)
            y -= {s[::-1], S, S[::-1]} - {s}
    # finally filter out holey ones
    return sum(map(check,y))

온라인으로 사용해보십시오!

m = 999은 모든 것을 계산하는 데 시간이 걸리고 계산하기 위해 이미 ~ 8 초가 걸리기 때문에 선택됩니다 n = 1..15. 99 대신 1 바이트를 저장하는 것이 좋습니다. 더 이상 필요하지 않으며 복잡한 숫자가 내장되어 있기 때문에 임의의 입력 크기에 맞도록 보장됩니다.


5
PPCG에 오신 것을 환영합니다! PPCG 경력을 시작하기위한 확실한 방법입니다. :)
Martin Ender

3
PPCG에 오신 것을 환영합니다.이 솔루션에 감사드립니다! 나는 이미 해결책을 기대하고 포기했다 :)
Galen Ivanov

3
내 PPCG 경력을 시작하기에 좋은 점처럼 보였다 (또는하지?) . 글쎄, 이것은 놀랍게도 우리 대부분이 생각조차 못했을 정도로 놀랄만 한 짧은 해결책이며, ungolfed 버전도 놀랍도록 단순 해 보이지만 어쩌면 이것이 PPCG 경력을 시작하는 평균적인 방법일까요? :)
Outgolfer Erik

1
@Erik 그 라인은 반 농담이었습니다. :) 그래, 해결책은 나에게 놀랍 습니다. 원래 제출에서 ~ 36 % 감소를 끌어낼 것으로 기대하지 않았습니다.
Bubbler 2019


4

APL (Dyalog Unicode) , 70 65 바이트

+/{∧/2≤|(⊢-¯3↓¨,\)+\0 1\0j1*⍵}¨∪{(⊃∘⍋⊃⊢)(⊢,⌽¨)⍵(-⍵)}¨2-,⍳2↓⎕⍴3

온라인으로 사용해보십시오!

Adám 덕분에 아래 코드의 전체 프로그램 버전입니다.


APL (Dyalog Unicode) , 70 바이트

{+/{∧/2≤|(⊢-¯3↓¨,\)+\0 1\0j1*⍵}¨∪{(⊃∘⍋⊃⊢)(⊢,⌽¨)⍵(-⍵)}¨2-,⍳3⍴⍨0⌈⍵-2}

온라인으로 사용해보십시오!

작동 원리

위의 코드는 다음 정의와 같습니다.

gen←{2-,⍳3⍴⍨0⌈⍵-2}
canonicalize←{(⊃∘⍋⊃⊢)(⊢,⌽¨)⍵(-⍵)}
test←{(∧/⊢{∧/2≤|⍺-¯3↓⍵}¨,\)+\0 1\0j1*⍵}
{+/test¨∪canonicalize¨gen⍵}

이것은 파이썬 솔루션처럼 작동하지만 다른 순서로 작동합니다. 그것은 gen로지로 LFR길이를 -strips n-2, canonicalize각 스트립 s가 얻어 nique 스트립, test그 자체가 접촉하는 경우, 각 스트립 S (1 접촉 그렇지 않으면, 그렇지 않으면 0)을 가산 +/부울 결과.

gen

{2-,⍳3⍴⍨0⌈⍵-2}
{            }   ⍵←input number n
        0⌈⍵-2    xmax(0, n-2)
     3⍴⍨         x copies of 3
   ,⍳            multi-dimensional indexes; x-th cartesian power of [1,2,3]
                 (`⍳` gives x-dimensional hypercube; `,` flattens it)
 2-              compute 2-k for each k in the array

 in each strip, ¯1, 0, 1 corresponds to R, F, L respectively

canonicalize

{(⊃∘⍋⊃⊢)(⊢,⌽¨)⍵(-⍵)}
{                  }   ⍵←single strip
              ⍵(-⍵)    nested array of  and its LR-flip
        (⊢,⌽¨)         concatenate their head-to-tail flips to the above
 (⊃∘⍋  )               find the index of the lexicographically smallest item
     ⊃⊢                take that item

test

{(∧/⊢{∧/2≤|⍺-¯3↓⍵}¨,\)+\0 1\0j1*⍵}
{                                  }   ⍵←single strip
                              0j1*⍵    power of i; direction changes
                            ×\         cumulative product; directions
                        0 1,     initial position(0) and direction(1)
                      +\         cumulative sum; tile locations
 (  ⊢{           }¨,\)    test with current tile(⍺) and all tiles up to ⍺(⍵):
             ¯3↓⍵         x←⍵ with last 3 tiles removed
           ⍺-             relative position of each tile of x from 
        2≤|               test if each tile of x is at least 2 units away
      ∧/                  all(...for each tile in x)
  ∧/         all(...for each position in the strip)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.