È L-convesso?


14

sfondo

Un poliomino è chiamato L-convesso , se è possibile viaggiare da qualsiasi piastrella a qualsiasi altra piastrella mediante un percorso a forma di L, cioè un percorso che va nelle direzioni cardinali e cambia direzione al massimo una volta. Ad esempio, il poliomino di 1s nella figura

0 0 1 1 1 0

1 1 1 1 0 0

1 1 0 0 0 0

non è L-convesso, poiché entrambi i percorsi a forma di L dal basso a sinistra 1in alto a destra 1contengono un 0:

0>0>1>1>1 0
^       ^
1 1 1 1 0 0
^       ^
1>1>0>0>0 0

Tuttavia, il poliomino di 1s in questa figura è L-convesso:

0 1 1 1 0 0

1 1 1 1 1 1

0 1 1 0 0 0

Ingresso

L'input è una matrice 2D di bit nel formato nativo della tua lingua o come stringa delimitata da nuova riga se la nostra lingua non dispone di array. È garantito che ne contenga almeno uno 1.

Produzione

L'output deve essere un valore veritiero se l'insieme di 1s è un poliomino L-convesso e in caso contrario un valore falsy. Questi output devono essere coerenti: è necessario generare lo stesso valore di verità per tutti gli input L-convessi e lo stesso valore di falsa per gli altri. Si noti che un set disconnesso di 1s (che non è un poliomino) genera un output errato.

Regole e punteggio

È possibile scrivere un programma completo o una funzione. Vince il conteggio di byte più basso e non sono consentite scappatoie standard .

Casi test

Questi casi di test dovrebbero funzionare anche se si ruotano o si riflettono gli array o si aggiungono righe di 0s a qualsiasi bordo.

False instances
01
10

111
101
111

1101
1111
1110

1100
1000
0011

01100
11110
01110
00110

011000
011110
001111

True instances
1

01
11

010
111
010

001
011
111

11100
11110
01100
01000

011000
011000
111100
111111
001000

Sfida molto bella, mi sono divertito =)
flawr

Informazioni sull'input: è consentita una stringa delimitata da una nuova riga , se la nostra lingua non è priva di array ?
edc65,

@ edc65 (Siamo spiacenti, sono stato fuori dalla griglia per un paio di giorni.) Certo, anche questo è permesso, è solo mal scritto da parte mia.
Zgarb,

Risposte:


6

Lumache , 45 24

