มันเป็น L-convex หรือไม่


14

พื้นหลัง

polyominoเรียกว่าL-นูนถ้ามันเป็นไปได้ที่จะเดินทางจากกระเบื้องใด ๆ กับกระเบื้องอื่น ๆ โดยเส้นทางรูปตัว L ที่เป็นเส้นทางที่จะไปในทิศทางที่พระคาร์ดินัลและทิศทางการเปลี่ยนแปลงที่มากที่สุดครั้งหนึ่ง ตัวอย่างเช่นโพลีโนมีนของ1s ในรูป

0 0 1 1 1 0

1 1 1 1 0 0

1 1 0 0 0 0

ไม่ใช่ L-convex เนื่องจากเส้นทางรูปตัว L จากด้านล่างซ้าย1ไปด้านบนขวา1ประกอบด้วย0:

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

อย่างไรก็ตามโพลีโอมิโนของ1s ในรูปนี้คือ L-convex:

0 1 1 1 0 0

1 1 1 1 1 1

0 1 1 0 0 0

อินพุต

การป้อนข้อมูลของคุณคืออาร์เรย์บิตสองบิตในรูปแบบดั้งเดิมของภาษาของคุณหรือเป็นสตริงที่มีการคั่นด้วยการขึ้นบรรทัดใหม่หากภาษาของเราไม่มีอาร์เรย์ 1มันมีการประกันเพื่อมีอย่างน้อยหนึ่ง

เอาท์พุต

ผลลัพธ์ของคุณจะเป็นค่าความจริงหากชุดของ 1 s คือโพลีโนมิก L-convex และค่าที่ผิดพลาดหากไม่ ผลลัพธ์เหล่านี้จะต้องสอดคล้องกัน: คุณต้องส่งออกค่าความจริงเดียวกันสำหรับอินพุต L-convex ทั้งหมดและค่าเท็จสำหรับผู้อื่น โปรดทราบว่าชุด1s ที่ถูกตัดการเชื่อมต่อ(ซึ่งไม่ใช่โพลีโอมิโน) จะส่งผลให้เกิดผลลัพธ์ที่ผิดพลาด

กฎและเกณฑ์การให้คะแนน

คุณสามารถเขียนโปรแกรมเต็มหรือฟังก์ชั่น จำนวนไบต์ต่ำสุดที่ชนะและช่องโหว่มาตรฐานไม่ได้รับอนุญาต

กรณีทดสอบ

กรณีทดสอบเหล่านี้ควรทำงานได้เช่นกันถ้าคุณหมุนหรือสะท้อนอาร์เรย์หรือเพิ่มแถวของ0s ลงในเส้นขอบใด ๆ

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

ความท้าทายที่ดีมากฉันสนุกกับมัน =)
ข้อผิดพลาด

เกี่ยวกับการป้อนข้อมูล: มันสตริงคั่นด้วยการขึ้นบรรทัดใหม่ได้, ถ้าภาษาของเราไม่ได้ขาดอาร์เรย์ ?
edc65

@ edc65 (ขออภัยออกจากตารางมาสองสามวัน) แน่นอนว่าได้รับอนุญาตด้วยเช่นกัน
Zgarb

คำตอบ:


6

หอย , 45 24

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

ทันทีหลังจากโพสต์โซลูชันเริ่มต้นของฉันฉันรู้ว่ามีวิธีที่ดีกว่ามาก โปรแกรมต้นฉบับเดินทางรอบจัตุรัสที่เกิดจากเส้นทางระหว่างสอง1s เพื่อทดสอบว่ามี 0 ในแต่ละด้านของคู่ นอกจากนี้ยังต้องมีกรณีพิเศษสำหรับเส้นทางเส้นตรง เวอร์ชั่นใหม่เริ่มต้นด้วยการส่งผ่านทางไกลจากที่หนึ่ง1ไปยังอีกที่หนึ่งและทดสอบว่าไม่มีเส้นทางตรงหรือรูปตัว L 1กลับไปที่จุดเริ่มต้น


พระเจ้าช่วย!! มีล่ามออนไลน์ที่เราสามารถเล่นกับมันได้ไหม?
ข้อบกพร่อง

1
@flawr คุณสามารถสร้างมันขึ้นมาจากแหล่งที่มีรหัสที่มาที่นี่
Alex A.

6

Matlab, 182 ไบต์

แนวคิด: ทำซ้ำสำหรับทุกคน1ในเมทริกซ์โพลีโอมิโน:

  • สร้างเมทริกซ์ใหม่ที่มีเพียงกำหนด1แต่ส่วนที่เหลือเป็นศูนย์
  • สำหรับทุกคน1ในเมทริกซ์ใหม่นี้ (ทำซ้ำจนกว่าจะไม่มีอะไรเปลี่ยนแปลงอีกต่อไป)
    • เพิ่ม1เป็นเพื่อนบ้านในทิศทาง x หากมี1เพื่อนบ้านอยู่ใน polynomio
  • สำหรับทุกคน1ในเมทริกซ์ใหม่นี้ (ทำซ้ำจนกว่าจะไม่มีอะไรเปลี่ยนแปลงอีกต่อไป)
    • เพิ่ม 1เป็นเพื่อนบ้านในทิศทาง x หากมี1เพื่อนบ้านอยู่ใน polynomio

