Виявлення прямокутника


21

Напишіть програму або функцію, яка містить багаторядкові рядки 0's і 1' s. Жодних інших символів не буде в рядку, і рядок завжди буде прямокутним (усі рядки матимуть однакову кількість символів), розміри яких становлять 1 × 1, але в іншому випадку 0'і і 1можуть бути розташовані довільно.

Ви можете припустити, що в рядку є необов'язковий останній новий рядок, і при бажанні ви можете використовувати будь-які два різних символів для друку ASCII замість 0та 1.

Роздрукуйте або поверніть значення "truthy", якщо всі області, пов'язані з контуром, і 0s, і 1s у рядку є суцільними прямокутниками , інакше вивести помилкове значення .

Область, пов'язана з 0шляхом, означає, що з будь-якого 0регіону 0можна дістатися до всіх інших , лише рухаючись вгору, вниз, вліво та вправо до інших 0не рухаючись по діагоналі, не рухаючись до жодної 1, і не рухається за межі рядків). Ця ж ідея стосується 1областей, пов'язаних з трактом.

Твердий прямокутник з 0«означає сек всій площі прямокутника не заповнюється 0» и і немає 1«и. Ця ж ідея стосується 1суцільних прямокутників.

Виграє найкоротший код у байтах. Тирбейкер - це відповідь раніше.

(Зверніть увагу, що рядок не обертається з тороїдальними граничними умовами .)

Приклади

1) Цей вхідний рядок має 3 області, пов'язані шляхом (2 для 0та 1 для 1). Тільки в нижній правій 00області є суцільний прямокутник, тому вихід буде хибним.

0011
0111
0100

2) Цей вхідний рядок має 4 області, пов'язані шляхом (2 для обох 0і 1). Усі вони є суцільними прямокутниками, тому вихід був би простий.

0011
0011
1100

3) Цей вхід має дві області, пов'язані з контуром, але лише одна з них є суцільним прямокутником, тому вихід буде хибним.

00000000
01111110
00000000

4) Цей вхід має лише 1 область, пов'язану з контуром, і є тривіально суцільним прямокутником, тому вихід є простий.

11111111
11111111
11111111

Випробування

Трохи Tнижче введення рядка означає truthy, Fозначає хибність .

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

Для цього використовується той же алгоритм, що і відповідь Ruby @ LevelRiverSt . Фактичний алгоритм вписується в останні 4 байти; перші три байти потрібні для розбору формату введення.

Спробуйте в Інтернеті!

Як це працює

ṣ⁷µ=Ḣ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 за те, що він займався гольфом, до половини його початкового розміру (за допомогою недокументованих функцій).

Спробуйте в Інтернеті ! Зверніть увагу, що потрійні лапки призначені для рядкового рядка.

Пояснення

Основний алгоритм: повертайте справжній iff, кожна кожна підрешітка 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 Якщо ви не згладжуєтесь, Jelly намагається підбити підсумок списку векторів, і в результаті ви отримаєте вектор
Sp3000

Просто суму і суму - це краще!
CalculatorFeline

4
"Недокументовані функції" - ага! Так ось , як Денніс 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 кольори. Ви закінчите викривлену шахівницю, де всі кольори переливають у кожному рядку.

Хочете намалювати прямокутники з лініями лише частиною впоперек? спробуйте видалити сегмент будь-якого з рядків. Тепер вам знадобиться більше двох кольорів для кольорового дизайну, оскільки у вас з’являться точки, де зустрічаються 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

Друкує площу сітки, якщо немає 2х2 квадрата з 3 нулями, а також одним чи трьома нулями, або 0якщо такий квадрат 2х2 існує.


3

MATL , 12 байт

Ybc2thYCs2\~

Той самий алгоритм, як і чудова відповідь @ sp3000 .

Щоб дозволити багаторядковий вхід, MATL потребує чітко побудованого масиву рядків char (string), використовуючи символ 10для нового рядка. Отже, вхід чотирьох прикладів є (зверніть увагу, що []це конкатенація, тому кожен з них є масивом рядків символів):

['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']

Truthy вихід - це масив, що містить лише один.

Спробуйте в Інтернеті!

Пояснення

Для цього використовується той факт, що парність знаків '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

Вхід повинен бути рядком
Хобі Кальвіна

@HelkaHomba MATL не дозволяє вводити рядковий рядок ... Вхід повинен бути рядковим масивом форми ['first line' 10 'second llne'], де 10ASCII для нового рядка. Це прийнятно?
Луїс Мендо

@HelkaHomba Я використав це в оновленій відповіді. Чи можна використовувати простір замість нового рядка? Перший приклад'0011 0111 0100'
Луїс Мендо

@LuisMendo Я ціную цю думку, але думаю, що відповідь Рубі насправді тут може бути гольфістом :)
Sp3000

@ Sp3000 О, я цього не бачив. Дуже розумний теж
Луїс Мендо

2

JavaScript (ES6), 69 байт

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

Я вважаю, що критерій прямокутника зв’язності шляху є еквівалентним вимогам, якщо задано чотири точки, які утворюють кути довільного прямокутника, що є парне число 1s. Зауважте, що парність прямокутника (0, b), (x, y) така ж, як (0, b), (a, y) ^(a, b), (x, y), тому мені залишається лише перевірити ті прямокутники, лівий верхній кут яких (0, 0). Також за законами Де Моргана - !.some()це те саме, .every(!)що заощаджує мені пару байтів.

Редагувати: Я помічаю, що рішення Jelly перевіряє парність кутів усіх прямокутників 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) 

Менше гольфу

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 разів довше!
Ніл

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, що кожен рядок повинен бути або однаковим, або протилежним першому.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.