Biến mảng boolean 2D thành đa giác (trực tuyến)


8

Thử thách

Viết chương trình, đưa ra một mảng boolean 2 chiều (tương đương, một bitmap đơn sắc), đưa ra một loạt các đa giác mô tả đường viền của khu vực đó là đúng true (1).

Đầu vào được cung cấp dưới dạng một chuỗi các ký tự '#'(băm), ' '(dấu cách) và \n(dòng mới). Các dòng có thể khác nhau về chiều dài, trong trường hợp các phần bị thiếu được coi là khoảng trắng. Đầu ra phải là một danh sách đa giác (được phân tách bằng dòng mới), mỗi đa giác được biểu thị bằng một danh sách tọa độ (được phân tách bằng dấu phẩy).

Ví dụ & Yêu cầu

  1. Các tọa độ phải được liệt kê theo thứ tự chiều kim đồng hồ. Đầu vào:

    #
    

    Đầu ra chấp nhận được bao gồm:

    (0,0), (1,0), (1,1), (0,1)
    
    (1,0), (1,1), (0,1), (0,0)
    
    (1,1), (0,1), (0,0), (1,0)
    
    (0,1), (0,0), (1,0), (1,1)
    
  2. Các vùng khác nhau phải trả lại nhiều đa giác. Đầu vào:

    # #
    

    Ví dụ đầu ra (đầu ra thực tế phải bao gồm hai dòng):

    (0,0), (1,0), (1,1), (0,1)
    (2,0), (3,0), (3,1), (2,1)
    
  3. Các lỗ trong đa giác phải được liệt kê dưới dạng đa giác riêng biệt, nhưng theo thứ tự ngược chiều kim đồng hồ. Đầu vào:

    ###
    # #
    ###
    

    Ví dụ đầu ra:

    (0,0), (3,0), (3,3), (0,3)
    (1,1), (1,2), (2,2), (2,1)
    
  4. Bạn có thể tự do lựa chọn các đỉnh liền kề theo đường chéo có tham gia hay không. Đầu vào:

    #
     #
    

    Ví dụ đầu ra:

    (0,0), (1,0), (1,1), (0,1)
    (1,1), (2,1), (2,2), (1,2)
    

    hoặc là

    (0,0), (1,0), (1,1), (2,1), (2,2), (1,2), (1,1), (0, 1)
    
  5. Các danh sách tọa độ không cần phải tối ưu ngắn. Ví dụ:

    ##
    

    Đầu ra chấp nhận được:

    (0,0), (2,0), (2,1), (0,1)
    
    // Redundant coordinates along a straight line are acceptable
    (0,0), (1,0), (2,0), (2,1), (1,1), (0,1)
    
    // Duplicate start- and end-point are acceptable
    (0,0), (2,0), (2,1), (0,1), (0,0)
    

Như thường lệ, chương trình ngắn nhất thắng Thắng.


1
Bạn có thể giải thích hệ quả của điểm 5? Tôi thấy nó rất phản trực giác.
Peter Taylor

nếu bạn nói rằng trong một hình vuông AB trên CD thì BC luôn được kết nối và AD luôn bị ngắt kết nối sẽ phù hợp, nhưng dường như bạn đang nói (thực tế) rằng các hình vuông không thực sự là hình vuông và hình dạng của chúng thay đổi một cách tinh tế khi bạn chuyển đổi # thành không gian hoặc ngược lại.
Peter Taylor

Tôi đã thêm một vài thẻ để giúp phân loại con thú này. [tối ưu hóa đầu ra] được dự định đại diện cho bạn với điều kiện "Danh sách tọa độ không cần phải ngắn gọn tối ưu" và tôi sẽ rất vui nếu ai đó có thể tìm thấy biểu thức tốt hơn cho nó.
dmckee --- ex-moderator mèo con

Tôi đã nới lỏng các điều kiện một chút, vì vậy liệu những thứ liền kề theo đường chéo có tham gia hay không bây giờ là tùy chọn. Tôi cũng đã xóa các bình luận của mình để bảo vệ các yêu cầu cũ.
Timwi

Câu trả lời:


3

Perl, 345 311 265 ký tự

s!.!$i{$x++}=$&eq'#'!ge,$x=$r+=64for<>;sub a{$d+=@_||3;$d%=4;$y=$x%64;$z=$x>>6;$c.=", ($y,$z)";}for$x(keys%i){if($c=!$v{$x}&$i{$x}&!$i{$x-1}){$i{($x+=(1,64)[$d^3])-(64,65,1)[$d]}?$i{$x-(65,1,0,64)[$d]}?a 1:($x-=(64,1)[$d]):a while$d||!$v{$x}++;print substr$c.$/,3}}