ตอนนี้ 1ในเมทริกซ์ใหม่ควรครอบคลุมทั้งหมด1ใน polynomio-matrix ที่สามารถเข้าถึงได้จากจุดเริ่มต้นที่กำหนดโดยไปในทิศทาง x ก่อนแล้วตามทิศทาง y ตอนนี้เราสามารถทำซ้ำกระบวนการเดียวกันได้ แต่ก่อนจะเข้าสู่ทิศทาง y และในทิศทาง x ตอนนี้โพลีโอมิโน1เมทริกซ์ทุกตัวควรถึงในทันทีหรือทั้งสองครั้ง ถ้าไม่เช่นนั้นเราจะพบตำแหน่งในเมทริกซ์พหุนามซึ่งไม่สามารถเข้าถึงได้จากตำแหน่งอื่นทุกตำแหน่งด้วยL -path

แข็งแรงเล่นกอล์ฟ:

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

ด้วยความคิดเห็น:

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

สคริปต์กรณีทดสอบ:

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 ไบต์

ตกลงบางทีมันอาจจะไม่ชนะรางวัลใด ๆ สำหรับช่วงเวลาสั้น ๆ แต่ใช้แนวทางใหม่ ดูเวอร์ชั่นที่ไม่ดีสำหรับวิธีการทำงาน

ข้อพิสูจน์สำหรับวิธีนี้สามารถพบได้ใน: ระบบเซลลูล่าร์ออโตและระบบแยกอิสระ

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

Ungolfed:

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
ฮาบทความนั้นเป็นที่ที่ฉันได้รับแรงบันดาลใจสำหรับความท้าทายนี้!
Zgarb

@Zgarb บทความนี้ยอดเยี่ยมมากและเป็นหนึ่งในไม่กี่แห่งที่ฉันพบว่าทำให้คนที่ไม่ได้สนใจเรื่องคณิตศาสตร์
George Reith

2

Mathematica, 129 127 bytes

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

คำอธิบาย:

อันดับแรกหากมี0ระหว่างสอง1s ในแถวหรือคอลัมน์เดียวกันอาร์เรย์ไม่ใช่ L-convex เนื่องจากเราไม่สามารถเชื่อมต่อทั้งสอง1ได้

หลังจากยกเว้นกรณีนี้ทุก ๆ สอง1วินาทีในแถวหรือคอลัมน์เดียวกันสามารถเชื่อมต่อกันด้วยเส้นทางตรง เราสามารถสร้างกราฟที่มีจุดยอดเป็นตำแหน่งของ1s ในอาร์เรย์และขอบเป็นคู่ของ1s ในแถวหรือคอลัมน์เดียวกัน จากนั้นอาร์เรย์จะเป็น L-convex ถ้าหากเส้นผ่านศูนย์กลางของกราฟน้อยกว่า 3


1
คุณสามารถให้คำอธิบายวิธีการทำงานได้หรือไม่? ผมไม่ได้จะพูดพล่อยๆ upvote ไม่มีใครอาจจะเข้าใจ =)
flawr

สิ่งนี้จะรับรู้อินสแตนซ์เท็จที่หนึ่งและสี่ (อันที่ถูกตัดการเชื่อมต่อ) ได้อย่างไร?
Zgarb

1
@Zgarb หากกราฟถูกตัดการเชื่อมต่อเส้นผ่านศูนย์กลางจะไม่มีที่สิ้นสุด
alephalpha

2

JavaScript (ES6) 174

ดูที่กริดของเซลล์ที่ว่างเปล่าหรือที่เต็มไปสำหรับคู่ของเซลล์ที่เต็มไปฉันตรวจสอบเส้นทางแนวนอนไปยังคอลัมน์เซลล์อื่น ๆ (อาจมี 1 หากเซลล์อยู่ในแถวเดียวกันหรือ 2) และเส้นทางแนวตั้งไปยัง แถวเซลล์อื่น ๆ (อาจมี 1 หรือ 2 ด้วย) หากฉันพบเซลล์ว่างในทั้งเส้นทางแนวตั้งหรือเส้นทางแนวนอนทั้งสองดังนั้นจะไม่มีเส้นทางที่มีรูปร่างเป็น L ระหว่างเซลล์

(ฉันมีความยากลำบากในการพยายามอธิบายคำอธิบายนี้ - ฉันหวังว่าจะชัดเจน)

ทดสอบการเรียกใช้ตัวอย่างข้อมูลด้านล่างในเบราว์เซอร์ที่สอดคล้องกับ EcmaScript 6

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>

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.