Deteksi Persegi Panjang

21

Tulis program atau fungsi yang menggunakan string multiline 0's dan 1' s. Tidak ada karakter lain dalam string dan string akan selalu persegi panjang (semua garis akan memiliki jumlah karakter yang sama), dengan dimensi sekecil 1 × 1, tetapi jika 0's dan 1' dapat diatur secara sewenang-wenang.

Anda dapat mengasumsikan string memiliki baris tambahan opsional, dan jika diinginkan Anda dapat menggunakan dua karakter ASCII yang dapat dicetak untuk menggantikan 0dan 1.

Cetak atau kembalikan nilai kebenaran jika semua wilayah jalur yang terhubung baik 0dari dan 1di dalam string adalah persegi panjang yang solid , selain itu menghasilkan nilai palsu .

Sebuah jalan wilayah terhubung dari 0'berarti s bahwa dari salah satu 0di wilayah tersebut, semua yang lain 0' s dapat dicapai dengan hanya bergerak ke atas, bawah, kiri dan kanan untuk lainnya 0's (dan tidak bergerak diagonal, tidak bergerak untuk setiap 1, dan tidak bergerak di luar batas string). Ide yang sama berlaku untuk 1jalur yang terhubung wilayah.

Sebuah persegi panjang yang solid dari 0's berarti seluruh area persegi panjang diisi dengan 0' s dan tidak ada 1's. Gagasan yang sama berlaku untuk 1persegi panjang yang solid.

Kode terpendek dalam byte menang. Tiebreaker adalah jawaban sebelumnya.

(Perhatikan bahwa string tidak membungkus dengan kondisi batas toroidal .)

Contohnya

1) String input ini memiliki 3 jalur yang terhubung wilayah (2 untuk 0dan 1 untuk 1). Hanya daerah kanan bawah 00adalah persegi panjang yang solid, jadi outputnya akan palsu.

0011
0111
0100

2) String input ini memiliki 4 jalur yang terhubung wilayah (2 untuk keduanya 0dan 1). Semua dari mereka adalah persegi panjang yang solid sehingga hasilnya akan benar.

0011
0011
1100

3) Input ini memiliki 2 jalur yang terhubung dengan daerah, tetapi hanya satu dari mereka adalah persegi panjang yang solid, sehingga hasilnya akan palsu.

00000000
01111110
00000000

4) Input ini hanya memiliki 1 jalur yang terhubung wilayah dan biasanya merupakan persegi panjang yang solid, sehingga hasilnya benar.

11111111
11111111
11111111

Uji Kasus

Sebuah Ttepat di bawah berarti string input truthy, Fberarti 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
Hobi Calvin
sumber

Jawaban:

5

Jelly , 7 byte

ṣ⁷µ=ḢZE

Ini menggunakan algoritma yang sama dengan jawaban Ruby @ LevelRiverSt . Algoritma aktual sesuai dalam 4 byte terakhir; 3 byte pertama diperlukan untuk mem-parsing format input.

Cobalah online!

Bagaimana itu bekerja

ṣ⁷µ=Ḣ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.
Dennis
sumber
16

Jelly , 11 10 byte

ṣ⁷^2\⁺€FS¬

Terima kasih banyak kepada @Dennis untuk bermain golf yang ini hingga setengah dari ukuran aslinya (melalui fitur tidak berdokumen).

Cobalah online ! Perhatikan bahwa tanda kutip tiga adalah untuk string multiline.

Penjelasan

Algoritma dasarnya adalah: mengembalikan true iff setiap subgrid 2x2 memiliki angka genap 1s (atau, ekuivalen, 0s).

Sudah jelas mengapa angka ganjil 1s tidak dapat bekerja, karena kita akan memiliki salah satu dari yang berikut:

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

Perhatikan bahwa 4 pertama adalah rotasi dari hal yang sama, dan juga untuk 4 yang terakhir. Sudut refleks tidak dapat menjadi bagian dari persegi panjang, karenanya mengapa itu tidak valid.

Dengan kata lain, semua 2x2 subgrid harus merupakan salah satu dari yang berikut:

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

yang, jika kita melihat batas-batasnya, dapat dibayangkan sebagai "potongan puzzle" berikut:

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

Dan cobalah membentuk non-persegi panjang dengan potongan-potongan puzzle :) (sementara ujungnya cocok)

Implementasi yang sebenarnya adalah sebagai berikut:

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

Misalnya untuk input

100
010
000
101

kita punya:

  ṣ⁷: ["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
Sp3000
sumber
1
Bisakah Anda mendokumentasikan fitur yang Anda gunakan? Jika orang melakukannya maka dokumentasi akan terjadi!
CalculatorFeline
Apakah Anda perlu meratakan?
CalculatorFeline
@CatsAreFluffy Jika Anda tidak meratakan, Jelly mencoba untuk menjumlahkan daftar vektor dan Anda mendapatkan vektor sebagai hasilnya
Sp3000
Jumlah dan jumlah - lebih baik!
CalculatorFeline
4
"Fitur tidak berdokumen" - aha! Jadi yang ini bagaimana Dennis outgolfs semua orang! : 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}

