Rilevamento rettangolo


21

Scrivi un programma o una funzione che accetta una stringa multilinea di 0"se 1". Non ci saranno altri caratteri nella stringa e la stringa sarà sempre rettangolare (tutte le linee avranno lo stesso numero di caratteri), con dimensioni piccole come 1 × 1, ma in caso contrario le lettere 0"s 1" e "s" possono essere organizzate in modo arbitrario.

È possibile supporre che la stringa abbia una nuova riga finale opzionale e, se lo si desidera, è possibile utilizzare due caratteri ASCII stampabili distinti al posto di 0e 1.

Stampare o restituire un valore truthy se tutto il percorso collegato regioni di entrambi 0's e 1' s nella stringa sono rettangoli pieni , uscita altrimenti un valore falsy .

Una regione connessa al percorso di 0significa che da qualsiasi 0nella regione, tutte le altre 0possono essere raggiunte solo spostandosi verso l'alto, il basso, a sinistra e a destra verso le altre 0(e non spostandosi in diagonale, non spostandosi verso nessuna 1, e non muoversi al di fuori dei limiti della stringa). La stessa idea si applica alle 1regioni connesse al percorso.

Un rettangolo solido di 0'significa che l'intera area del rettangolo è riempita con 0' e no 1. La stessa idea si applica ai 1rettangoli solidi.

Vince il codice più breve in byte. Tiebreaker è la risposta precedente.

(Notare che la corda non si avvolge con le condizioni al contorno toroidali .)

Esempi

1) Questa stringa di input ha 3 regioni connesse al percorso (2 per 0e 1 per 1). 00Tuttavia, solo la regione in basso a destra è un rettangolo solido, quindi l'output sarebbe falso.

0011
0111
0100

2) Questa stringa di input ha 4 regioni connesse al percorso (2 per entrambi 0e 1). Tutti loro sono rettangoli solidi, quindi l'output sarebbe veritiero.

0011
0011
1100

3) Questo input ha 2 regioni connesse al percorso, ma solo una di esse è un rettangolo solido, quindi l'output sarebbe errato.

00000000
01111110
00000000

4) Questo input ha solo 1 regione connessa al percorso ed è banalmente un rettangolo solido, quindi l'output è veritiero.

11111111
11111111
11111111

Casi test

Un valore Tappena sotto la stringa di input significa verità, Fsignifica falsa.

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

Risposte:


5

Gelatina , 7 byte

ṣ⁷µ=ḢZE

Questo utilizza lo stesso algoritmo della risposta Ruby di @ LevelRiverSt . L'algoritmo effettivo si adatta negli ultimi 4 byte; i primi 3 byte sono necessari per analizzare il formato di input.

Provalo online!

Come funziona

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

Gelatina , 11 10 byte

ṣ⁷^2\⁺€FS¬

Grazie infinite a @Dennis per aver giocato a golf fino a metà delle sue dimensioni originali (tramite funzionalità non documentate).

Provalo online ! Si noti che le virgolette triple sono per una stringa multilinea.

Spiegazione

L'algoritmo di base è: restituisce vero iff ogni subgrid 2x2 ha un numero pari di 1s (o, equivalentemente, 0s).

È chiaro il motivo per cui un numero dispari di 1 non può funzionare, poiché avremmo una delle seguenti:

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

Nota che i primi 4 sono rotazioni della stessa cosa e idem per gli ultimi 4. L'angolo riflesso non può far parte di un rettangolo, quindi perché non sarebbe valido.

In altre parole, tutte le griglie secondarie 2x2 devono essere una delle seguenti:

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

che, se guardiamo i confini, possono essere immaginati come i seguenti "pezzi del puzzle":

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

E prova a formare un non rettangolo con quei pezzi del puzzle :) (pur avendo le estremità abbinate)

L'attuazione effettiva è quindi:

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

Ad esempio, per l'input

100
010
000
101

noi abbiamo:

  ṣ⁷: ["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
Puoi per favore andare a documentare le funzionalità che hai usato? Se la gente lo fa, accadrà la documentazione!
CalcolatriceFeline

Devi appiattire?
Calcolatrice

@CatsAreFluffy Se non si appiattisce, Jelly cerca di sommare un elenco di vettori e di conseguenza ottieni un vettore
Sp3000,

Somma e somma, è meglio!
Calcolatrice

4
"Funzionalità non documentate" - aha! Quindi, questo è come Dennis outgolfs tutti! : 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}

