การตรวจจับสี่เหลี่ยมผืนผ้า


21

เขียนโปรแกรมหรือฟังก์ชั่นที่ใช้ในสตริงหลายบรรทัดของ0's และ1' s ไม่มีอักขระอื่นใดที่อยู่ในสตริงและสตริงจะเป็นรูปสี่เหลี่ยมผืนผ้าเสมอ (ทุกบรรทัดจะมีจำนวนอักขระเหมือนกัน) โดยมีขนาดเล็กเท่ากับ 1 × 1 แต่ไม่เช่นนั้นตัวอักษร0และ1ของอาจถูกจัดเรียงโดยพลการ

คุณอาจจะสมมติสตริงมีการขึ้นบรรทัดใหม่ต่อท้ายตัวเลือกและถ้าต้องการคุณอาจใช้ใด ๆ ที่แตกต่างกันสองASCII พิมพ์ตัวอักษรในสถานที่และ01

พิมพ์หรือส่งกลับค่า truthyถ้าทั้งหมดของเส้นทางเชื่อมต่อภูมิภาคของทั้งสอง0'และ1' s ในสตริงเป็นรูปสี่เหลี่ยมที่เป็นของแข็งอื่นส่งออกมูลค่า falsy

เส้นทางพื้นที่เชื่อมต่อของ0's หมายความว่าจากคนใดคนหนึ่ง0ในภูมิภาคอื่น ๆ ทั้งหมดที่0' s สามารถเข้าถึงได้โดยเฉพาะการเคลื่อนย้ายขึ้นลงซ้ายและขวาเพื่ออื่น ๆ0's (และไม่ได้ย้ายแนวทแยงมุมไม่ได้ย้ายไปอยู่ที่ใด1และไม่เคลื่อนไหวนอกขอบเขตของสตริง) แนวคิดเดียวกันนี้นำไปใช้กับ1ภูมิภาคที่เชื่อมต่อเส้นทาง

สี่เหลี่ยมแข็งของ0's หมายถึงพื้นที่ทั้งหมดของสี่เหลี่ยมที่เต็มไปด้วย0' และไม่มี1's แนวคิดเดียวกันนี้ใช้กับ1สี่เหลี่ยมทึบ

รหัสที่สั้นที่สุดในหน่วยไบต์ชนะ Tiebreaker เป็นคำตอบก่อนหน้า

(โปรดสังเกตว่าสตริงไม่ได้ล้อมรอบด้วยเงื่อนไขขอบเขต toroidal )

ตัวอย่าง

1)สตริงอินพุตนี้มีพื้นที่การเชื่อมต่อ 3 เส้นทาง (2 สำหรับ0และ 1 สำหรับ1) เฉพาะพื้นที่ด้านล่างขวาเท่านั้นที่00เป็นรูปสี่เหลี่ยมผืนผ้าที่มั่นคงดังนั้นเอาต์พุตจะเป็นเท็จ

0011
0111
0100

2)สตริงอินพุตนี้มีพื้นที่การเชื่อมต่อ 4 เส้นทาง (2 สำหรับทั้งคู่0และ1) พวกเขาทั้งหมดเป็นรูปสี่เหลี่ยมผืนผ้าที่มั่นคงดังนั้นผลลัพธ์จะเป็นจริง

0011
0011
1100

3)อินพุตนี้มีพื้นที่เชื่อมต่อ 2 เส้นทาง แต่หนึ่งในนั้นคือสี่เหลี่ยมผืนผ้าทึบดังนั้นเอาต์พุตจะเป็นเท็จ

00000000
01111110
00000000

4)อินพุตนี้มีเพียง 1 เส้นทางที่เชื่อมต่อภูมิภาคและเป็นรูปสี่เหลี่ยมผืนผ้าที่มั่นคงดังนั้นเอาต์พุตจึงเป็นความจริง

11111111
11111111
11111111

กรณีทดสอบ

Tเพียงด้านล่างอินพุตสตริงวิธี truthy, Fวิธี falsy

0
T

1
T

00
T

01
T

10
T

11
T

0000000
T

1111111
T

011100100100101100110100100100101010100011100101
T

00
11
T

01
10
T

01
11
F

00
01
F

11
11
T

110
100
F

111
000
T

111
101
111
F

101
010
101
T

1101
0010
1101
0010
T

1101
0010
1111
0010
F

0011
0111
0100
F

0011
0011
1100
T

00000000
01111110
00000000
F

11111111
11111111
11111111
T

