Reconocer una vid

31

Fondo

Tengo un montón de viejas y granuladas imágenes en blanco y negro. Algunos de ellos representan enredaderas trepando por una pared, otros no; su tarea es clasificarlos por mí.

Entrada y salida

Su entrada es una matriz rectangular 2D de bits A , dada en cualquier formato conveniente. No estará vacío, pero no se garantiza que contenga 0s y 1s. La matriz representa una vid si se cumplen las siguientes condiciones:

  • La fila inferior de A contiene al menos uno 1. Estas son las raíces de la vid.
  • Cada 1 en A está conectado a la fila inferior por una ruta de 1s que solo va a la izquierda, derecha y abajo (no arriba y no diagonalmente). Estos caminos son las ramas de la vid.

Su salida es un valor de verdad consistente si la entrada representa una viña, y un valor de falsedad consistente de lo contrario.

Ejemplos

Esta matriz representa una vid:

0 0 1 0 0 1
0 1 1 0 0 1
0 1 0 1 1 1
1 1 0 1 0 1
0 1 1 1 0 1
0 0 1 0 1 1

Esta entrada no representa una viña, ya que hay un 1 en el medio del borde derecho que no está conectado a las raíces por una rama:

0 0 0 1 1 0
0 1 0 1 1 1
0 1 0 1 0 1
0 1 1 1 1 0
0 0 1 1 0 1

La matriz all-0 nunca representa un vine, pero la matriz all-1 siempre lo hace.

Reglas y puntaje

Puede escribir un programa completo o una función. El conteo de bytes más bajo gana, y las lagunas estándar no se permiten.

Casos de prueba

Entradas de verdad:

1

0
1
1

01
11

0000
0111
1100
1001

1111
1111
1111
1111

001001
011001
010111
110101
011101
001011

1011011
1001001
1111111
0100000
0111111
1111001
1001111
1111101

0000000
0011100
0010100
0011100
0001000
1111111
0001000
0011100
0010100
0010100

Entradas de falsa:

0

1
0

10
01

000
000
000

011
110
000

111111
000000
101011
111001

010010
001000
000010
110001

001100
111111
110101
010011
111011

000110
010111
010101
011110
001101

11000000
10110001
10011111
11110001
01100011
00110110
01101100
01100001
01111111
Zgarb
fuente
1
No me di cuenta de que la vid no puede crecer hacia abajo, tuve una buena idea usando componentes conectados de un gráfico, suspiro ...
swish
@swish Todo lo que significa es que eliminar cada fila por turno debe continuar dando como resultado un gráfico conectado a una línea de 1s en la parte inferior.
Neil

Respuestas:

26

Caracoles , 25 19 17 bytes

&
\0z),(\1dlr)+d~

Pruébalo en línea!

Explicación

Snails es un lenguaje de coincidencia de patrones 2D inspirado en regex, que fue desarrollado originalmente para nuestro desafío de diseño de lenguaje de coincidencia de patrones 2D .

Esto &hace que Snails pruebe el patrón desde todas las posiciones de inicio posibles e imprime 0o 1dependiendo de si el patrón falla en alguno de ellos o coincide en todos ellos.

Ahora Snails puede trabajar con paréntesis implícitos, por lo que el patrón es la abreviatura de lo siguiente:

(\0z),(\1dlr)+d~

El ,actúa como una *en expresiones regulares (es decir, cero o más veces), mientras que el +es el mismo que en expresiones regulares (que coincida con una o más veces). Entonces, comenzamos haciendo coincidir las \0zveces que sea necesario, que coincide con un solo 0y luego permite que el caracol restablezca su dirección arbitrariamente z. Esto permite ceros en la entrada, siempre que se pueda encontrar una celda de vid válida en cualquier otro lugar.

Luego emparejamos al menos uno \1dlr, que coincide con uno solo 1y luego permite que el caracol restablezca su dirección hacia abajo, hacia la izquierda o hacia la derecha. Tenga en cuenta que si la celda en la que comenzamos contiene un, 1entonces solo estamos haciendo coincidir esta parte. Básicamente permite que el caracol atraviese una vid desde una rama hasta las raíces.

Finalmente, debemos asegurarnos de llegar al suelo buscando una celda fuera de los límites ( ~) debajo ( d).

Martin Ender
fuente
1
Estoy gratamente sorprendido de que alguien haya podido seguir la documentación :)
feersum
3

JavaScript (ES6), 135 bytes

s=>s.replace(/^[^1]*\n/,``).split`
`.map(s=>+`0b${s}`).reverse(g=(n,m,o=(m<<1|m|m>>1)&n)=>n-m?o-m&&g(n,o):n).reduce((m,n,i)=>g(n,n&m))

