Desafío
Dada una entrada gráfica de una forma, determine cuántos agujeros hay en ella.
No duplicado
Esta pregunta fue marcada como un posible duplicado de Count Islands . Creo que este desafío es diferente del desafío Count Island porque en este, tienes que descubrir cómo eliminar los bloques que tocan el borde.
Entrada
La entrada se dará como una forma de entrada en 2D, ya sea una cadena multilínea, una matriz de cadenas o una matriz de matrices de caracteres. Esto representa la forma. Se garantiza que la forma sea de una sola pieza, conectada por el borde. Especifique cómo desea que se tome la entrada.
Salida
La salida es un entero entero que indica cuántos agujeros hay en la forma. Se permite una nueva línea final, pero no otros espacios en blanco iniciales o finales. En otras palabras, la salida debe coincidir con la expresión regular ^\d+\n?$
.
¿Qué es un hoyo?
Estos son agujeros individuales:
####
# #
# #
####
####
# #
# ##
###
#####
# # #
# #
#####
Estos no son agujeros:
########
########
# ####
# ####
# ######
#
########
###
#
###
##########
#
# ########
# # #
# # #### #
# # ## #
# ###### #
# #
##########
Más o menos, si la brecha se une al borde exterior, no es un agujero.
Casos de prueba
#####
# # # -> 2
#####
#####
#
# ### -> 1
# # #
#####
####
## # -> 1 (things are connected by edges)
# ##
####
###
### -> 0 (You must handle shapes with no holes, but input will always contain at least one filled space)
###
Puede usar cualquier carácter en lugar del '#' y en lugar de los espacios.
Criterios de puntuación objetiva
La puntuación se da como el número de bytes en su programa.
Victorioso
El ganador será la presentación con el puntaje más bajo, antes del 4 de abril.
###|# #|##
como un caso de prueba? Eso debería ser0
, ¿verdad?Respuestas:
MATLAB / Octave, 18 bytes
Pruébalo en línea!
Esta es una función anónima que toma una matriz lógica como entrada. El objeto está formado por las
true
entradas (con la conectividad especificada), el espacio vacío son lasfalse
entradas.bweuler
luego calcula el número de Euler de la imagen binaria representada por esa matriz, es decir, el número de objetos menos el número de agujeros.fuente
Mathematica,
5957 bytesHay un incorporado para eso. Toma entrada como una matriz 2D de
1
s (paredes)0
ys (agujeros). Por conveniencia, aquí están todos los casos de prueba en este formato de entrada:Solución alternativa, 59 bytes.
Este fue mi enfoque original. También se basa en los elementos integrados relacionados con los componentes, pero no cuenta los agujeros directamente (en su lugar, trata los agujeros en sí mismos como componentes).
Toma el mismo formato de entrada que el anterior, pero con los papeles de
0
s y1
s intercambiado.La razón por la que necesito convertir esto en un
Image
primero es que, de lo contrario, Mathematica consideraría todas las1
células como parte de un solo componente (porque trata la matriz como una matriz de etiqueta de componente). Por lo tanto, si alguna1
celda bordea el margen, los eliminaría a todos. EnDeleteBorderComponents
cambio, cuando se usa en una imagen, realizará una comprobación de conectividad implícita para encontrar los componentes.Alternativamente, podría llamar
MorphologicalComponents
primero , lo que convertiría la entrada en una matriz de etiquetas adecuada, pero si lo hago enDeleteBorderComponents
segundo lugar, ya no está garantizado que la etiqueta máxima del componente corresponda al número de componentes (porque podría eliminar un componente más pequeño).fuente
GenerateBuiltin
. Genera una función incorporada para cualquier desafío que no tenga una función incorporada. Además, me siento mal por la bandeja de entrada de Martin Ender, así que si quieres, continuemos esta discusión aquíPerl 5 , 154 bytes
152 bytes de código + 2 bytes para el
-p0
indicador.Pruébalo en línea!
Creo que el código se explica por sí mismo.
Si necesita algunas explicaciones para comprender, aquí hay algunos pasos de las transformaciones realizadas por el programa en una entrada simple (proveniente de aquí ), seguidas de algunas explicaciones a continuación:
Primero,
s/^ | $/A/gm;s/^.*\K | (?=.*$)/A/&&redo
reemplazará los espacios en el borde (primera expresión regular para izquierda / derecha, segunda para abajo / arriba) conA
(elijo ese carácter bastante arbitrario).Luego, obtenemos el ancho de la forma
/.*/;$@="@+"-1;
.Ahora, queremos reemplazar cada espacio que está conectado a a
A
con unA
(porque si un espacio está conectado a aA
, significa que no puede ser parte de un agujero. Eso se hace porfor$%(A,X){(s/$%(.?.?.{$@})? /$%$1$%/s||s/ (.?.?.{$@})?$%/$%$1$%/s)&&redo}
. (Notará que esto se hace) una vez para laA
s y otra para laX
s - las explicaciones para la siguienteX
son.) Hay dos expresiones regulares aquí:s/$%(.?.?.{$@})? /$%$1$%/s
trata con los espacios que están a la derecha o al final de A.A
Ys/ (.?.?.{$@})?$%/$%$1$%/s
con los espacios en la parte superior o izquierda de aA
.En este punto, los únicos espacios que quedan en la cadena son parte de los agujeros.
Si bien todavía hay espacios, repetimos:
- Para saber cuántos agujeros hay, reemplazamos un espacio con a
X
(s/ /X/
) e incrementamos el contador de agujeros ($\++
), y rehace todo el programa (en realidad, solo queremos rehacer elfor
ciclo , pero son menos bytes rehacer todo el programa).- Luego, el
for
bucle reemplazará cada espacio que esté conectado a aX
con aX
, ya que son parte del mismo agujero.Al final,
$\|=0
asegura que si no hay agujeros,0
se imprime a en lugar de una cadena vacía. Y$\
se imprime implícitamente gracias a la-p
bandera.fuente
Python 2, 282 bytes
+100 para manejar toques diagonales TT_TT (¿realmente necesitamos eso?)
-119 gracias a la guía de @Rod :)
Pruébalo en línea . Toma una matriz de matrices de caracteres '#' y espacios en blanco como entrada.
Busca el primer espacio en blanco y lo marca como no vacío ('#'). Verifique recursivamente todo su entorno, mientras llena todas las celdas vacías. Si alguna celda vacía del "agujero" actual parece estar en el contador de bordes no cambiará, de lo contrario se incrementaría en 1. Repita el proceso, hasta que no haya más espacios en blanco.
fuente
sum(A,[])
para aplanarNone
s, pero eso es irrelevante)x=T[0];y=T[1]
->x,y=T
, (probablemente) no necesita declararg=1
en la tercera línea, y puede usar<
o>
comparar cadenas (tomará elord()
valor de cada carácter) lo que le permite reemplazarA[y][x]!='#'
conA[y][x]<'#'
, desde entonces' '<'#'
.Python 2,
233225222 bytesmatemática_junkie : -8 bytes
Toma una matriz 2D de booleanos / enteros (0/1) como entrada
Pruébalo en línea!
Versión formateada:
fuente
print sum(m(x,y)...
lugar dea=
yprint a
C # 7, 364 bytes
Menos que contento con esto ... tal vez alguien más pueda resolverlo ... Si tengo la energía más tarde, invertiré el primer bucle y veré si eso puede ayudar a recortar los límites.
Pruébalo en línea
Programa completo, acepta entrada a entrada estándar, salida a salida estándar. Utiliza conjuntos disjuntos para determinar los agujeros provisionales, y cuando mata, toca los bordes (con cierta dificultad para el borde superior).
Código formateado y comentado:
fuente
Func<List<string>, int>
para eliminar la pelusa y las cosas de la consola. Sin embargo, he visto que tiene funciones locales, por lo que es posible que no pueda tenerlas en una función. Podría simplemente compilar a un métodoint h(string[] s) { }
.Caracoles , 48 bytes
Sin golf:
fuente
JavaScript (ES6), 192 bytes
Basado en mi respuesta a Detect Failing Castles . Primero, la cuerda se rellena con espacios para hacer un área alrededor de la forma. Luego, RegExp busca dos cuadrados adyacentes, uno que contenga un
@
, otro que contenga un espacio, y los reemplaza a ambos con un@
. Si no puede hacer esto, llena un espacio con un@
y cuenta esto como un nuevo agujero. Finalmente se resta uno para tener en cuenta el área circundante.fuente