0000001111
0000001111
T

0000001111
0000011111
F

0000001111
1000001111
F

1000001111
1000001111
T

1110100110101010110100010111011101000101111
1010100100101010100100010101010101100101000
1110100110010010110101010111010101010101011
1010100100101010010101010110010101001101001
1010110110101010110111110101011101000101111
F

คำตอบ:


5

เยลลี่ขนาด 7 ไบต์

ṣ⁷µ=ḢZE

นี้ใช้ขั้นตอนวิธีการเดียวกับ@ LevelRiverSt คำตอบของทับทิม อัลกอริทึมจริงพอดีใน 4 ไบต์สุดท้าย; 3 ไบต์แรกจะต้องแยกวิเคราะห์รูปแบบการป้อนข้อมูล

ลองออนไลน์!

มันทำงานอย่างไร

ṣ⁷µ=ḢZE  Main link. Argument: t (string)

ṣ⁷       Split t at linefeeds..
  µ      Begin a new, monadic link. Argument: A (list of strings)
    Ḣ    Pop the first string of A.
   =     Compare all other strings in A with the first.
         = compares characters, so this yields a list of Booleans for each string.
         For a truthy input, all pairs of lines now have been transformed in lists
         of only 1's or only 0's. That means all columns must be equal.
     Z   Zip; transpose rows with columns.
      E  Check if all rows (former columns) are equal to each other.

16

เยลลี่ , 11 10 ไบต์

ṣ⁷^2\⁺€FS¬

ต้องขอบคุณ @Dennis อย่างมากสำหรับการเล่นกอล์ฟขนาดนี้ถึงครึ่งหนึ่งของขนาดดั้งเดิม (ผ่านคุณสมบัติที่ไม่มีเอกสาร)

ลองออนไลน์ ! โปรดทราบว่าคำพูดสามเท่าสำหรับสตริงหลาย

คำอธิบาย

อัลกอริทึมพื้นฐานคือ: return จริง iff ทุก subgrid 2x2 มีจำนวน 1s (หรือเทียบเท่า 0s)

เห็นได้ชัดว่าทำไมจำนวน 1 คี่ไม่สามารถใช้งานได้เนื่องจากเราจะมีหนึ่งในรายการต่อไปนี้:

10  01  00  00  01  10  11  11
00  00  01  10  11  11  10  01

โปรดทราบว่า 4 อันแรกคือการหมุนของสิ่งเดียวกันและเหมือนกันสำหรับ 4 ครั้งล่าสุดมุมสะท้อนกลับไม่สามารถเป็นส่วนหนึ่งของสี่เหลี่ยมผืนผ้าได้ดังนั้นทำไมจึงไม่ถูกต้อง

กล่าวอีกนัยหนึ่งย่อย 2x2 ทั้งหมดจะต้องเป็นอย่างใดอย่างหนึ่งต่อไปนี้:

00  00  11  01  10  01  10  11
00  11  00  01  10  10  01  11

ซึ่งถ้าเราดูที่ขอบเขตสามารถจินตนาการเป็น "ชิ้นส่วนปริศนา" ต่อไปนี้:

 ___    ___    ___    ___
|   |  | | |  |   |  | | |
|   |  | | |  |---|  |-|-|
|___|  |_|_|  |___|  |_|_|

และลองสร้างชิ้นส่วนที่ไม่ใช่รูปสี่เหลี่ยมผืนผ้าด้วยตัวต่อปริศนา :) (ในขณะที่มีจุดจบตรงกัน)

การใช้งานจริงจึง:

ṣ⁷               Split input by newlines to give rows
  ^2\            Taking overlapping sets of 2 rows at a time: accumulate rows by XOR
                 Note that strings cast to integers automatically for bitwise operators
     ⁺€          Repeat the previous link (⁺), on each (€) element in the resulting array
       F         Flatten the array
        S        Sum (effectively reducing by OR)
         ¬       Logical negation of the result

ตัวอย่างเช่นสำหรับการป้อนข้อมูล

100
010
000
101

เรามี:

  ṣ⁷: ["100", "010", "000", "101"]
 ^2\: [[1, 1, 0], [0, 1, 0], [1, 0, 1]]    (e.g. first entry is "100" ^ "010")
^2\€: [[0, 1], [1, 1], [1, 1]]             (e.g. the first entry is [1^1, 1^0] - this
                                            gives the counts of 1s in each subgrid, mod 2)
   F: [0, 1, 1, 1, 1, 1]
   S: 5                                    (this gives the number of invalid 2x2 subgrids,
                                            which is indeed all but the top left)
   ¬: 0

