Phát hiện hình chữ nhật


21

Viết chương trình hoặc hàm có trong một chuỗi nhiều dòng của 0's và 1'. Không nhân vật khác sẽ nằm trong chuỗi và chuỗi sẽ luôn là hình chữ nhật (tất cả các dòng sẽ có cùng một số nhân vật), với kích thước nhỏ như 1 × 1, nhưng nếu không thì 0's và 1' s có thể được sắp xếp tùy tiện.

Bạn có thể giả sử chuỗi có một dòng mới tùy chọn và nếu muốn, bạn có thể sử dụng bất kỳ hai ký tự ASCII có thể in riêng biệt nào thay cho 01.

In hoặc trả về một giá trị trung thực nếu tất cả các vùng được kết nối của cả hai 01trong chuỗi là hình chữ nhật liền khối , mặt khác tạo ra giá trị sai .

Một con đường kết nối khu vực của 0'có nghĩa là s mà từ bất kỳ một 0trong khu vực, tất cả các khác 0' s có thể đạt được bằng cách chỉ di chuyển lên, xuống, sang trái và phải để khác 0's (và không di chuyển theo đường chéo, không di chuyển đến bất kỳ 1, và không di chuyển ngoài giới hạn chuỗi). Ý tưởng tương tự áp dụng cho 1các vùng kết nối đường dẫn.

Một hình chữ nhật rắn của 0's phương tiện toàn bộ diện tích của hình chữ nhật được làm đầy với 0' s và không có 1's. Ý tưởng tương tự áp dụng cho 1hình chữ nhật rắn.

Mã ngắn nhất tính bằng byte thắng. Tiebreaker là câu trả lời trước đó.

(Lưu ý rằng chuỗi không quấn quanh với các điều kiện biên hình xuyến .)

Ví dụ

1) Chuỗi đầu vào này có 3 vùng được kết nối đường dẫn (2 cho 0và 1 cho 1). Chỉ có vùng dưới cùng bên phải 00là một hình chữ nhật chắc chắn, vì vậy đầu ra sẽ là giả.

0011
0111
0100

2) Chuỗi đầu vào này có 4 vùng kết nối đường dẫn (2 cho cả hai 01). Tất cả chúng đều là hình chữ nhật chắc chắn nên đầu ra sẽ là sự thật.

0011
0011
1100

3) Đầu vào này có 2 vùng được kết nối đường dẫn, nhưng chỉ một trong số chúng là một hình chữ nhật chắc chắn, vì vậy đầu ra sẽ bị sai lệch.

00000000
01111110
00000000

4) Đầu vào này chỉ có 1 vùng kết nối đường dẫn và tầm thường là một hình chữ nhật chắc chắn, vì vậy đầu ra là trung thực.

11111111
11111111
11111111

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

Một Tngay bên dưới chuỗi đầu vào có nghĩa là trung thực, Fcó nghĩa là giả.

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

Câu trả lời:


5

Thạch , 7 byte

ṣ⁷µ=ḢZE

Điều này sử dụng thuật toán tương tự như câu trả lời Ruby của @ LevelRiverSt . Thuật toán thực tế phù hợp với 4 byte cuối cùng; 3 byte đầu tiên được yêu cầu để phân tích định dạng đầu vào.

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

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

ṣ⁷µ=Ḣ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

Thạch , 11 10 byte

ṣ⁷^2\⁺€FS¬

Rất cảm ơn @Dennis vì đã chơi golf này xuống một nửa kích thước ban đầu của nó (thông qua các tính năng không có giấy tờ).

Hãy thử trực tuyến ! Lưu ý rằng các trích dẫn ba là cho một chuỗi nhiều dòng.

Giải trình

Thuật toán cơ bản là: trả về iff đúng sau mỗi subgrid 2x2 có số chẵn là 1s (hoặc tương đương là 0s).

Rõ ràng tại sao một số lẻ 1 không thể hoạt động, vì chúng ta sẽ có một trong những điều sau đây:

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

Lưu ý rằng 4 đầu tiên là các phép quay của cùng một thứ và ditto cho 4. cuối cùng góc phản xạ không thể là một phần của hình chữ nhật, do đó tại sao nó không hợp lệ.

Nói cách khác, tất cả các lớp con 2x2 phải là một trong những điều sau đây:

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

trong đó, nếu chúng ta nhìn vào các ranh giới, có thể được tưởng tượng như là "mảnh ghép" sau đây:

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

Và thử tạo thành một hình chữ nhật với các mảnh ghép đó :) (trong khi có các đầu khớp với nhau)

Do đó, việc thực hiện là:

ṣ⁷               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

Ví dụ: cho đầu vào

100
010
000
101

chúng ta có:

  ṣ⁷: ["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
Bạn có thể vui lòng đi tài liệu các tính năng bạn sử dụng? Nếu mọi người làm điều đó thì tài liệu sẽ xảy ra!
Máy

Bạn có cần phải làm phẳng?
Máy

@CatsAreFluffy Nếu bạn không làm phẳng, Jelly cố gắng tổng hợp danh sách các vectơ và kết quả là bạn sẽ có được một vectơ
Sp3000

Chỉ cần tổng hợp và tổng hợp - tốt hơn!
Máy

4
"Tính năng không có giấy tờ" - aha! Vì vậy, đó là cách Dennis vượt qua tất cả mọi người! : D
admBorkBork

12

Ruby, 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}

