Rechteckerkennung

21

Schreiben Sie ein Programm oder eine Funktion, die eine mehrzeilige Folge von 0's und 1' s enthält. Andere Zeichen werden in der Zeichenfolge sein , und die Zeichenfolge wird immer rechteckig sein (alle Linien dieselbe Anzahl von Zeichen haben), mit den Abmessungen so klein wie 1 × 1, aber ansonsten ist das 0"s und 1s können willkürlich angeordnet sein.

Sie können davon ausgehen, dass die Zeichenfolge eine optionale nachgestellte Newline enthält. Falls gewünscht, können Sie zwei verschiedene druckbare ASCII- Zeichen anstelle von 0und verwenden 1.

Drucke oder einen Rück truthy Wert , wenn alle von dem Pfad verbunden Regionen beide 0's und 1ist in der Zeichenfolge sind feste Rechtecken , sonst Ausgabe eines falsy Wert .

Eine pfadverbundene Region von 0's bedeutet, dass von einer beliebigen 0Region in der Region alle anderen 0erreicht werden können, indem man sich nur nach oben, unten, links und rechts zu den anderen bewegt 0(und sich nicht diagonal bewegt, sich nicht zu einer anderen bewegt 1, und nicht außerhalb der Zeichenkettengrenzen bewegen). Die gleiche Idee gilt für 1pfadverbundene Regionen.

Ein ausgefülltes Rechteck von 0's bedeutet, dass der gesamte Bereich des Rechtecks ​​mit 0' s und no 1's gefüllt ist . Die gleiche Idee gilt für 1ausgefüllte Rechtecke.

Der kürzeste Code in Bytes gewinnt. Tiebreaker ist frühere Antwort.

(Beachten Sie, dass die Zeichenfolge nicht mit toroidalen Randbedingungen umwickelt wird .)

Beispiele

1) Diese Eingangszeichenfolge hat 3 pfadverbundene Bereiche (2 für 0und 1 für 1). Nur der rechte untere 00Bereich ist ein ausgefülltes Rechteck, daher wäre die Ausgabe falsch.

0011
0111
0100

2) Diese Eingangszeichenfolge hat 4 pfadverbundene Bereiche (2 für beide 0und 1). Alle von ihnen sind feste Rechtecke, so dass die Ausgabe wahr sein würde.

0011
0011
1100

3) Dieser Eingang verfügt über 2 pfadverbundene Bereiche, von denen jedoch nur einer ein ausgefülltes Rechteck ist, sodass der Ausgang falsch wäre.

00000000
01111110
00000000

4) Dieser Eingang hat nur 1 Pfad verbundenen Bereich und ist trivial ein festes Rechteck, so dass der Ausgang wahr ist.

11111111
11111111
11111111

Testfälle

Ein Tknapp unter der Eingabezeile stehendes Zeichen bedeutet Wahrhaftigkeit, Fbedeutet Falschheit.

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
Calvins Hobbys
quelle

Antworten:

5

Gelee , 7 Bytes

ṣ⁷µ=ḢZE

Dies verwendet den gleichen Algorithmus wie die Ruby-Antwort von @ LevelRiverSt . Der tatsächliche Algorithmus passt in die letzten 4 Bytes. Die ersten 3 Bytes werden benötigt, um das Eingabeformat zu analysieren.

Probieren Sie es online!

Wie es funktioniert

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

Jelly , 11 bis 10 Bytes

ṣ⁷^2\⁺€FS¬

Ein großes Dankeschön an @Dennis für das Golfen auf die Hälfte seiner ursprünglichen Größe (über undokumentierte Features).

Probieren Sie es online ! Beachten Sie, dass die dreifachen Anführungszeichen für eine mehrzeilige Zeichenfolge gelten.

Erläuterung

Der grundlegende Algorithmus lautet: return true, wenn jedes 2x2-Subgrid eine gerade Zahl von 1s (oder äquivalent 0s) hat.

Es ist klar, warum eine ungerade Anzahl von Einsen nicht funktionieren kann, da wir eine der folgenden Möglichkeiten hätten:

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

Beachten Sie, dass die ersten 4 Umdrehungen dasselbe sind, und dasselbe gilt für die letzten 4. Der Reflexwinkel kann nicht Teil eines Rechtecks ​​sein, weshalb er ungültig wäre.

Mit anderen Worten, alle 2x2-Teilgitter müssen eines der folgenden sein:

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

Was, wenn wir uns die Grenzen ansehen, als die folgenden "Puzzleteile" vorgestellt werden kann:

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

Und versuchen Sie, mit diesen Puzzleteilen ein Nicht-Rechteck zu bilden :) (während die Enden übereinstimmen)

Die eigentliche Implementierung ist also:

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

Zum Beispiel für die Eingabe

100
010
000
101