Dalam kisi-kisi apa pun yang seluruhnya terdiri dari persegi panjang, setiap baris harus identik dengan garis sebelumnya, atau semua bit dibalik dari 0 ke 1 dan sebaliknya.

Ini mudah dibuktikan. Ambil selembar kertas dan gambar garis vertikal dan horizontal yang sewenang-wenang sepanjang jalan di atasnya. Sekarang warna persegi panjang hanya menggunakan 2 warna. Anda akan berakhir dengan kotak-kotak yang terdistorsi, di mana semua warna terbalik di setiap baris.

Ingin menggambar persegi panjang dengan garis yang hanya sebagian melintang? coba hapus segmen dari salah satu baris Anda. Anda sekarang akan membutuhkan lebih dari 2 warna untuk mewarnai desain Anda, karena Anda akan memiliki titik di mana 3 persegi panjang bertemu (2 sudut dan tepi.) Desain seperti itu karena itu tidak relevan dengan pertanyaan ini.

Saya terkejut jawaban sejauh ini belum memperhatikan ini.

Saya pikir algoritma ini harusnya jauh lebih pendek dalam beberapa bahasa lain.

Tidak digabungkan dalam program uji

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
Level River St
sumber
Saya yakin menggunakan s.scan(/^?.*\n/)akan membantu menghemat byte.
Bukan berarti Charles
3

Siput , 20 byte

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

Mencetak area kisi jika tidak ada kotak 2x2 dengan 3 nol dan satu atau 3 dan nol, atau 0jika ada kotak 2x2 seperti itu.

feersum
sumber
3

MATL , 12 byte

Ybc2thYCs2\~

Algoritma yang sama dengan jawaban luar biasa @ sp3000 .

Untuk memungkinkan input multiline, MATL membutuhkan array char baris (string) yang akan dibangun secara eksplisit menggunakan karakter 10untuk baris baru. Jadi input dari empat contoh tersebut adalah (perhatikan bahwa []adalah gabungan, sehingga masing-masing adalah deretan baris karakter):

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

dan tiga kasus uji terakhir adalah

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

Output yang benar adalah array yang hanya berisi yang.

Cobalah online!

Penjelasan

Ini menggunakan fakta bahwa paritas karakter '0'dan '1'sama dengan angka 0dan 1, jadi tidak perlu mengkonversi dari char ke digit yang diwakilinya,

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
Luis Mendo
sumber
Input harus berupa string
Hobi Calvin
@HelkaHomba MATL tidak mengizinkan input string multiline ... Input harus berupa larik baris formulir ['first line' 10 'second llne'], di mana 10ASCII untuk baris baru. Apakah itu dapat diterima?
Luis Mendo
@HelkaHomba Saya sudah menggunakannya dalam jawaban yang diperbarui. Atau, dapatkah ruang digunakan alih-alih baris baru? Contoh pertama adalah string'0011 0111 0100'
Luis Mendo
@LuisMendo Saya menghargai pemikiran itu, tapi saya pikir jawaban Ruby mungkin sebenarnya lebih golf di sini :)
Sp3000
@ Sp3000 Oh, saya belum melihat yang itu. Sangat pintar juga
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]))

Saya percaya bahwa kriteria persegi panjang hubungan jalan setara dengan mengharuskan bahwa diberikan empat poin yang membentuk sudut-sudut persegi panjang sewenang-wenang bahwa ada bilangan genap 1s. Perhatikan bahwa paritas persegi panjang (0, b), (x, y) sama dengan (0, b), (a, y) ^(a, b), (x, y) jadi saya hanya perlu memeriksa persegi panjang yang sudut kiri atas berada di (0, 0). Juga oleh hukum De Morgan, !.some()sama seperti .every(!)yang menyelamatkan saya beberapa byte.

Sunting: Saya perhatikan bahwa solusi Jelly memeriksa paritas sudut semua persegi panjang 2 × 2, yang dapat ditunjukkan setara.

Neil
sumber
hampir 7 kali, tetapi +1
edc65
2

JavaScript (ES6), 79

Algoritma yang sama dari jawaban Jelly dari @ Sp3000 (dan senang tidak harus membuktikannya berhasil). Hanya 8 kali lebih lama

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

Kurang golf

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
   ) 

Suite uji

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>

edc65
sumber
1
Sekarang 8 kali lebih lama!
Neil
1

Grime v0.1, 31 byte

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

Mencetak 1untuk pertandingan dan 0tanpa pertandingan.Cobalah online!

Penjelasan

Grime adalah bahasa pencocokan pola 2D saya. Saya memang memodifikasinya hari ini, tetapi hanya untuk mengubah karakter elemen sintaks ( `bukan, ), jadi itu tidak mempengaruhi skor saya.

Saya menggunakan pendekatan yang mirip dengan Sp3000 : input salah jika berisi 2 × N persegi panjang yang satu baris berisi keduanya 0dan 1, dan baris lainnya tidak.

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
Zgarb
sumber
1

JavaScript (ES6), 64 byte

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

Berdasarkan pengamatan @ LevelRiverSt bahwa setiap baris harus sama atau kebalikan dari yang pertama.

pengguna81655
sumber