Nota: Debido a las limitaciones del tipo entero, solo funciona para vides de hasta 31 caracteres de ancho. Explicación: Cada fila se ANDA bit a bit con la fila adyacente para determinar los puntos de conexión, y luego la gfunción se usa para expandir recursivamente la fila horizontalmente hasta que ya no pueda expandirse. Por ejemplo, si dos filas adyacentes son 1110111y 1011100luego los puntos de conexión son 1010100y esto se expande 1110110y luego 1110111se encuentra que la fila está conectada. Si la gfunción falla, devuelve cero, lo que hace que todas las gfunciones posteriores también fallen, y el resultado es falso. Si la gfunción tiene éxito, devuelve la nueva fila que luego se propaga a través de reducepara probar la siguiente fila.

s=>s.replace(/^[^1]*\n/,``)         Remove irrelevant leading "blank" rows
    .split`\n`                      Split into lines
    .map(s=>+`0b${s}`)              Convert into binary
    .reverse(                       Process from bottom to top
     g=(n,m,o=(m<<1|m|m>>1)&n)=>     Expand row horizontally
      n-m?o-m&&g(n,o):n)             Check whether rows are connected
    .reduce((m,n,i)=>g(n,n&m))      Check all rows
Neil
fuente
Declararé que 31 caracteres son lo suficientemente amplios, y este enfoque es válido.
Zgarb
2

Python 2, 254 bytes

No hay bibliotecas

def f(A,r=0,c=-1):
 B=A[r];R=len(A)-1;C=len(B);i=1 in A[R]
 if c<0:
    for j in range(R*C+C):
        if A[j/C][j%C]:i&=f(A,j/C,j%C)
    return i&1
 _=B[c];B[c]=0;i=_&(r==R)
 if _:
    if c>0:i|=f(A,r,c-1)
    if r<R:i|=f(A,r+1,c)
    if c<C-1:i|=f(A,r,c+1)
 B[c]=_;return i

Tenga en cuenta que las sangrías de segundo y tercer nivel se forman con pestañas en el recuento de bytes.

Pruébalo en línea

Chuck Morris
fuente
1

Wolfram - 254

Dedique un tiempo a hacer que esto funcione, así que lo dejaré aquí:

f[s_]:=(
v=Characters@StringSplit@s;
{h,w}=Dimensions@v;
g=GridGraph@{w,h};
r=First/@Position[Flatten@v,"0"];
g=VertexDelete[Graph[VertexList@g,
EdgeList@g/.x_y_/;Abs[x-y]>1yx],r];
v=VertexList@g;
v≠{}∧v~Complement~VertexOutComponent[g,Select[v,#>w h-w&]]{}
)

Básicamente, construyo un gráfico de cuadrícula con los bordes dirigidos hacia arriba, elimino los vértices que corresponden a 0, compruebo que los componentes del vértice inferior contengan todos los vértices. Ridículo, lo sé ...

silbido
fuente
2
¿Por qué esto no es competitivo?
Downgoat
1
En la actualidad, consideraríamos que esto "no es una respuesta", ya que no se juega al golf. Si simplemente elimina espacios en blanco innecesarios y agrega un conteo de bytes, no veo ninguna razón por la cual esto no sea competitivo.
Alex A.
0

Python + NumPy 204 202 195 Bytes

from numpy import*
def f(A):
 r,c=A.shape
 z,s=zeros((r,1)),array([0,2,c+3])
 B=hstack((z,A,z)).flat
 for i in range(1,(r-1)*(c+2)):
    if B[i]and not any(B[s]):return 1<0
    s+=1
 return any(B[i:])

Espera Aser una matriz numpy 2D.

Toma la matriz, rellena cero columnas a izquierda y derecha y aplana la matriz. ses una plantilla que apunta al elemento izquierdo, derecho e inferior. El bucle verifica cada elemento, excepto la última línea, si es así, 1y al menos una de sus plantillas es 1, devuelve lo Falsecontrario. Luego, verifique si la última línea contiene alguna 1.

Dos casos de prueba para ti:

I1 = '001001\n011001\n010111\n110101\n011101\n001011'
A1 = array([int(c) for c in I1.replace('\n','')]).reshape(6,6)
print f(A1) #True

I2 = '001100\n111111\n110101\n010011\n111011'
A2 = array([int(c) for c in I2.replace('\n','')]).reshape(5,6)
print f(A2) #False

Edit1: 1<0es más corto queFalse

Edit2: flates una buena alternativa flatten()y uso de tabuladores para la segunda intención en el bucle

Karl Napf
fuente