wir haben:

  ṣ⁷: ["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
quelle
1
Können Sie bitte die von Ihnen verwendeten Funktionen dokumentieren? Wenn Leute das tun, wird Dokumentation passieren!
CalculatorFeline
Müssen Sie abflachen?
CalculatorFeline
@CatsAreFluffy Wenn Sie nicht abflachen, versucht Jelly, eine Liste von Vektoren zusammenzufassen, und Sie erhalten einen Vektor als Ergebnis
Sp3000
Nur Summe und Summe - es ist besser!
CalculatorFeline
4
"Undokumentierte Features" - aha! So das ist , wie Dennis outgolfs jeder! : D
AdmBorkBork
12

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

In einem Gitter, das ausschließlich aus Rechtecken besteht, muss jede Zeile mit der vorherigen Zeile identisch sein, oder es müssen alle Bits von 0 auf 1 und umgekehrt umgedreht werden.

Dies ist leicht zu beweisen. Nehmen Sie ein Blatt Papier und ziehen Sie beliebige vertikale und horizontale Linien darüber. Färben Sie nun die Rechtecke mit nur 2 Farben. Sie erhalten ein verzerrtes Schachbrettmuster, bei dem alle Farben in jeder Zeile umkehren.

Möchten Sie Rechtecke mit Linien zeichnen, die nur einen Teil der Breite haben? Versuchen Sie, ein Segment Ihrer Zeilen zu löschen. Sie benötigen jetzt mehr als 2 Farben, um Ihr Design einzufärben, da Sie Punkte haben, an denen sich 3 Rechtecke treffen (2 Ecken und eine Kante). Solche Designs sind daher für diese Frage irrelevant.

Ich bin überrascht, dass Antworten dies bisher nicht bemerkt haben.

Ich denke, dieser Algorithmus sollte in einer anderen Sprache viel kürzer sein.

Ungolfed im Testprogramm

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
quelle
Ich wette mit s.scan(/^?.*\n/)würde helfen, Bytes zu sparen.
Nicht dass Charles
3

Schnecken , 20 Bytes

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

Druckt den Bereich des Gitters, wenn es kein 2x2-Quadrat mit 3 Nullen und einer Eins oder drei Einsen und einer Null gibt oder 0wenn ein solches 2x2-Quadrat vorhanden ist.

Feersum
quelle
3

MATL , 12 Bytes

Ybc2thYCs2\~

Gleicher Algorithmus wie die großartige Antwort von @ sp3000 .

Um mehrzeilige Eingaben zuzulassen, muss das Zeilenzeichen-Array (String) explizit mit Zeichen 10für Zeilenvorschub erstellt werden. Die Eingabe der vier Beispiele []lautet also (beachten Sie, dass es sich bei der Verkettung um ein Zeilenarray von Zeichen handelt):

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

und die letzten drei Testfälle sind

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

Die Ausgabe von Truthy ist ein Array, das nur Einsen enthält.

Probieren Sie es online!

Erläuterung

Dies nutzt die Tatsache, dass die Parität von Zeichen '0'und '1'die gleiche ist wie die von Zahlen 0und 1, so dass es nicht erforderlich ist, von char zu der Ziffer, die es darstellt, zu konvertieren.

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
quelle
Die Eingabe muss eine Zeichenfolge sein
Calvins Hobbys
@HelkaHomba MATL erlaubt keine Eingabe von mehrzeiligen Zeichenfolgen ... Die Eingabe müsste ein Zeilenarray des Formulars sein ['first line' 10 'second llne'], wobei 10ASCII für newline ist. Ist das akzeptabel
Luis Mendo
@HelkaHomba Ich habe das in der aktualisierten Antwort verwendet. Alternativ kann Leerzeichen anstelle von Zeilenvorschub verwendet werden? Das erste Beispiel wäre String'0011 0111 0100'
Luis Mendo
@ LuisMendo Ich schätze den Gedanken, aber ich denke, die Ruby-Antwort könnte hier im Allgemeinen tatsächlich Golfspieler sein :)
Sp3000
@ Sp3000 Oh, das hatte ich nicht gesehen. Sehr klug auch
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]))

Ich glaube, dass das Kriterium des Wegeverbindungsrechtecks ​​der Forderung entspricht, dass es bei vier beliebigen Punkten, die die Ecken eines beliebigen Rechtecks ​​bilden, eine gerade Anzahl von 1s gibt. Beachten Sie, dass die Parität des Rechtecks ​​(0, b), (x, y) mit (0, b), (a, y), ^(a, b), (x, y) identisch ist , sodass ich nur prüfen muss die Rechtecke, deren obere linke Ecke bei (0, 0) liegt. Auch nach De Morgans Gesetzen !.some()ist es dasselbe, .every(!)was mir ein paar Bytes erspart.

Bearbeiten: Ich stelle fest, dass die Jelly-Lösung die Parität der Ecken aller 2 × 2-Rechtecke überprüft, die als äquivalent dargestellt werden können.

Neil
quelle
fast 7 Mal, aber +1
edc65
2

JavaScript (ES6), 79

Gleicher Algorithmus der Jelly-Antwort von @ Sp3000 (und froh, nicht beweisen zu müssen, dass es funktioniert). Nur 8 mal länger

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

Weniger golfen

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
   ) 

Testsuite

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
quelle
1
Jetzt 8 mal länger!
Neil
1

Grime v0.1, 31 Bytes

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

Druckt 1für Übereinstimmung und 0für keine Übereinstimmung. Probieren Sie es online!

Erläuterung

Schmutz ist meine 2D-Pattern-Matching-Sprache. Ich habe es heute geändert, aber nur, um den Charakter eines Syntaxelements ( `statt ,) zu ändern , damit es meine Punktzahl nicht beeinflusst.

Ich benutze einen ähnlichen Ansatz wie Sp3000 : Eine Eingabe ist falsch, wenn sie ein 2 × N-Rechteck enthält, dessen eine Zeile beide 0und enthält 1, und die andere Zeile nicht.

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
quelle
1

JavaScript (ES6), 64 Byte

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

Basierend auf der Beobachtung von @ LevelRiverSt, dass jede Linie entweder die gleiche oder die entgegengesetzte sein muss wie die erste.

user81655
quelle