Hạn chế

Giả sử rằng đầu vào không rộng hơn 64 ký tự (nhưng về nguyên tắc, chiều cao của nó không bị ràng buộc). Điều này có thể được mở rộng đến 512 hoặc 8192 hoặc bất kỳ sức mạnh nào khác của hai bằng cách thay đổi các hằng số có liên quan, làm cho mã chỉ dài hơn một chút.

Phiên bản dễ đọc hơn một chút

Một số tín dụng dành cho mob vì dòng đầu tiên là việc tôi sử dụng lại ý tưởng của mình trong laser . Phần còn lại hoàn toàn là công việc của tôi.

# Read “%i”nput (this line is essentially mob’s idea, see above)
s!.! $i{$x++} = $& eq '#' !ge, $x = $r += 64 for <>;

# Subroutine to add a vertex to the current polygon and change the current “$d”irection
sub a
{
    $d += @_ || 3;
    $d %= 4;
    $y = $x % 64;
    $z = $x >> 6;
    $c .= ", ($y,$z)";
}

for $x (keys %i)
{
    # Go to the next “upward-pointing” edge that we haven’t already “%v”isited.
    if ($c = !$v{$x} & $i{$x} & !$i{$x-1})
    {
        # We’re going in the “$d”irection of 0=up, 1=left, 2=down, 3=right
        $i{($x += (1,64)[$d^3]) - (64,65,1)[$d]}
        ?  $i{$x - (65,1,0,64)[$d]}
           ?  a 1               # take a 90° turn to the left
           : ($x -= (64,1)[$d]) # move straight ahead
        : a                     # take a 90° turn to the right

        # Only stop if the current “$d”irection is “up” and we encounter a “%v”isited edge
        # (which necessarily is the one we started from)
        while $d || !$v{$x}++;

        # Remove “1, ” and output this polygon
        print substr $c.$/, 3
    }
}

Chỉnh sửa

  • (345 → 312) Đã nhận ra rằng không cần cập nhật $xkhi thực hiện lần lượt vì lần lặp tiếp theo sẽ thực hiện điều đó
  • (312 → 311) Thay đổi 1= xuống, 2= trái sang 1= trái, 2= xuống và cập nhật $dqua XOR thay vì trực tiếp
  • (311 → 265) Loại bỏ sự lặp lại của biểu thức trong cùng và sử dụng các mảng để tham số hóa nó

2

Con trăn, 607 ký tự

Mã này hoạt động bằng cách giữ một danh sách các ranh giới được phát hiện cho đến khi nó xử lý các ký hiệu # theo thứ tự đầu vào. Các ranh giới được lưu trữ trong bảng E để ánh xạ các cạnh (4-tuples của x_start, y_start, x_end, y_end) vào danh sách các cạnh tạo thành ranh giới của một đa giác. Khi chúng tôi xử lý mỗi # mới, nó có thể được kết nối với một đa giác ở trên (p) hoặc bên trái của nó (q). Mã tìm thấy p và q bằng E và sau đó hợp nhất ranh giới của # (r) hiện tại với p và q, nếu chúng tồn tại. Trường hợp p == q tạo lỗ.

import sys
x=y=N=0
E={}
def P(L):
 if L:print ', '.join(map(lambda z:str(z[:2]),L))
while 1:
 r,a,b,c=[(x,y,x+1,y),(x+1,y,x+1,y+1),(x+1,y+1,x,y+1),(x,y+1,x,y)],(x+1,y,x,y),(x,y,x,y\
+1),sys.stdin.read(1)
 if not c:break
 p,q=E.get(a),E.get(b)
 if'#'==c:
  if p:
   i=p.index(a)
   if q:
    j=q.index(b)
    if p==q:
     if i<j:P(p[i+1:j]);p[i:j+1]=r[1:3]
     else:P(p[i+1:]+p[:j]);p[i:]=r[1:3];p[0:j+1]=[]
    else:p[i:i+1]=r[1:3]+q[j+1:]+q[:j]
   else:p[i:i+1]=r[1:]
  elif q:j=q.index(b);q[j:j+1]=r[:3];p=q
  else:p=r
  for e in p:E[e]=p
 x+=1
 if'\n'==c:y+=1;x=0
for L in E.values():
 if L:P(L);L[:]=[]
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.