&
!{\1t\1!{o\1,nf\1,!.!~

Subito dopo aver pubblicato la mia soluzione iniziale, mi sono reso conto che c'era un modo molto migliore. Il programma originale percorreva il quadrato formato dai percorsi tra due 1s, verificando la presenza di uno 0 in ciascuna coppia di lati. Doveva anche avere un caso speciale per i percorsi in linea retta. La nuova versione inizia teletrasportandosi dall'una 1all'altra e testando l'assenza di un percorso rettilineo o a forma di 1L di ritorno all'inizio.


OH MIO DIO!! C'è un interprete online in cui possiamo giocare con questo?
Flawr

1
@flawr Puoi costruirlo dal sorgente con il codice sorgente qui .
Alex A.

6

Matlab, 182 byte

Idea: ripetere per ogni 1matrice poliomino:

  • Crea una nuova matrice con solo il dato 1ma il resto zero.
  • per ognuno 1in questa nuova matrice (ripetere fino a quando non cambia più nulla)
    • aggiungi 1come vicini in direzione x se ci sono 1come vicini nel polinomio
  • per ognuno 1in questa nuova matrice (ripetere fino a quando non cambia più nulla)
    • aggiungi 1come vicini in direzione x se ci sono 1come vicini nel polinomio

Ora 1nella nuova matrice dovrebbe coprire tutto 1nella matrice polinomio che sono raggiungibili dal punto di partenza dato andando prima nella direzione xe poi nella direzione y. Ora possiamo ripetere lo stesso processo ma andando prima nella direzione ye poi nella direzione x. Ora ogni 1matrice di poliomino dovrebbe essere raggiunta in una volta o in entrambe le volte. In caso contrario, abbiamo trovato una posizione nella matrice polinomio che non può essere raggiunta da ogni altra posizione tramite un Lpercorso.

golfed:

function r=f(a);[i,j,b]=find(a);N=nnz(i);r=1;for k=1:N;K=1:3;for l=1:2;c=b;b=a*0;b(i(k),j(k))=1;for z=1:2*N; b=conv2(b+0,K,'s')&a;if z==N;K=K';end;end;end;r=r*all(b(:)|c(:)>=a(:));end

Con commenti:

function r=codegolf_L_convex(a);
%a=[0,1;1,1];
[i,j,b]=find(a);%b just needs to be initialized, does not really mattter
N=nnz(i);%number of ones in the matrix
r=1;%return value
for k=1:N;%go throu all '1' in the matrix
    %expand that pixel in x dir:
    K=1:3;%convolution kernel (just three positive values needed)
    for l=1:2;%first horizontal->vertical then vertical->horizontal
        c=b;%backup for considering both runs
        b=a*0;
        b(i(k),j(k))=1; %set the seed
        for z=1:2*N;     
            b=conv2(b+0,K,'s')&a; %expand the seed horizontally (or vertically for the second half) but only within the polyomino
            if z==N;
                K=K'; %change horizontal/vertical 
            end;
        end;
    end;
    r=r*all(b(:)|c(:)>=a(:));%check whether we can really reach every point
end

Script per casi di test:

disp('all false -------------');
a=[0,1;1,0];
f(a)
a=[1,1,1;1,0,1;1,1,1];
f(a)
a=[1,1,0,1;1,1,1,1;1,1,1,0];
f(a)
a=[1,1,0,0;1,0,0,0;0,0,1,1];
f(a)
a=[0,1,1,0,0;1,1,1,1,0;0,1,1,1,0;0,0,1,1,0];
f(a)
a=[0,1,1,0,0,0;0,1,1,1,1,0;0,0,1,1,1,1];
f(a)
 disp('all true +++++++++++++');
a=[1];
f(a)
a=[0,1;1,1];
f(a)
a=[0,1,0;1,1,1;0,1,0];
f(a)
a=[0,0,1;0,1,1;1,1,1];
f(a)
a=[1,1,1,0,0;1,1,1,1,0;0,1,1,0,0;0,1,0,0,0];
f(a)
a=[0,1,1,0,0,0;0,1,1,0,0,0;1,1,1,1,0,0;1,1,1,1,1,1;0,0,1,0,0,0];
f(a)

2

Javascript ES6, 290 byte

Ok, forse non vincerà alcun premio per brevità, ma utilizza un approccio innovativo. Vedi la versione non golfata per come funziona.

Prova di questo metodo può essere trovata in: Automi cellulari e sistemi complessi discreti .

L=a=>[1,0,1].every($=>(a=a[0].map((_,col)=>a.map(row=>row[col]))).map(r=>($?r.reverse():r).join``).every((r,i,b)=>r.replace(/^(0*)(1*)(0*)$|(.+)/,(_,s,m,o,e)=>(c=e)?'':!m||b[i-1]&&+b[i-1][s.length]?1:b.every((r,j)=>j<i||(c=c||!+r[l=s.length])?r.search(`0{${l}}.*0{${o.length}}`)+1:1)||'')))

Ungolfed:

function L(a) {
  /* Runs three times and ensure all pass validation
   * 1: horizontally reversed
   * 2: 90 degrees rotated
   * 3: original
   *
   *     | 1:  | 2:  | 3:
   * =====================
   * 001 | 100 | 111 | 001
   * 011 | 110 | 011 | 011
   * 111 | 111 | 001 | 111
   *
   * By finding maximal rectangles with corners on all NW and NE corners
   * (separately) of a HV-convex polyomino and ensuring it doesn't enter the
   * boundaries labelled ABCD for the rectangle X below:
   *
   *   A  |         |  B
   * -----===========-----
   *      |    X    |
   * -----===========-----
   *   C  |         |  D
   *
   * The first iteration tests the NE corners and horizontal convexity.
   * The second iteration test vertical convexity.
   * The third iteration tests the NW corners.
   *
   * If all pass then the polyomino is L-convex.
   */
  return [1,0,1].every(function($){
    return (a=a[0].map((_,col)=>{
      // Transpose rows with columns
      return a.map(row=>row[col])
    })).map(row=>{
      // Join rows as strings and on odd iterations reverse them
      return ($ ? row.reverse() : row).join``
    }).every(function(row, i, b) {
      if (i == 0) console.log(b.join('\n'));
      return row.replace(/^(0*)(1*)(0*)$|(.+)/, function(_, start, middle, end, invalid) {
        // Non H-convex polyomino (0 between 1s)
        if (invalid) return '';
        // Is not a NW corner (character above is 1)
        if (!middle || b[i-1] && +b[i-1][start.length]) return 1;
        c=1;
        return b.every(function(row, j) {
          // Above or below maximal rectangle from corner
          if (j < i || !(c=c&&+row[l=start.length])) {
            // Area before and after maximal rectangle doesn't contain 1
            return row.search(`0{${l}}.*0{${end.length}}`)+1
          }
          return 1;
        }) || '';
      });
    });
  });
}

1
Ah, quell'articolo è dove ho preso l'ispirazione per questa sfida!
Zgarb,

@Zgarb L'articolo è stato fantastico e uno dei pochi che ho trovato sensato per qualcuno che non è orientato matematicamente.
George Reith,

2

Mathematica, 129 127 byte

3>GraphDiameter@Graph[#,#<->#2&@@@Select[#~Tuples~2,!FreeQ[#-#2&@@#,0]&]]&@Position[#,1]&&{#,Thread@#}~FreeQ~{___,1,0..,1,___}&

Spiegazione:

Innanzitutto, se sono presenti 0due 1s sulla stessa riga o colonna, l'array non è L-convesso, poiché non è possibile collegare i due 1s.

Dopo aver escluso questo caso, ogni due 1s sulla stessa riga o colonna possono essere collegati da un percorso rettilineo. Possiamo generare un grafico, i cui vertici sono le posizioni di 1s nella matrice e i bordi sono coppie di 1s sulla stessa riga o colonna. Quindi la matrice è L-convessa se e solo se il diametro del grafico è inferiore a 3.


1
Puoi dare una spiegazione su come funziona? Non ho intenzione di votare senza senso che nessuno possa capire =)
flawr

In che modo questo riconosce la prima e la quarta falsa istanza (quelle disconnesse)?
Zgarb,

1
@Zgarb Se il grafico è disconnesso, il suo diametro è infinito.
alephalpha,

2

JavaScript (ES6) 174

Osservando la griglia di celle vuote o riempite, per qualsiasi coppia di celle riempite controllo i percorsi orizzontali verso l'altra colonna di celle (può esserci 1 se le celle si trovano sulla stessa riga, altrimenti o 2) e i percorsi verticali verso altra riga di celle (possono esserci anche 1 o 2). Se trovo una cella vuota in entrambi i percorsi verticali o entrambi i percorsi orizzontali, allora non può esserci un percorso a forma di L tra le celle.

(Ho avuto difficoltà a provare a dare questa spiegazione - spero di essere stato chiaro)

Prova a eseguire lo snippet di seguito in qualsiasi browser compatibile con EcmaScript 6

F=p=>!p.some((n,y)=>n.some((q,x)=>q&&p.some((o,u)=>o.some((q,t)=>{for(f=0,i=y;q&i<=u;i++)f|=!p[i][x]|2*!p[i][t];if(f<3)for(f=0,j=x;q&j<=t;j++)f|=!n[j]|2*!o[j];return f>2}))))

// TEST
console.log=(...x)=>O.innerHTML+=x+'\n'

tko = [
 [[0,1],[1,0]]
,[[1,1,1],[1,0,1],[1,1,1]]
,[[1,1,0,1],[1,1,1,1],[1,1,1,0]]
,[[1,1,0,0],[1,0,0,0],[0,0,1,1]]
,[[0,1,1,0,0],[1,1,1,1,0],[0,1,1,1,0],[0,0,1,1,0]]
,[[0,1,1,0,0,0],[0,1,1,1,1,0],[0,0,1,1,1,1]]
]
tko.forEach(t=>(console.log(t.join`\n`+`\nFalse? ${F(t)}\n`)));
tok = [
 [[1]]
,[[0,1],[1,1]]
,[[0,1,0],[1,1,1],[0,1,0]]
,[[0,0,1],[0,1,1],[1,1,1]]
,[[1,1,1,0,0],[1,1,1,1,0],[0,1,1,0,0],[0,1,0,0,0]]
,[[0,1,1,0,0,0],[0,1,1,0,0,0],[1,1,1,1,0,0],[1,1,1,1,1,1],[0,0,1,0,0,0]]
]  
tok.forEach(t=>(console.log(t.join`\n`+`\nTrue? ${F(t)}\n`)));

// LESS GOLFED

U=p=>
  !p.some((n,y)=>  
    n.some((q,x)=> 
      q && p.some((o,u)=>  
        o.some((q,t)=>{
          for(f=0,i=y; q&i<=u; i++)f|=!p[i][x]|2*!p[i][t]
          if (f<3)
            for(f=0,j=x; q&j<=t; j++)f|=!n[j]|2*!o[j]
          return f>2
        })
      )
    )
  )
<pre id=O></pre>

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.