Обнаружение прямоугольника

21

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

Вы можете предположить, что в строке есть дополнительный завершающий символ новой строки, и при желании вы можете использовать любые два различных печатаемых символа ASCII вместо 0и 1.

Выведите или верните истинное значение, если все области, связанные путями, и 0s, и 1s в строке являются сплошными прямоугольниками , в противном случае выведите ложное значение .

Связно область из 0«средств s , что из любого 0региона, все остальные 0» s может быть достигнуто только перемещения вверх, вниз, влево и вправо к другому 0«s (и не двигаться по диагонали, не двигаясь к любому 1, и не выходя за пределы строки). Та же самая идея относится к 1областям, связанным путями.

Твердый прямоугольник из 0«означает сек всей площади прямоугольника не заполняется 0» ы и нет 1«ы. Та же идея относится и к 1сплошным прямоугольникам.

Самый короткий код в байтах побеждает. Tiebreaker - более ранний ответ.

(Обратите внимание, что строка не имеет тороидальных граничных условий .)

Примеры

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ниже входной строки означает правдивость, 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 байта; первые 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 за игру в гольф до половины ее первоначального размера (благодаря недокументированным функциям).

Попробуйте онлайн ! Обратите внимание, что тройные кавычки предназначены для многострочной строки.

объяснение

Основной алгоритм: вернуть true, если каждая подсетка 2x2 имеет четное число 1 с (или, что эквивалентно, 0 с).

Понятно, почему нечетное число 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
Sp3000
источник
1
Можете ли вы пойти документировать функции, которые вы использовали? Если люди это сделают, тогда будет документация!
CalculatorFeline
Вам нужно сгладить?
CalculatorFeline
@CatsAreFluffy Если вы не сгладите, Jelly попытается суммировать список векторов, и в результате вы получите вектор
Sp3000
Просто сумма и сумма - это лучше!
CalculatorFeline
4
«Недокументированные черты» - ага! Вот так Денис обгоняет всех! : 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 угла и ребро). Поэтому такие дизайны не имеют отношения к этому вопросу.

Я удивлен ответами, пока не заметил этого.

Я думаю, что этот алгоритм должен быть намного короче на каком-то другом языке.

Неуправляемый в тестовой программе

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
Уровень реки St
источник
Бьюсь об заклад, использование s.scan(/^?.*\n/)поможет сэкономить байты.
Не то чтобы Чарльз
3

Улитки , 20 байт

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

Печатает область сетки, если не существует квадрата 2x2 с 3 нулями и единичным или 3 единицами и нулем, или 0если такой квадрат 2x2 существует.

feersum
источник
3

MATL , 12 байт

Ybc2thYCs2\~

Тот же алгоритм, что и у великолепного ответа @ sp3000 .

Чтобы разрешить многострочный ввод, MATL необходимо, чтобы массив строк (строка) был явно создан с использованием символа 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']

Истинный вывод - это массив, содержащий только единицы.

Попробуйте онлайн!

объяснение

При этом используется тот факт , что соотношение символов '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 Я ценю эту мысль, но я думаю, что ответ Ruby в действительности может быть более подходящим для игры в гольф здесь :)
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>

edc65
источник
1
Теперь в 8 раз дольше!
Нил
1

Grime v0.1, 31 байт

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

Отпечатки 1для матча и 0без матча. Попробуйте онлайн!

объяснение

Grime - мой язык сопоставления двухмерных шаблонов. Я изменил его сегодня, но только для изменения характера элемента синтаксиса ( `вместо ,), чтобы он не влиял на мой счет.

Я использую подход, аналогичный подходу 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
Zgarb
источник
1

JavaScript (ES6), 64 байта

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

Основываясь на наблюдении @ LevelRiverSt, каждая строка должна быть одинаковой или противоположной первой.

user81655
источник