Có phải là L-lồi?


14

Lý lịch

Một polyomino được gọi là L-lồi , nếu có thể di chuyển từ bất kỳ ô nào sang bất kỳ ô nào khác bằng một đường dẫn hình chữ L, nghĩa là một đường đi theo hướng chính và thay đổi hướng nhiều nhất một lần. Ví dụ, polyomino của 1s trong hình

0 0 1 1 1 0

1 1 1 1 0 0

1 1 0 0 0 0

không phải là L-lồi, vì cả hai đường dẫn hình chữ L từ dưới cùng bên trái 1lên trên cùng bên phải 1đều chứa a 0:

0>0>1>1>1 0
^       ^
1 1 1 1 0 0
^       ^
1>1>0>0>0 0

Tuy nhiên, polyomino của 1s trong hình này là L-lồi:

0 1 1 1 0 0

1 1 1 1 1 1

0 1 1 0 0 0

Đầu vào

Đầu vào của bạn là một mảng bit 2D ở định dạng gốc của ngôn ngữ của bạn hoặc dưới dạng chuỗi được phân tách bằng dòng mới nếu ngôn ngữ của chúng tôi thiếu mảng. Nó được đảm bảo để chứa ít nhất một 1.

Đầu ra

Đầu ra của bạn sẽ là một giá trị trung thực nếu tập hợp 1s là một polyomino L-lồi và giá trị giả nếu không. Các đầu ra này phải nhất quán: bạn phải xuất cùng một giá trị trung thực cho tất cả các đầu vào L-lồi và cùng một giá trị giả cho các đầu vào khác. Lưu ý rằng một tập hợp 1s bị ngắt kết nối (không phải là polyomino) dẫn đến đầu ra giả.

Quy tắc và chấm điểm

Bạn có thể viết một chương trình đầy đủ hoặc một chức năng. Số byte thấp nhất sẽ thắng và các sơ hở tiêu chuẩn không được phép.

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

Các trường hợp kiểm tra này cũng sẽ hoạt động nếu bạn xoay hoặc phản ánh các mảng hoặc thêm các hàng 0s vào bất kỳ đường viền nào.

False instances
01
10

111
101
111

1101
1111
1110

1100
1000
0011

01100
11110
01110
00110

011000
011110
001111

True instances
1

01
11

010
111
010

001
011
111

11100
11110
01100
01000

011000
011000
111100
111111
001000

Rất đẹp thách thức, tôi rất thích nó =)
flawr

Về đầu vào: đó là một chuỗi giới hạn dòng mới được phép, nếu ngôn ngữ của chúng tôi không thiếu mảng ?
edc65

@ edc65 (Xin lỗi, đã rời khỏi lưới điện trong một vài ngày.) Chắc chắn, điều đó cũng được cho phép, đó chỉ là từ ngữ tồi tệ từ phía tôi.
Zgarb

Câu trả lời:


6

Ốc , 45 24