Trong bất kỳ lưới nào bao gồm toàn bộ hình chữ nhật, mỗi dòng phải giống hệt với dòng trước hoặc có tất cả các bit được lật từ 0 đến 1 và ngược lại.

Điều này là dễ dàng để chứng minh. Lấy một mảnh giấy và vẽ các đường dọc và ngang tùy ý trên suốt đường đi. Bây giờ tô màu các hình chữ nhật chỉ sử dụng 2 màu. Bạn sẽ kết thúc với một bàn cờ bị biến dạng, trong đó tất cả các màu lật ở mỗi dòng.

Bạn muốn vẽ hình chữ nhật với các đường chỉ cách một phần? hãy thử xóa một đoạn của bất kỳ dòng nào của bạn. Bây giờ bạn sẽ cần nhiều hơn 2 màu để tô màu cho thiết kế của mình, bởi vì bạn sẽ có các điểm mà 3 hình chữ nhật gặp nhau (2 góc và một cạnh.) Các thiết kế như vậy không liên quan đến câu hỏi này.

Tôi ngạc nhiên câu trả lời cho đến nay đã không nhận thấy điều này.

Tôi nghĩ thuật toán này nên ngắn hơn rất nhiều ở một số ngôn ngữ khác.

Ungolfed trong chương trình thử nghiệm

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

Tôi đặt cược bằng cách sử dụng s.scan(/^?.*\n/)sẽ giúp tiết kiệm byte.
Không phải Charles

3

Ốc , 20 byte

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

In diện tích của lưới nếu không có hình vuông 2x2 có 3 số 0 và một hoặc 3 và số 0 hoặc 0nếu hình vuông 2x2 như vậy tồn tại.


3

MATL , 12 byte

Ybc2thYCs2\~

Thuật toán tương tự như câu trả lời tuyệt vời của @ sp3000 .

Để cho phép đầu vào đa dòng, MATL cần mảng char hàng (chuỗi) được xây dựng rõ ràng bằng cách sử dụng ký tự 10cho dòng mới. Vì vậy, đầu vào của bốn ví dụ là (lưu ý []là ghép, vì vậy mỗi trong số này là một mảng ký tự hàng):

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

và ba trường hợp thử nghiệm cuối cùng là

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

Đầu ra thật là một mảng chỉ chứa những cái.

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

Giải trình

Điều này sử dụng thực tế là tính chẵn lẻ của ký tự '0''1'giống như số 01vì vậy không cần phải chuyển đổi từ char sang chữ số mà nó đại diện,

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

Đầu vào cần phải là một chuỗi
Sở thích của Calvin

@HelkaHomba MATL không cho phép nhập chuỗi nhiều dòng ... Đầu vào sẽ phải là một mảng hàng của biểu mẫu ['first line' 10 'second llne'], trong đó 10ASCII cho dòng mới. Điều đó có được chấp nhận không?
Luis Mendo

@HelkaHomba Tôi đã sử dụng nó trong câu trả lời được cập nhật. Ngoài ra, không gian có thể được sử dụng thay vì dòng mới? Ví dụ đầu tiên sẽ là chuỗi'0011 0111 0100'
Luis Mendo

@LuisMendo Tôi đánh giá cao suy nghĩ này, nhưng tôi nghĩ rằng câu trả lời của Ruby thực sự có thể là người chơi golf nói chung ở đây :)
Sp3000

@ Sp3000 Ồ, tôi chưa thấy cái đó. Cũng rất thông minh
Luis Mendo

2

JavaScript (ES6), 69 byte

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

Tôi tin rằng tiêu chí hình chữ nhật kết nối đường dẫn tương đương với yêu cầu cho bốn điểm bất kỳ tạo thành các góc của hình chữ nhật tùy ý có số 1s chẵn . Lưu ý rằng tính chẵn lẻ của hình chữ nhật (0, b), (x, y) giống với (0, b), (a, y) ^(a, b), (x, y) nên tôi chỉ phải kiểm tra những hình chữ nhật có góc trên cùng bên trái là (0, 0). Cũng theo luật của De Morgan, !.some()cũng giống như .every(!)việc tiết kiệm cho tôi một vài byte.

Chỉnh sửa: Tôi nhận thấy rằng giải pháp Jelly kiểm tra tính chẵn lẻ của các góc của tất cả các hình chữ nhật 2 × 2, có thể được hiển thị là tương đương.


gần 7 lần, nhưng +1
edc65

2

JavaScript (ES6), 79

Thuật toán tương tự của Jelly trả lời từ @ Sp3000 (và vui vì không phải chứng minh nó hoạt động). Chỉ cần 8 lần nữa

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

Ít chơi gôn

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
   ) 

Bộ kiểm tra

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
Bây giờ dài hơn 8 lần!
Neil

1

Grime v0.1, 31 byte

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

In 1cho khớp và 0không khớp. Hãy thử trực tuyến!

Giải trình

Grime là ngôn ngữ phù hợp với mô hình 2D của tôi. Tôi đã sửa đổi nó ngày hôm nay, nhưng chỉ để thay đổi ký tự của một yếu tố cú pháp ( `thay vì ,), vì vậy nó không ảnh hưởng đến điểm số của tôi.

Tôi đang sử dụng một cách tiếp cận tương tự như của Sp3000 : đầu vào bị sai lệch nếu nó chứa hình chữ nhật 2 × N có một hàng chứa cả hai 01hàng còn lại thì không.

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 byte

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

Dựa trên quan sát của @ LevelRiverSt rằng mỗi dòng phải giống nhau hoặc ngược lại với dòng đầu tiên.

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.