Este es el primero de una serie de desafíos de Island Golf. Siguiente reto
Dada una isla en el arte ASCII, genera una ruta óptima para circunnavegarla.
Entrada
Su entrada será una cuadrícula rectangular que consta de dos caracteres, que representan tierra y agua. En los ejemplos a continuación, la tierra es #
y el agua es .
, pero puede sustituir cualquiera de los dos caracteres distintos que desee.
...........
...##......
..#####....
..#######..
.#########.
...#######.
...#####.#.
....####...
...........
Siempre habrá al menos una ficha de tierra. Todas las fichas de tierra serán contiguas (es decir, solo hay una isla). Las baldosas de agua también serán contiguas (es decir, no hay lagos). El borde exterior de la cuadrícula será de baldosas de agua. Las fichas de tierra no se conectarán en diagonal: es decir, nunca verás algo como
....
.#..
..#.
....
Salida
Su código debe generar la misma cuadrícula, con una circunnavegación más corta dibujada en ella. En los ejemplos a continuación, se dibuja la ruta de circunnavegación o
, pero puede sustituir cualquier personaje siempre que sea distinto de sus caracteres de tierra y agua.
Una circunnavegación es una curva cerrada simple, dibujada completamente en baldosas de agua, que rodea completamente todas las baldosas terrestres en la cuadrícula. Se permiten conexiones diagonales . Por ejemplo, esta es una circunnavegación de la isla anterior (pero no la más corta):
.ooooo.....
o..##.oo...
o.#####.o..
o.#######o.
o#########o
ooo#######o
..o#####.#o
..oo####..o
....oooooo.
La longitud de una circunnavegación se calcula de la siguiente manera: por cada par de mosaicos adyacentes en el camino, si están conectados horizontal o verticalmente, agregue 1; si están conectados en diagonal, agregue √2. La longitud de la ruta anterior es 22 + 7√2 (≈ 31.9).
Una circunnavegación más corta es una circunnavegación con la menor longitud posible. Su programa debe generar cualquier ruta que satisfaga esta condición. Para la mayoría de las islas, habrá múltiples soluciones posibles. Aquí hay una solución para la isla anterior, con longitud 10 + 13√2 (≈ 28.4):
...oo......
..o##oo....
.o#####oo..
.o#######o.
o#########o
.o.#######o
..o#####.#o
...o####.o.
....ooooo..
Detalles
Su solución puede ser un programa completo o una función . Cualquiera de los métodos de entrada y salida predeterminados son aceptables.
Su entrada y salida puede ser una cadena multilínea o una lista de cadenas. Si su idioma tiene un tipo de caracteres distinto de las cadenas de un solo carácter, puede sustituir "lista de caracteres" por "cadena" en la oración anterior. Si su idioma necesita ingresar el alto y / o ancho de la cuadrícula, puede hacerlo. Su salida puede (opcionalmente) tener una nueva línea final. Como se mencionó anteriormente, puede usar tres caracteres distintos en lugar de #.o
(especifique en su envío qué caracteres está usando).
Casos de prueba
A. Islas con circunnavegaciones más cortas y únicas:
...
.#.
...
.o.
o#o
.o.
......
.####.
......
.oooo.
o####o
.oooo.
......
......
..##..
...#..
......
......
......
..oo..
.o##o.
..o#o.
...o..
......
.......
.#####.
...#...
...#...
.#####.
.......
.ooooo.
o#####o
o..#..o
o..#..o
o#####o
.ooooo.
.......
...#...
...#...
.#####.
...#...
...#...
.......
...o...
..o#o..
.o.#.o.
o#####o
.o.#.o.
..o#o..
...o...
.......
.#####.
.##..#.
..#..#.
.......
.ooooo.
o#####o
o##..#o
.o#..#o
..oooo.
B. Ejemplo de una isla con múltiples soluciones posibles:
........
....##..
...####.
..###...
.#####..
.#####..
..##....
........
Salidas posibles:
....oo..
...o##o.
..o####o
.o###.o.
o#####o.
o#####o.
.o##oo..
..oo....
....oo..
...o##o.
..o####o
.o###.o.
o#####o.
o#####o.
.o##.o..
..ooo...
....oo..
...o##o.
..o####o
.o###..o
o#####.o
o#####o.
.o##oo..
..oo....
....oo..
...o##o.
..o####o
.o###..o
o#####.o
o#####o.
.o##.o..
..ooo...
C. Gran caso de prueba como Gist
Este es el código de golf : gana el código más corto en cada idioma.
Respuestas:
Mathematica (versión 9), 165 bytes
La
ConvexHullMesh
función corta y agradable que usó Greg Martin solo se introdujo en la versión 10 de Mathematica, así que pensé en intentarlo sin ella, usando mi antigua versión 9. de Mathematica. Es una función que toma y devuelve una lista de cadenas (con.
,#
yo
que los símbolos).Explicación:
Characters@# /. {"."->0, "#"->1}
convierte la entrada en una matriz de0
sy1
s."o"MorphologicalTransform[MorphologicalComponents[#,Method->"ConvexHull"],Max[#(1-#[[2,2]])CrossMatrix@1]&]+"#"#
luego usa las poderosas capacidades de procesamiento de imágenes de Mathematica (pero extremadamente pesadas en bytes ...) para llenar primero el casco convexo de la isla (que es la forma que obtendría si estirara un trozo de cuerda a su alrededor), y luego tome su límite. Luego multiplicamos esta matriz por la cadena"o"
para obtener una matriz de0
sys"o"
(gracias a la impresionante adaptabilidad de Mathematica sobre los tipos), y agregamos esto a"#"
veces la matriz de la isla.""<>#& /@ (... /. {0->"."})
convierte esta matriz de"o"
s,"#"
sy0
s en una matriz de"o"
s,"#"
sy"."
s, y une cada fila en una cadena.Cuando probamos esto en el ejemplo B , obtenemos la salida
[Editar, gracias a Greg Martin:] Si se nos permite usar matrices de caracteres en lugar de listas de cadenas, podemos reducir esto a 144 bytes:
fuente
MorphologicalComponents[#, Method->"ConvexHull"]
:) Puede guardar aún más bytes suponiendo que la entrada ya está dividida en caracteres y devolviendo también una matriz 2D de caracteres.MorphologicalComponents
hasta hoy!f[{"...",".#.","..."}]
y obtuve algunos errores.f
. (Bueno, estrictamente hablando, son las cosas después del punto y coma.) Para llamar a la función, escriba todo en una ventana de Mathematica, seguido de[
su entrada y]
, por lo tanto, debería verse algo así comof@m_:=m(1-m[[2,2]]) . . . #/.{"."->0,"#"->1}]&[{"...", ".#.", "..."}]
(abreviado por espacio).(Pero vota la solución de Notatree , ¡es mejor!)
Mathematica, 168 bytes
Función pura que toma una matriz 2D de caracteres como entrada y devuelve una matriz 2D de caracteres. Una versión más fácil de leer:
La línea 1 define una función
n
que produce la distancia (más pequeña) entre un puntox
en el plano y un conjuntoy
de otros puntos. La línea 2 inicializa la variablei
a la entrada, tanto para resolver una ambigüedad curry más tarde como para poder modificarla para producir la salida final; La línea 2 también define una funciónp
que devuelve las coordenadas de todas las ocurrencias de su entradai
.En la línea 3,
p["#" | "."]
representa cada coordenada del mapa de entrada (ya que todos sus caracteres son"#"
o"."
), por lo quet
es una función que selecciona solo aquellas coordenadas que satisfacen una propiedad aún no especificada. En la línea 4,i~Part~## = "o"
va a cambiar un montón de entradas deli
personaje"o"
; esos caracteres se seleccionarán del conjunto de coordenadas posibles de acuerdo con las cosas en las líneas 5-8. Y la línea 9 solo devuelve la respuesta una vez que se calcula.Bien, infraestructura hecha, ahora a la computación real.
ConvexHullMesh
es la función integrada de Mathematica para calcular el casco convexo de un conjunto de puntos (el polígono convexo más pequeño que contiene esos puntos). Hablando moralmente, esto debería "completar" las calas y los fiordos de la isla (que ess = p@"#"
), para descartarlos de nuestra navegación en bicicleta. Hay un pequeño problema conConvexHullMesh
cuando ese conjunto de puntos está todo en una línea (gracias, caso de prueba # 2), que resolvemos agregando una versión ligeramente desplazada des
sí mismo en la línea 7. Esta salida es un polígono, por lo que las líneas 7 -9 (t[...~RegionMember~# &]
) produce una lista de los puntos con coordenadas enteras en ese polígono. Finalmente, la línea 5 y el final de la línea 9 calculan todos los puntos que están a una distancia exactamente 1 (por lo tanto, no 0) de este conjunto de puntos enteros; ese conjunto se convierte en el camino de circunnavegación.A continuación se muestra la salida para el caso de prueba grande en el enlace del OP. Observe en la esquina superior izquierda, las elecciones inusuales de cuándo ir al oeste versus suroeste insinúan el hecho de que está sombreando una línea invisible de pendiente -2/3 entre dos penínsulas (dicho segmento de línea es parte del límite del casco convexo).
fuente
char
tipo separado ; en ese caso, sechar
podría usar una matriz en lugar de una cadena.Python 3, 779 bytes (sangría con pestañas)
Este es todo el programa. Lee la entrada de stdin y la imprime en stdout. Stdin debe terminar con EOF. Ejemplo ejecutado con la entrada grande: https://ideone.com/XIfYY0
La idea es simple: calcula los límites octogonales más pequeños y dibuja celdas que están dentro de todos los límites calculados e intersectan al menos uno de los bordes.
fuente
sys.stdin
como entrada.input()
, Conseguir de varias líneas haría el trabajo y cuestan menos bytesR(0,x)
porR(x)
P
yf
;L(generator expression)
=>[generator expression]
;F
,r
YB
parecen ser utilizados una sola vez cada uno y por lo tanto puede ser inline.JavaScript (ES6),
369343bytesExplicación: La cadena se divide en una matriz de caracteres (no estoy claro si la entrada de la matriz de caracteres es aceptable). La matriz se repite y se ubican las posiciones de todos los cuadrados de tierra. Las líneas que limitan dadas por las ecuaciones
x - y = o
,x = p
,x + y = q
,y = r
,y - x = t
,-x = u
,-x - y = v
,-y = w
se determinan de tal manera que el parámetro máximo posible se elige donde todas mentiras la tierra más allá de la línea. Esto tiene el efecto de encerrar la isla en un octágono. Las coordenadas de las esquinas del octágono se calculan fácilmente a partir de los parámetros y las celdas en su borde se rellenan. La matriz se vuelve a unir en una cadena. La razón por la que es suficiente un octágono es la siguiente:Considere una esquina del octágono. En algún punto a lo largo de los dos bordes, el camino estará limitado por la tierra porque construimos el octágono para tocar la tierra lo más cerca posible. Si no hay tierra en la esquina, el camino podría tomar las rutas alternativas como se muestra a la derecha, pero sigue siendo el mismo número de pasos ortogonales y diagonales, por lo que la distancia no cambia.
fuente
rest of arguments
parámetro....p
en diferentes lugares). La desestructuración es otra cosa (aunque el operador de propagación se puede usar en la desestructuración).Python 3.5,
224, 263, 234218 bytesAprovechó otros 16 bytes eliminando la función anidada y convirtiéndola en una sola línea.
Golfed de 29 bytes:
La entrada es una sola cadena que usa '~' para el océano, 'X' para la tierra y 'o' para el límite. (El uso de 'X' guarda un byte para '>' en lugar de '==')
Versión menos golfista con comentarios:
fuente
C # 7 -
414369327 bytesEditar : cambió a 1D looping, informática
i
yj
sobre la marchaEditar : cambió el método de entrada, contrajo la tabla de búsqueda y cambió a límites iniciales bien definidos ... y eliminó el espacio sin sentido en el último for-loop externo
Pruébalo en línea
Programa completo, toma la entrada en el estándar, lo imprime a cabo estándar, usos
#
,.
yo
. Para cada celda, calcula un 'perfil' (que es la distancia sobre 8 direcciones (parece calcular una novena por conveniencia, pero esto es siempre0
), y registra un máximo de cada una de ellas. Luego escribe todo el mapa nuevamente, y reemplaza cualquier celda que esté en un límite y no fuera de ninguna con una 'o'. El código comentado a continuación explica cómo funciona todo.Según mi respuesta a Save the Geese from Extinction , esto produce el octágono más pequeño (circunnavegación válida con el área más grande) que limita la isla.
Nota : que por una vez en mi vida estoy usando algo de la década actual, y este código requiere C # 7 para compilar. Si no tiene C # 7, hay una línea que deberá reemplazarse, que está claramente marcada en el código.
Ejemplo de uso y salida:
Código formateado y comentado:
fuente