Fondo
Quiero comprar un terreno y construir mi casa en él. Mi casa debe ser rectangular y lo más grande posible; sin embargo, las parcelas disponibles tienen muchas áreas rocosas en las que no puedo construir, y tengo problemas para instalar una casa potencial en las parcelas. Quiero que escribas un programa que analice las tramas por mí.
Entrada y salida
Su entrada es una matriz rectangular 2D de bits, de un tamaño de al menos 1 × 1, en cualquier formato razonable. La matriz representa una parcela de tierra; 1
s son áreas "buenas" donde podría construir mi casa, y 0
s son áreas "rocosas" donde no se puede construir la casa.
Su salida será el área máxima de un rectángulo sólido de 1
s en la matriz de entrada. Representa el área de la casa más grande que podría construir en la parcela. Tenga en cuenta que si no hay 1
s en la entrada, entonces la salida es 0
.
Ejemplo
Considere la entrada
101
011
111
El rectángulo más grande de 1
s es el rectángulo 2 × 2 en la esquina inferior derecha. Esto significa que la salida correcta es 4
.
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
0
-> 0
1
-> 1
00
00
-> 0
01
10
-> 1
01
11
-> 2
111
010
111
-> 3
101
011
111
-> 4
0111
1110
1100
-> 4
1111111
1110111
1011101
-> 7
111011000
110111100
001111110
011111111
001111110
000111100
000011000
-> 20
000110000
110110010
110111110
110011100
010011111
111111111
111101110
-> 12
plow
.Respuestas:
Jalea ,
21201817 bytesPruébalo en línea! o verificar todos los casos de prueba .
Fondo
Sea M una matriz de bits como
Comenzamos contando el número de 1 bits en cada columna de M , restableciendo el recuento cada vez que encontramos un bit 0 .
Para nuestra matriz de ejemplo, esto da
A continuación, calculamos todas las sublistas contiguas de cada fila. Logramos esto generando todos los cortes de longitud k , donde k varía entre 1 y el número de entradas en cada fila.
Para la penúltima fila, esto da
A continuación, asignamos cada segmento al producto de su mínimo y su longitud. Para cada corte, esto calcula el área del rectángulo de 1 bits de altura máxima que tiene el corte dado como fila inferior.
Para los cortes de longitud 3 de la penúltima fila de nuestra matriz de ejemplo, esto da
Todo lo que queda por hacer es tomar el máximo en todos los segmentos de todas las filas.
Para nuestra matriz de ejemplo, esto da 12 .
Cómo funciona
fuente
MATL,
323127 bytesEsto utiliza un enfoque basado en convolución 2D de fuerza bruta. Todos los tamaños de rectángulo posibles se crean y se relacionan con el terreno. El resultado máximo de todas las convoluciones es el área del rectángulo máximo.
Esta es una solución extremadamente ineficiente porque para ahorrar bytes, creo núcleos para todos los rectángulos entre
[1, 1]
y en[numel(input) numel(input)]
lugar de determinar realmente el número de filas / columnas en la entrada para determinar los rangos de dimensión de rectángulo adecuados.Gracias a @Luis por sugerir el uso
M
y omitir el]]
.Pruébalo en línea!
Explicación
fuente
Julia,
83605753 bytesPruébalo en línea! El último caso de prueba excede el límite de tiempo de TIO, pero lo he verificado localmente.
Cómo funciona
Primero ! comprueba si su argumento de matriz M consiste completamente en 1 's.
Si es así ! devuelve la suma de las entradas de M , que es igual a su área.
Si no ,! hace lo siguiente:
Gire M en 0 ° , 90 ° , 180 ° y 270 ° en sentido horario.
Eliminar la primera fila de cada una de las cuatro rotaciones, eliminando de forma eficaz uno de la fila superior, fila inferior, columna de la izquierda y la columna más a la derecha de M .
Se llama recursivamente en cada una de las submatrices.
Devuelve el máximo de los valores de retorno de las llamadas recursivas.
fuente
JavaScript (ES6), 97 bytes
Resulta que el twiddling todavía gana. Acepta una matriz de matriz de enteros. Sin golf:
El conjunto se divide en filas según las otras respuestas, por lo que cada posible rango de filas se repite. Dado un rango de filas, el siguiente paso es medir los rectángulos disponibles. Esto se logra ANDing las filas juntas bit a bit; el resultado es una lista de bits que se establecieron en todo el rango de filas. Luego queda encontrar la longitud máxima de los bits establecidos en la fila y multiplicarla por la altura del rango. Prueba descaradamente robada de @ ed65:
fuente
Python 2.7,
9391898179 bytesLa entrada es una lista de tuplas. Verifique los casos de prueba más pequeños aquí y los casos de prueba más grandes aquí .
Sin memoria, los dos últimos casos de prueba exceden el límite de tiempo de Ideone, ya que requieren, respectivamente, 1,530,831,935 y 2,848,806,121 llamadas a f , lo que toma 39 y 72 minutos en mi máquina.
Algoritmo
Para una matriz M dada , la idea general es iterar sobre todas las submatrices de M eliminando las filas superiores y girando los cuartos de vuelta en sentido contrario a las agujas del reloj, haciendo un seguimiento de los tamaños de las submatrices encontradas que consisten completamente en 1 bit.
Jugar una implementación recursiva directa de la idea anterior conduce a una función f (M) que hace lo siguiente.
Si M no contiene ningún 0 bits, devuelve su número de 1 bits.
Si ya hemos rotado M dos veces y no contiene ningún 1 bit, devuelve 0 .
Si ya hemos rotado M cinco veces, devuelve 0 .
Llama recursivamente f a M sin su fila superior.
Recurrentemente, la llamada f en M gira un cuarto de vuelta en sentido antihorario.
Devuelve el máximo de los valores de retorno de las llamadas recursivas.
Código
En la implementación, usamos un argumento de función adicional t que por defecto es 1 para realizar un seguimiento de cuántas veces hemos rotado esta matriz en particular. Esto permite condensar los pasos 1 a 3 en un solo paso probando
`t/3`in`M`
y devolviendo`M`.count(`t`)
si la prueba falla.Si t = 1 , no hemos rotado esta submatriz particular en esta rama.
t / 3 = 0 , por
`t/3`in`M`
lo que devolverá True si la representación de cadena de M contiene el carácter 0 .Si no es así, volvemos
`M`.count(`t`)
, el número de veces que los caracteres 1 aparece en la representación de cadena H .Tenga en cuenta que una matriz sin 0 bits solo puede ocurrir si t = 1 , ya que no recurrimos en este caso.
Si 3 ≤ t ≤ 5 , hemos rotado previamente esta submatriz particular al menos dos veces en esta rama.
t / 3 = 1 , por
`t/3`in`M`
lo que devolverá True si la representación de cadena de M contiene el carácter 1 .Si no es así, volvemos 0 calculada como
`M`.count(`t`)
el número de veces que la representación de cadena de t (es decir, el carácter 3 , 4 o 5 ) aparece en la representación de cadena H .Si t = 6 , previamente hemos rotado esta submatriz particular cinco veces en esta rama.
t / 3 = 2 , por
`t/3`in`M`
lo que devolverá False , porque la representación de cadena de M no contiene el carácter 2 .Volvemos 0 calculada como
`M`.count(`t`)
, el número de veces que los caracteres 6 aparece en la representación de cadena H .Si f no regresó ya, se ejecutan los pasos restantes.
f(M[1:])
llama a f en M sin su fila superior. Como t no se especifica, el valor predeterminado es 1 , lo que indica que es la primera vez que f encuentra esta submatriz particular en esta rama.f(zip(*M)[::-1],t+1)
las llamadas f en M giraron un cuarto de vuelta en sentido antihorario, incrementando t para realizar un seguimiento del tiempo que hemos rotado esta submatriz particular en esta rama.El cuarto de vuelta se obtiene por comprimir las filas de M entre sí, volviendo tuplas de los elementos correspondientes de M filas 's, por lo que la transposición de M , a continuación, invirtiendo el orden de filas (es decir, la colocación de la fila superior en la parte inferior y viceversa )
Finalmente
max
devuelve el máximo de los valores de retorno de las llamadas recursivas.fuente
zip
devuelve una lista de tuplas de los elementos correspondientes de sus argumentos. Con una lista 2D desempaquetada (matriz)*M
, esencialmente transpone filas y columnas, por lo quezip(*M[::-1])
realiza una rotación de 90 ° en sentido horario.JavaScript (ES6),
154176Edit intentó acortar un poco, pero no puede competir contra la solución de @ Neil
Pruebe todos los rectángulos posibles, devuelva el tamaño máximo. Probablemente el mismo algoritmo de la respuesta de Matl, solo 6 veces más.
Ingresar como una matriz 2D de enteros
Menos golf
Este es el algoritmo original, la versión de golf abusa de muchas funciones de desplazamiento de matriz en lugar de bucles
Prueba
fuente
APL (Dyalog Extended) ,
272320 bytes-3 bytes por Adám y ngn
Pruébalo en línea!
fuente
{⌈/,(×/×1∊⍵⍷⍨⍴∘1)¨⍳⍴⍵}
es más corto y simple (ni siquiera requiere Extended).{⌈/∊(×/×⍵⍷⍨⍴∘1)¨⍳⍴⍵}
Brachylog ,
201715 bytesGracias a Kroppeb por 2 bytes.
Pruébalo en línea!
Explicación
fuente
aa
puede ser reemplazado por ¡s
Pruébelo en línea!R ,
129122 bytesPruébalo en línea!
Enfoque simple y simple de la fuerza bruta.
Código desenrollado y explicación:
fuente
Stax , 14 bytes
Ejecutar y depurarlo
fuente
Matlab 106 bytes
Sin golf:
La operación en el bucle comienza con la convolución 2D
conv2()
de la matriz de entrada con lap*m
matriz de unos.==p*m
comprueba si la matriz resultante contiene un elemento igual ap*m
. El elemento correspondiente se activa1
, todos los demás elementos se activan0
.any()
convierte la matriz en vector. Las columnas que contienen al menos una entrada distinta de cero se activan1
, de lo contrario0
.p*m*()
multiplica el vectorp*m
convirtiendo todo1
-s enp*m
.[__,r]
los corchetes concatenan el resultado obtenido con el área máxima anterior almacenada enr
. Finalmente,max()
encuentra el valor máximo en el vector resultante.fuente
any()
devuelve1
si la columna contiene un elemento distinto de cero y de lo0
contrario.Matlab
(222)(209)En realidad, esta solución me da vergüenza por tener el doble de tamaño que la solución real del mismo idioma, pero ... ¡caramba, había estado pensando en ella durante 6 horas! y el truco es una construcción ligeramente diferente de las respuestas de Dennis y Neil.
La función se llama como
Podría ahorrar más bytes si se introdujera la longitud de la matriz en las dimensiones de la función, a pesar de que hay más golf en curso.
¿Cómo procede esto?
Este algoritmo agrega la matriz real a sí misma desplazada hacia la izquierda, con un poco de giro (&). En cualquier etapa, la matriz resultante se establece como inicial y se agrega a sí misma desplazada hacia arriba repetidamente, luego se reubica desde el principio con la nueva matriz. Todos los subelementos de todas las matrices generadas por esta operación
(original_matrix+shifted_matrix)&shifted_and_original_matrices)
se maximizan a la salida.ejemplo:
fuente
Japt , 30 bytes
Pruebe todos los casos de prueba
Aproximadamente un puerto de Dennis's Jelly responde. Los casos de prueba son simplemente matrices 2D de números, convertidos del formato de la pregunta usando esto .
Explicación:
fuente
J , 38 bytes
Pruébalo en línea!
cómo
fuente