&
!{\1t\1!{o\1,nf\1,!.!~

Ngay sau khi đăng giải pháp ban đầu của tôi, tôi nhận ra có một cách tốt hơn nhiều. Chương trình ban đầu đi vòng quanh quảng trường được hình thành bởi các đường dẫn giữa hai 1s, kiểm tra sự hiện diện của 0 ở mỗi cặp cạnh. Nó cũng phải có một trường hợp đặc biệt cho các đường thẳng. Phiên bản mới bắt đầu bằng cách dịch chuyển tức thời từ cái này 1sang cái khác và kiểm tra sự vắng mặt của một đường thẳng hoặc hình chữ L của 1s trở lại điểm bắt đầu.


CHÚA ƠI!! Có một thông dịch viên trực tuyến nơi chúng ta có thể chơi xung quanh với điều này?
flawr

1
@flawr Bạn có thể xây dựng nó từ nguồn với mã nguồn ở đây .
Alex A.

6

Matlab, 182 byte

Ý tưởng: Lặp lại cho mọi 1trong ma trận polyomino:

  • Tạo ma trận mới chỉ với số đã cho 1nhưng phần còn lại bằng không.
  • cho mọi 1trong ma trận mới này (lặp lại cho đến khi không có gì thay đổi nữa)
    • thêm 1là hàng xóm theo hướng x nếu có 1hàng xóm trong đa thức
  • cho mọi 1trong ma trận mới này (lặp lại cho đến khi không có gì thay đổi nữa)
    • thêm 1là hàng xóm theo hướng x nếu có 1hàng xóm trong đa thức

Bây giờ 1trong ma trận mới sẽ bao gồm tất cả 1trong ma trận đa thức có thể truy cập từ điểm bắt đầu đã cho bằng cách trước tiên đi theo hướng x và sau đó theo hướng y. Bây giờ chúng ta có thể lặp lại quá trình tương tự nhưng trước tiên đi vào hướng y và sau đó theo hướng x. Bây giờ mọi 1ma trận polyomino nên đạt được cùng một lúc hoặc cả hai lần. Nếu không, thì chúng ta đã tìm thấy một vị trí trong ma trận polynomio không thể đạt được từ mọi vị trí khác bằng một đường dẫn L.

Chơi gôn

function r=f(a);[i,j,b]=find(a);N=nnz(i);r=1;for k=1:N;K=1:3;for l=1:2;c=b;b=a*0;b(i(k),j(k))=1;for z=1:2*N; b=conv2(b+0,K,'s')&a;if z==N;K=K';end;end;end;r=r*all(b(:)|c(:)>=a(:));end

Với nhận xét:

function r=codegolf_L_convex(a);
%a=[0,1;1,1];
[i,j,b]=find(a);%b just needs to be initialized, does not really mattter
N=nnz(i);%number of ones in the matrix
r=1;%return value
for k=1:N;%go throu all '1' in the matrix
    %expand that pixel in x dir:
    K=1:3;%convolution kernel (just three positive values needed)
    for l=1:2;%first horizontal->vertical then vertical->horizontal
        c=b;%backup for considering both runs
        b=a*0;
        b(i(k),j(k))=1; %set the seed
        for z=1:2*N;     
            b=conv2(b+0,K,'s')&a; %expand the seed horizontally (or vertically for the second half) but only within the polyomino
            if z==N;
                K=K'; %change horizontal/vertical 
            end;
        end;
    end;
    r=r*all(b(:)|c(:)>=a(:));%check whether we can really reach every point
end

Kịch bản trường hợp thử nghiệm:

disp('all false -------------');
a=[0,1;1,0];
f(a)
a=[1,1,1;1,0,1;1,1,1];
f(a)
a=[1,1,0,1;1,1,1,1;1,1,1,0];
f(a)
a=[1,1,0,0;1,0,0,0;0,0,1,1];
f(a)
a=[0,1,1,0,0;1,1,1,1,0;0,1,1,1,0;0,0,1,1,0];
f(a)
a=[0,1,1,0,0,0;0,1,1,1,1,0;0,0,1,1,1,1];
f(a)
 disp('all true +++++++++++++');
a=[1];
f(a)
a=[0,1;1,1];
f(a)
a=[0,1,0;1,1,1;0,1,0];
f(a)
a=[0,0,1;0,1,1;1,1,1];
f(a)
a=[1,1,1,0,0;1,1,1,1,0;0,1,1,0,0;0,1,0,0,0];
f(a)
a=[0,1,1,0,0,0;0,1,1,0,0,0;1,1,1,1,0,0;1,1,1,1,1,1;0,0,1,0,0,0];
f(a)

2

Javascript ES6, 290 byte

Ok, có thể nó sẽ không giành được bất kỳ giải thưởng nào cho sự ngắn gọn, nhưng nó sử dụng một cách tiếp cận mới lạ. Xem phiên bản không được biết về cách thức hoạt động.

Bằng chứng cho phương pháp này có thể được tìm thấy trong: Hệ thống tự động di động và hệ thống phức tạp rời rạc .

L=a=>[1,0,1].every($=>(a=a[0].map((_,col)=>a.map(row=>row[col]))).map(r=>($?r.reverse():r).join``).every((r,i,b)=>r.replace(/^(0*)(1*)(0*)$|(.+)/,(_,s,m,o,e)=>(c=e)?'':!m||b[i-1]&&+b[i-1][s.length]?1:b.every((r,j)=>j<i||(c=c||!+r[l=s.length])?r.search(`0{${l}}.*0{${o.length}}`)+1:1)||'')))

Ung dung:

function L(a) {
  /* Runs three times and ensure all pass validation
   * 1: horizontally reversed
   * 2: 90 degrees rotated
   * 3: original
   *
   *     | 1:  | 2:  | 3:
   * =====================
   * 001 | 100 | 111 | 001
   * 011 | 110 | 011 | 011
   * 111 | 111 | 001 | 111
   *
   * By finding maximal rectangles with corners on all NW and NE corners
   * (separately) of a HV-convex polyomino and ensuring it doesn't enter the
   * boundaries labelled ABCD for the rectangle X below:
   *
   *   A  |         |  B
   * -----===========-----
   *      |    X    |
   * -----===========-----
   *   C  |         |  D
   *
   * The first iteration tests the NE corners and horizontal convexity.
   * The second iteration test vertical convexity.
   * The third iteration tests the NW corners.
   *
   * If all pass then the polyomino is L-convex.
   */
  return [1,0,1].every(function($){
    return (a=a[0].map((_,col)=>{
      // Transpose rows with columns
      return a.map(row=>row[col])
    })).map(row=>{
      // Join rows as strings and on odd iterations reverse them
      return ($ ? row.reverse() : row).join``
    }).every(function(row, i, b) {
      if (i == 0) console.log(b.join('\n'));
      return row.replace(/^(0*)(1*)(0*)$|(.+)/, function(_, start, middle, end, invalid) {
        // Non H-convex polyomino (0 between 1s)
        if (invalid) return '';
        // Is not a NW corner (character above is 1)
        if (!middle || b[i-1] && +b[i-1][start.length]) return 1;
        c=1;
        return b.every(function(row, j) {
          // Above or below maximal rectangle from corner
          if (j < i || !(c=c&&+row[l=start.length])) {
            // Area before and after maximal rectangle doesn't contain 1
            return row.search(`0{${l}}.*0{${end.length}}`)+1
          }
          return 1;
        }) || '';
      });
    });
  });
}

1
Ha, bài báo đó là nơi tôi có cảm hứng cho thử thách này!
Zgarb

@Zgarb Bài báo rất hay và là một trong số ít tôi có thể thấy điều đó có ý nghĩa với một người không định hướng toán học.
George Reith

2

Toán học, 129 127 byte

3>GraphDiameter@Graph[#,#<->#2&@@@Select[#~Tuples~2,!FreeQ[#-#2&@@#,0]&]]&@Position[#,1]&&{#,Thread@#}~FreeQ~{___,1,0..,1,___}&

Giải trình:

Đầu tiên, nếu có một 0giữa hai 1s trên cùng một hàng hoặc cột, thì mảng không phải là L-lồi, vì chúng ta không thể kết nối hai1 s.

Sau khi loại trừ trường hợp này, cứ hai 1s trên cùng một hàng hoặc cột có thể được kết nối bằng một đường thẳng. Chúng ta có thể tạo một biểu đồ, có các đỉnh là vị trí của 1s trong mảng và các cạnh là các cặp 1s trên cùng một hàng hoặc cột. Khi đó mảng là L-lồi khi và chỉ khi đường kính của đồ thị nhỏ hơn 3.


1
Bạn có thể đưa ra một lời giải thích làm thế nào điều này hoạt động? Tôi sẽ không nâng cao sự vô nghĩa mà không ai có thể hiểu được =)
flawr

Làm thế nào để nhận ra trường hợp sai thứ nhất và thứ tư (những trường hợp bị ngắt kết nối)?
Zgarb

1
@Zgarb Nếu đồ thị bị ngắt kết nối, đường kính của nó là vô cùng.
alephalpha

2

JavaScript (ES6) 174

Nhìn vào lưới các ô trống hoặc đầy, đối với bất kỳ cặp ô được điền nào, tôi kiểm tra các đường dẫn ngang đến cột ô khác (có thể có 1 nếu các ô nằm trên cùng một hàng, khác hoặc 2) và các đường dẫn dọc tới hàng ô khác (có thể có 1 hoặc 2 quá). Nếu tôi tìm thấy một ô trống trong cả hai đường dọc hoặc cả hai đường ngang, thì không thể có đường dẫn hình chữ L giữa các ô.

(Tôi đã có một thời gian khó khăn để đưa ra lời giải thích này - Tôi hy vọng đã được rõ ràng)

Kiểm tra chạy đoạn mã dưới đây trong bất kỳ trình duyệt tuân thủ EcmaScript 6 nào

F=p=>!p.some((n,y)=>n.some((q,x)=>q&&p.some((o,u)=>o.some((q,t)=>{for(f=0,i=y;q&i<=u;i++)f|=!p[i][x]|2*!p[i][t];if(f<3)for(f=0,j=x;q&j<=t;j++)f|=!n[j]|2*!o[j];return f>2}))))

// TEST
console.log=(...x)=>O.innerHTML+=x+'\n'

tko = [
 [[0,1],[1,0]]
,[[1,1,1],[1,0,1],[1,1,1]]
,[[1,1,0,1],[1,1,1,1],[1,1,1,0]]
,[[1,1,0,0],[1,0,0,0],[0,0,1,1]]
,[[0,1,1,0,0],[1,1,1,1,0],[0,1,1,1,0],[0,0,1,1,0]]
,[[0,1,1,0,0,0],[0,1,1,1,1,0],[0,0,1,1,1,1]]
]
tko.forEach(t=>(console.log(t.join`\n`+`\nFalse? ${F(t)}\n`)));
tok = [
 [[1]]
,[[0,1],[1,1]]
,[[0,1,0],[1,1,1],[0,1,0]]
,[[0,0,1],[0,1,1],[1,1,1]]
,[[1,1,1,0,0],[1,1,1,1,0],[0,1,1,0,0],[0,1,0,0,0]]
,[[0,1,1,0,0,0],[0,1,1,0,0,0],[1,1,1,1,0,0],[1,1,1,1,1,1],[0,0,1,0,0,0]]
]  
tok.forEach(t=>(console.log(t.join`\n`+`\nTrue? ${F(t)}\n`)));

// LESS GOLFED

U=p=>
  !p.some((n,y)=>  
    n.some((q,x)=> 
      q && p.some((o,u)=>  
        o.some((q,t)=>{
          for(f=0,i=y; q&i<=u; i++)f|=!p[i][x]|2*!p[i][t]
          if (f<3)
            for(f=0,j=x; q&j<=t; j++)f|=!n[j]|2*!o[j]
          return f>2
        })
      )
    )
  )
<pre id=O></pre>

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.