1
คุณช่วยไปบันทึกคุณสมบัติที่คุณใช้ไปได้ไหม? ถ้าคนทำอย่างนั้นเอกสารจะเกิดขึ้น!
CalculatorFeline

คุณจำเป็นต้องแบนหรือไม่?
CalculatorFeline

@CatsAreFluffy หากคุณไม่แบนเยลลี่จะพยายามสรุปรายการของเวกเตอร์และคุณจะได้เวกเตอร์มาด้วย
Sp3000

เพียงผลรวมและผลรวมจะดีกว่า!
CalculatorFeline

4
"คุณสมบัติที่ไม่มีเอกสาร" - aha! ดังนั้นที่ว่าเดนนิส outgolfs ทุกคน! : D
AdmBorkBork

12

ทับทิม, 76

->s{j=!r=1
s.lines{|t|i=t.to_i(2)
j&&r&&=(j^i)%t.tr(?0,?1).to_i(2)<1
j=i}
r}

ในกริดใด ๆ ที่ประกอบด้วยสี่เหลี่ยมทั้งหมดแต่ละบรรทัดจะต้องเหมือนกันกับเส้นก่อนหรือมีบิตทั้งหมดพลิกจาก 0 ถึง 1 และในทางกลับกัน

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

ต้องการที่จะวาดรูปสี่เหลี่ยมผืนผ้าที่มีเส้นเพียงส่วนเดียวข้าม? ลองลบกลุ่มของบรรทัดใด ๆ ของคุณ ตอนนี้คุณจะต้องมากกว่า 2 สีเพื่อกำหนดสีการออกแบบของคุณเนื่องจากคุณจะมีจุดที่รูปสี่เหลี่ยม 3 รูปมาบรรจบกัน (2 มุมและขอบ) การออกแบบดังกล่าวจึงไม่เกี่ยวข้องกับคำถามนี้

ฉันประหลาดใจที่คำตอบไม่ได้สังเกตสิ่งนี้

ฉันคิดว่าอัลกอริทึมนี้ควรสั้นกว่ามากในภาษาอื่น

Ungolfed ในโปรแกรมทดสอบ

f=->s{
  j=!r=1                              #r = truthy, j=falsy
  s.lines{|t|                         #for each line
    i=t.to_i(2)                       #i = value of current line, converted to a number in base 2 (binary)
    j&&                               #if j is truthy (i.e this is not the first line)
      r&&=(j^i)%t.tr(?0,?1).to_i(2)<1 #XOR i with the previous line. Take the result modulo (current line with all 0 replaced by 1)
                                      #if the result of the XOR was all 0 or all 1, the modulo == zero (<1). Otherwise, it will be a positive number.   
j=i}                                  #j = value of current line (always truthy in ruby, even if zero)
r}                                    #return 1 or true if all the modulo calculations were zero, else false.



#text to print after test case to check answer is as desired
T='T

'
F='F

'

#test cases
puts f['0'],T

puts f['1'],T