In qualsiasi griglia composta interamente da rettangoli, ogni riga deve essere identica alla riga precedente o avere tutti i bit capovolti da 0 a 1 e viceversa.

Questo è facile da dimostrare. Prendi un pezzo di carta e disegna arbitrariamente linee verticali e orizzontali su di esso. Ora colora i rettangoli usando solo 2 colori. Si finirà con una scacchiera distorta, in cui tutti i colori si capovolgono su ogni riga.

Vuoi disegnare rettangoli con linee solo a metà strada? prova a eliminare un segmento di una qualsiasi delle tue linee. Ora avrai bisogno di più di 2 colori per colorare il tuo disegno, perché avrai punti in cui 3 rettangoli si incontrano (2 angoli e un bordo.) Tali disegni sono quindi irrilevanti per questa domanda.

Sono sorpreso che le risposte finora non lo abbiano notato.

Penso che questo algoritmo dovrebbe essere molto più breve in qualche altra lingua.

Non registrato nel programma di test

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

Scommetto che usare s.scan(/^?.*\n/)aiuterebbe a salvare byte.
Non che Charles

3

Lumache , 20 byte

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

Stampa l'area della griglia se non c'è un quadrato 2x2 con 3 zeri e uno o 3 uno e uno zero, o 0se esiste un quadrato 2x2.


3

MATL , 12 byte

Ybc2thYCs2\~

Stesso algoritmo della grande risposta di @ sp3000 .

Per consentire l'input multilinea, MATL richiede che l'array di caratteri di riga (stringa) sia esplicitamente creato utilizzando il carattere 10per newline. Quindi l'input dei quattro esempi sono (nota che []è concatenazione, quindi ognuno di questi è un array di righe di caratteri):

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

e gli ultimi tre casi di test sono

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

L'output vero è un array contenente solo quelli.

Provalo online!

Spiegazione

Questo utilizza il fatto che la parità di caratteri '0'ed '1'è lo stesso di quello dei numeri 0e 1, quindi non sufficiente ad convertire da char alla cifra che rappresenta,

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

L'input deve essere una stringa
Calvin's Hobbies,

@HelkaHomba MATL non consente l'input di stringhe su più righe ... L'input dovrebbe essere un array di righe del modulo ['first line' 10 'second llne'], dove 10è ASCII per newline. È accettabile?
Luis Mendo,

@HelkaHomba L'ho usato nella risposta aggiornata. In alternativa, è possibile utilizzare lo spazio anziché newline? Il primo esempio sarebbe la stringa'0011 0111 0100'
Luis Mendo,

@LuisMendo Apprezzo il pensiero, ma penso che la risposta di Ruby potrebbe essere più golfista in generale qui :)
Sp3000

@ Sp3000 Oh, non l'avevo visto. Molto intelligente
Luis Mendo il

2

JavaScript (ES6), 69 byte

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

Credo che il criterio del rettangolo di connessione del percorso sia equivalente a richiedere quello dato quattro punti qualsiasi che formano gli angoli di un rettangolo arbitrario che ci sia un numero pari di 1s. Nota che la parità del rettangolo (0, b), (x, y) è uguale a (0, b), (a, y) ^(a, b), (x, y), quindi devo solo controllare quei rettangoli il cui angolo in alto a sinistra è in (0, 0). Anche secondo le leggi di De Morgan, !.some()è lo stesso .every(!)che mi fa risparmiare un paio di byte.

Modifica: noto che la soluzione Jelly controlla la parità degli angoli di tutti i rettangoli 2 × 2, che possono essere mostrati equivalenti.


quasi 7 volte, ma +1
edc65

2

JavaScript (ES6), 79

Lo stesso algoritmo di Jelly risponde da @ Sp3000 (e felice di non doverlo dimostrare che funziona). Solo 8 volte di più

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

Meno 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 di test

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
Ora 8 volte di più!
Neil,

1

Grime v0.1, 31 byte

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

Stampa 1per corrispondenza e 0per nessuna corrispondenza. Provalo online!

Spiegazione

Grime è il mio linguaggio di corrispondenza dei motivi 2D. L'ho modificato oggi, ma solo per cambiare il carattere di un elemento di sintassi ( `anziché ,), quindi non influisce sul mio punteggio.

Sto usando un approccio simile a quello di Sp3000 : un input è falso se contiene un rettangolo 2 × N la cui una riga contiene sia 0e 1che l'altra no.

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))

Sulla base dell'osservazione di @ LevelRiverSt che ogni riga deve essere uguale o opposta alla prima.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.