Đếm đa nang


18

Polystrips là tập hợp con của đa giác tuân theo các quy tắc sau:

  • mỗi mảnh bao gồm 1 hoặc nhiều ô
  • không có tế bào nào có thể có nhiều hơn hai hàng xóm
  • các tế bào không được bao quanh một lỗ

Đa giác tự do là khác biệt khi không có sự biến đổi cứng nhắc (dịch, xoay, phản xạ hoặc phản xạ trượt) của một số khác (các mảnh có thể được nhặt và lật lên). Dịch, xoay, phản xạ hoặc lướt qua phản ánh một polyomino tự do không thay đổi hình dạng của nó ( Wikipedia )

Ví dụ, có 30 heptastrips miễn phí (polystrips có chiều dài 7). Dưới đây là tất cả chúng, được đóng gói thành một lưới 14x15.

Heptastrips

Tín dụng hình ảnh: Miroslav Vicher

Mục tiêu

Viết chương trình / hàm lấy một số nguyên dương nlàm đầu vào và liệt kê các đa thức tự do riêng biệt n.

  • n = 1 -> 1 (Một hình vuông)

  • n = 2 -> 1 (Chỉ có một 2 polystrip có thể được tạo thành từ 2 hình vuông)

  • n = 3 -> 2 (Một hình gồm 3 hình vuông được nối thành một dòng và hình kia có hình chữ L)

  • n = 4 -> 3 (Một hình thẳng, một hình chữ L và một hình chữ Z)

  • . . .

Các trường hợp thử nghiệm:

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

Chấm điểm

Đây là , vì vậy mã ngắn hơn là tốt hơn. Tôi sẽ đánh giá rất cao những giải thích chi tiết về thuật toán và mã.

Thực hiện tham chiếu một phần trong J

Tôi quyết định mô tả từng mảnh theo định dạng "vectơ" và tôi chỉ cần các khối n-2 để mô tả một mảnh n-polystrip (chỉ có 1 2-polystrip và nó được trả lại rõ ràng). Các khối mô tả hướng tương đối: 0 - không thay đổi; 1 - rẽ trái; 2 - rẽ phải. Không quan trọng người ta sẽ bắt đầu theo hướng nào mà chỉ cho biết vị trí của ô tiếp theo. Có thể có bất kỳ số 0 liên tiếp nào, nhưng 1 và 2 luôn luôn là số đơn. Việc triển khai này là một phần, vì nó không tính đến các lỗ - các giải pháp cho n> 6 cũng tính các phần có lỗ.

Hãy thử trực tuyến!


1
OEIS có liên quan. (Nhưng không loại trừ lỗ hổng.)
Martin Ender

@ Martin Ender Cảm ơn bạn, tôi không biết điều đó.
Galen Ivanov

2
Để chắc chắn, tôi giả sử rằng nếu bạn điền vào lưới 3x3 ngoại trừ tâm và một góc cũng được tính là một lỗ ( 101010trong ký hiệu mẫu của bạn)?
TonMedel 17/2/18

@TonMedel Vâng, chính xác - đây là mảnh heptastrip duy nhất có lỗ.
Galen Ivanov

1
Có lẽ một câu hỏi hay cho môn toán.SE
Jonah

Câu trả lời:


12

Python 3 , 480 433 406 364 309 299 295 byte

Trông giống như một điểm tốt để bắt đầu sự nghiệp PPCG của tôi (hay không?).

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)

Hãy thử trực tuyến!

Chỉnh sửa:

  • Nội tuyến DX, và điều chỉnh một chút về một số điểm có thể chơi được.
  • Áp dụng nhiều thủ thuật, chủ yếu liên quan đến thiết lập.
  • Thay đổi thành dạng chương trình và thay đổi thành sử dụng số phức thay vì số tùy ý m. (Số phức thực sự là một tính năng mạnh mẽ nhưng thường bị bỏ qua; được điều chỉnh từ giải pháp của xnor cho một thách thức khác )
  • Đã thay đổi LFRbiểu diễn chuỗi thành -1,0,1bộ dữ liệu và hy sinh thời gian thực hiện để giảm lượng byte điên cuồng (!). Bây giờ giải pháp là đúng về mặt lý thuyết nhưng hết thời gian chờ trước khi đưa ra kết quả cho 15.
  • Một vòng lặp nhờ Jonathan Frech, sau đó tôi tìm thấy sự thay thế tốt hơn nhiều cho việc tính toán r . CUỐI CÙNG DƯỚI 300 BYTES !!!
  • Đáng ngạc nhiên là 1jcó thể dính vào bất cứ điều gì khác mà không gây nhầm lẫn cho trình phân tích cú pháp (-2B) và notcó mức độ ưu tiên cực kỳ thấp (-2B).

Phiên bản lỗi thời (480 byte):

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))

Hãy thử trực tuyến!

Giải pháp lộn xộn với ý kiến:

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))

Hãy thử trực tuyến!

m = 999được chọn vì phải mất thời gian theo cấp số nhân để tính tất cả mọi thứ và đã mất ~ 8 giây để tính toán n = 1..15. Có lẽ thật tốt khi tiết kiệm 1 byte bằng cách sử dụng 99 thay thế. Chúng tôi không cần điều này nữa, và bây giờ nó được đảm bảo là chính xác cho kích thước đầu vào tùy ý, nhờ số phức được tích hợp sẵn.


5
Chào mừng đến với PPCG! Chắc chắn là một cách ấn tượng để bắt đầu sự nghiệp PPCG của bạn. :)
Martin Ender

3
Chào mừng bạn đến với PPCG và cảm ơn giải pháp này! Tôi đã từ bỏ mong đợi để xem một giải pháp :)
Galen Ivanov

3
Trông giống như một điểm tốt để bắt đầu sự nghiệp PPCG của tôi (hay không?) . Chà, đây là một giải pháp ngắn đáng ngạc nhiên cho hầu hết chúng ta thậm chí sẽ không bao giờ nghĩ được, ngay cả phiên bản không có vẻ đơn giản đến đáng ngạc nhiên, nhưng, có lẽ đây là một cách trung bình để bắt đầu sự nghiệp PPCG của bạn, phải không? :)
Erik the Outgolfer 24/218

1
@Erik Dòng đó là một nửa trò đùa :) Nhưng vâng, giải pháp thậm chí còn gây ngạc nhiên cho tôi - Tôi không bao giờ mong đợi bản thân sẽ rút ra ~ 36% so với gửi ban đầu.
Bong bóng


4

APL (Dyalog Unicode) , 70 65 byte

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

Hãy thử trực tuyến!

Phiên bản chương trình đầy đủ của mã bên dưới, nhờ Adám.


APL (Dyalog Unicode) , 70 byte

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

Hãy thử trực tuyến!

Làm thế nào nó hoạt động

Mã ở trên tương đương với định nghĩa sau:

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

Điều này hoạt động giống như giải pháp Python, nhưng theo một thứ tự khác. Nó generates LFR-strips chiều dài n-2, canonicalizelà mỗi dải, có dải nique, testlà mỗi dải nếu nó chạm vào bản thân (1 nếu không chạm vào, 0 nếu ngược lại), và tóm tắt +/kết quả boolean.

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)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.