puts f['00
'],T

puts f['01'],T

puts f['10'],T

puts f['11
'],T

puts f['0000000'],T

puts f['1111111'],T

puts f['011100100100101100110100100100101010100011100101'],T

puts f['00
11'],T

puts f['01
10'],T


puts f['01
11'],F

puts f['00
01'],F

puts f['11
11
'],T

puts f['110
100'],F

puts f['111
000'],T

puts f['111
101
111'],F

puts f['101
010
101
'],T

puts f['1101
0010
1101
0010'],T

puts f['1101
0010
1111
0010'],F

puts f['0011
0111
0100
'],F

puts f['0011
0011
1100'],T

puts f['00000000
01111110
00000000'],F

puts f['11111111
11111111
11111111'],T

puts f['0000001111
0000001111'],T

puts f['0000001111
0000011111'],F

puts f['0000001111
1000001111'],F

puts f['1000001111
1000001111'],T

puts f['1110100110101010110100010111011101000101111
1010100100101010100100010101010101100101000
1110100110010010110101010111010101010101011
1010100100101010010101010110010101001101001
1010110110101010110111110101011101000101111'],F

ฉันเดิมพันโดยใช้s.scan(/^?.*\n/)จะช่วยประหยัดไบต์
ไม่ใช่ชาร์ลส์ที่

3

หอยทาก 20 ไบต์

!{to{\0w`3\1|\1w`3\0

พิมพ์พื้นที่ของกริดหากไม่มี 2x2 สแควร์ที่มี 3 ศูนย์และหนึ่งหรือ 3 คนและศูนย์หรือ0ถ้ามี 2x2 สแควร์


3

MATLขนาด 12 ไบต์

Ybc2thYCs2\~

ขั้นตอนวิธีการเช่นเดียวกับคำตอบที่ดีของ @ SP3000

ในการอนุญาตให้ป้อนหลาย10บรรทัดMATL ต้องการอาร์เรย์แถว (สตริง) เพื่อสร้างขึ้นอย่างชัดเจนโดยใช้ตัวอักษรสำหรับการขึ้นบรรทัดใหม่ ดังนั้นอินพุตของตัวอย่างทั้งสี่คือ (โปรดทราบว่าการ[]ต่อข้อมูลดังนั้นแต่ละเหล่านี้จึงเป็นอาร์เรย์แถวของตัวอักษร):

['0011' 10 '0111' 10 '0100']
['0011' 10 '0011' 10 '1100']
['00000000' 10 '01111110' 10 '00000000']
['11111111' 10 '11111111' 10 '11111111']

และสามกรณีทดสอบสุดท้ายคือ

['0000001111' 10 '1000001111']
['1000001111' 10 '1000001111']
['1110100110101010110100010111011101000101111' 10 '1010100100101010100100010101010101100101000' 10 '1110100110010010110101010111010101010101011' 10 '1010100100101010010101010110010101001101001' 10 '1010110110101010110111110101011101000101111']

เอาท์พุทจริงเป็นอาร์เรย์ที่มีเพียงคนเดียว

ลองออนไลน์!

คำอธิบาย

นี่ใช้ความจริงที่ว่าความเท่าเทียมกันของตัวอักษร'0'และ'1'เหมือนกันกับตัวเลข0และ1ดังนั้นจึงไม่จำเป็นต้องแปลงจากอักขระเป็นตัวเลขที่แสดง

Yb     % split implicit input by whitespace. Gives a cell array
c      % concatenate cell contents into 2D char array
2th    % push array [2 2]
YC     % get 2×2 sliding blocks and arrange as columns
s      % sum of each column
2\     % modulo 2 of each sum
~      % negate. Implicit display

อินพุตต้องเป็นสตริง
งานอดิเรกของ Calvin

@HelkaHomba MATL ไม่อนุญาตให้ป้อนสตริงหลายบรรทัด ... อินพุตจะต้องเป็นอาร์เรย์แถวของฟอร์ม['first line' 10 'second llne']โดยที่10ASCII สำหรับบรรทัดใหม่ เป็นที่ยอมรับหรือไม่?
Luis Mendo

@HelkaHomba ฉันเคยใช้มันในคำตอบที่ปรับปรุงแล้ว หรือสามารถใช้พื้นที่แทน newline ได้หรือไม่ ตัวอย่างแรกจะเป็นสตริง'0011 0111 0100'
Luis Mendo

@ LuisMendo ฉันซาบซึ้งกับความคิด แต่ฉันคิดว่าคำตอบของ Ruby อาจจะเป็นนักกอล์ฟโดยทั่วไปที่นี่ :)
Sp3000

@ Sp3000 โอ้ฉันไม่เคยเห็นแบบนั้นมาก่อน ฉลาดมากเช่นกัน
Luis Mendo

2

JavaScript (ES6), 69 ไบต์

s=>!s.split`
`.some((t,i,u)=>[...t].some((v,j)=>v^t[0]^u[0][j]^s[0]))

ฉันเชื่อว่าเกณฑ์ความสัมพันธ์ของเส้นทางการเชื่อมต่อสี่เหลี่ยมผืนผ้านั้นเทียบเท่ากับที่กำหนดให้กับจุดสี่จุดใด ๆ ที่ก่อมุมของสี่เหลี่ยมผืนผ้าโดยพลการที่มีจำนวน1คู่ โปรดทราบว่าความเท่าเทียมกันของสี่เหลี่ยมผืนผ้า (0, b), (x, y) เหมือนกับ (0, b), (a, y) ^(a, b), (x, y) ดังนั้นฉันต้องตรวจสอบเท่านั้น รูปสี่เหลี่ยมผืนผ้าที่มีมุมซ้ายบนอยู่ที่ (0, 0) นอกจากนี้ตามกฎของเดอมอร์แกน!.some()ก็เหมือนกัน.every(!)ซึ่งช่วยฉันสองสามไบต์

แก้ไข: ฉันสังเกตเห็นว่าวิธีการแก้ปัญหาวุ้นตรวจสอบความเท่าเทียมกันของมุมของรูปสี่เหลี่ยมผืนผ้า 2 × 2 ซึ่งสามารถแสดงให้เทียบเท่า


เกือบ 7 ครั้ง แต่ +1
edc65

2

JavaScript (ES6), 79

อัลกอริทึมเดียวกันกับคำตอบของ Jelly จาก @ Sp3000 (และดีใจที่ไม่ต้องพิสูจน์ว่าใช้ได้) อีกต่อไปเพียง8 ครั้ง

s=>[...s].every((x,i)=>[++i,i+=s.search`
`,i+1].some(p=>!(x^=p=s[p],p>`
`))|!x) 

น้อย golfed

s=>[...s].every((x,i)=> // repeat check for every sub square
     [++i,                  // array of position for next char in row
      i+=s.search`\n`, i+1] // and 2 chars at same column in next row
       .some(p=> // for each position 
          !( 
            x^=s[p],  // xor current value with value at position p
            s[p]>`\n` // true if value at position p is valid
           ) // the condition is negated
       ) // if any value scanned is not valid, .some return true
         // else, we must consider the check for current square
       | !x // x can be 0 or 1, to be valid must be 0
   ) 

ชุดทดสอบ

f=s=>[...s].every((x,i)=>[++i,i+=s.search`
`,i+1].some(p=>!(x^=p=s[p],p>`
`))|!x) 

testData=`
0
T

1
T

00
T

01
T

10
T

11
T

0000000
T

1111111
T

011100100100101100110100100100101010100011100101
T

00
11
T

01
10
T

01
11
F

00
01
F

11
11
T

110
100
F

111
000
T

111
101
111
F

101
010
101
T

1101
0010
1101
0010
T

1101
0010
1111
0010
F

0011
0111
0100
F

0011
0011
1100
T

00000000
01111110
00000000
F

11111111
11111111
11111111
T

0000001111
0000001111
T

0000001111
0000011111
F

0000001111
1000001111
F

1000001111
1000001111
T

1110100110101010110100010111011101000101111
1010100100101010100100010101010101100101000
1110100110010010110101010111010101010101011
1010100100101010010101010110010101001101001
1010110110101010110111110101011101000101111
F`

console.log=x=>O.textContent+=x+'\n'

testData.split('\n\n').forEach(t=>{
  var k=t.slice(-1)=='T',
      r=f(t.slice(0,-1))
  console.log(t+' '+r+ (k==r?' OK\n':' KO\n'))
})  
<pre id=O></pre>


1
ตอนนี้อีกต่อไป 8 เท่า!
Neil

1

Grime v0.1, 31 ไบต์

E=\0+|\1+
N=.+&E!
e`(E/N|N/E)#!

พิมพ์1สำหรับการจับคู่และ0ไม่มีการจับคู่ ลองออนไลน์!

คำอธิบาย

Grime เป็นภาษาจับคู่รูปแบบ 2D ของฉัน ฉันทำการแก้ไขในวันนี้ แต่เพียงเพื่อเปลี่ยนลักษณะขององค์ประกอบไวยากรณ์ ( `แทน,) ดังนั้นจึงไม่ส่งผลกระทบต่อคะแนนของฉัน

ฉันกำลังใช้วิธีการคล้ายกับของSp3000 : การป้อนข้อมูลเป็นเท็จถ้ามันมีสี่เหลี่ยมผืนผ้า 2 × N ซึ่งหนึ่งแถวมีทั้ง0และ1และแถวอื่นไม่ได้

E=             Define a nonterminal E, which matches
  \0+|           a horizontal run of one or more 0s, OR
      \1+        a horizontal run of one or more 1s.
N=             Define a nonterminal N, which matches
  .+             a horizontal run of one or more characters,
    &E!          which is NOT matched by E (so contains both 0 and 1).
e`             Match entire input to this pattern:
            !    not
           #     contains
  (E/N|N/E)      E on top of N, or N on top of E

1

JavaScript (ES6), 64 ไบต์

s=>(a=s.split`
`).every(l=>l==a[0]|l==a[0].replace(/./g,n=>n^1))

ตามการสังเกตของ @ LevelRiverSt ว่าแต่ละบรรทัดจะต้องเหมือนกันหรือตรงข้ามกับบรรทัดแรก

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