Eres un viajero que cruza el desierto entre dos pueblos. No puede llevar suficiente agua para cruzar sin detenerse. Esta es una variación de un rompecabezas clásico.
Las normas
Un desierto se ve así: una cuadrícula WxH de espacio mayormente vacío. El espacio marcado S
es donde comienzas, E
es donde quieres terminar, y un cuadrado marcado con el número N contiene N unidades de agua. Cuadrados marcados con una .
bodega cero agua.
.....................................
........S............................
.....................................
.........7...........................
.....................................
.......................3.............
.....5...............................
................................2....
.....................................
.....................................
.....................................
...............................E.....
.....................................
....................7................
.....................................
.....................................
Comienzas en S con 5 unidades de agua.
Puede transportar como máximo 5 unidades de agua.
Cada turno tu
- mover un cuadrado hacia arriba, abajo, izquierda o derecha,
- consume 1 unidad de agua que llevas,
- recoger o dejar caer una cierta cantidad de unidades de agua.
A su vez, está anotada así: (direction)(+|-)(units of water)
, +
indica que se está recogiendo el agua, -
que está dejarlo caer.
Ejemplo de turnos:
D+0 Move Down
R+0 Move Right
D+2 Move Down, pick up two units of water.
U-1 Move Up, drop one unit of water.
Si realiza estos movimientos comenzando en S en el ejemplo anterior, el desierto se ve así después.
.....................................
........S............................
.........1...........................
.........5...........................
.....................................
.......................3.............
.....5...............................
................................2....
.....................................
.....................................
.....................................
...............................E.....
.....................................
....................7................
.....................................
.....................................
No puedes recoger más agua de la que ya está en tu plaza. Cuando recojas el agua, deduce esa cantidad de unidades del recuento de fichas.
Solo puede recoger agua para contener un máximo de 5 unidades.
Ningún mosaico puede contener más de 9 unidades, excepto S que contiene unidades de infinito.
Solo puedes soltar tanta agua como la que tienes actualmente.
El agua en el suelo permanece sin cambios hasta que la recojas nuevamente.
Si regresa a S, puede recoger cualquier cantidad de agua sin agotarla.
Si llegas a E, entonces ganas . Aún ganas si consumes tu última unidad de agua en E.
Si, después de tu turno, tienes cero agua y no estás en E, mueres .
Entrada y salida
Su programa recibirá un mapa inicial de tamaño arbitrario STDIN
como arte ASCII en el formato anterior. Puede suponer que es rectangular, es decir, todas las líneas tienen la misma longitud, que hay exactamente uno S
y un E
cuadrado, todas las líneas están terminadas \n
y todo el STDIN se ajustará a esta expresión regular:/^[SE1-9\.\n]+$/
Su programa escribirá la siguiente salida en STDOUT:
- la lista de movimientos,
- El estado final del mapa.
Puede generar la lista de movimientos en cualquier formato conveniente.
El estado final del mapa se imprimirá en el mismo formato que la entrada, excepto que además mostrará la ruta que tomó por el desierto marcando todas las fichas visitadas #
, si esa ficha no contiene agua y no es S o E (es decir, es .
)
Ejemplo de entrada:
.....S.
.......
.......
E......
....8..
EJEMPLO resultado ganador:
D+0
D+0
D+0
D+0
L+5
L+0
L+0
L+0
L+0
U+0
.....S.
.....#.
.....#.
E....#.
####3#.
No trivialidad
Cuando publique su código, publique una entrada de mapa de muestra para la cual su código encuentre una solución que satisfaga las siguientes condiciones de no trivialidad:
- S y E están separados por al menos 10 movimientos.
- Cualquier cuadrado que inicialmente contenga N unidades de agua debe estar rodeado por un borde de ancho N en el que todos los cuadrados estén
.
(sin agua, ni S ni E)
EJEMPLO
........2.
..........
..........
S.1..2....
..........
..........
........1.
..3.......
.........E
Si aumenta la cantidad de agua en cualquier azulejo, lo anterior se vuelve trivial.
Requisitos
Presumiblemente, su programa encontrará varios intentos fallidos antes de encontrar una solución, si la hay.
- Su programa eventualmente debe resolver cualquier entrada solucionable.
- Quiero verte morir : tu programa generará los movimientos y el mapa final de la ruta a la muerte para cada intento fallido de encontrar una solución.
- Si encuentra una solución ganadora, imprima la salida completa para eso y finalice.
- Ejecute hasta que se encuentre una solución, pero no intente la misma solución dos veces : todas las muertes deben ser por rutas distintas.
- Use esto como entrada de prueba:
(requiere al menos un movimiento para dejar caer un caché de agua en algún punto medio).
S........
.........
.........
........E
El código más corto que se publica con una entrada de demostración no trivial que resuelve gana.
Respuestas:
Perl,
299 + 1 =300254 + 1 = 255 bytesEsto seguramente será superado por uno de los idiomas de golf cuando la gente vea mi algoritmo :-)
Corre con
-n
(penalización de 1 byte).La versión anterior no cumplía con la especificación porque dejaba agua extra en el mapa y no la mostraba en la versión final del mapa; Mientras cambiaba el algoritmo para lidiar con esa situación, logré jugar golf un poco más pequeño en el proceso.
Ejemplo (he agregado saltos de línea a la salida para evitar la necesidad de desplazarse y mostrar la estructura):
En la notación utilizada por el programa, el movimiento se representa por medio de
L
,R
,U
, yD
para la izquierda, arriba, derecha, abajo, respectivamente. Por defecto, recoges 1 unidad de agua después de cada movimiento, pero esto se puede modificar agregando un personaje:X
: suelta 2 unidades de agua, en lugar de recoger 1Y
: suelta 1 unidad de agua, en lugar de recoger 1(es decir, espacio): rellene completamente con agua (solo sale después de un movimiento
S
; el programa también sale con un espacio inicial, lo que tiene sentido porque comienza lleno en el agua)Como puede ver, es posible cruzar este mapa (más bien estéril) sin usar grupos adicionales. De hecho, es posible obtener cualquier distancia bajo estas reglas, en cualquier mapa, sin la ayuda de agua previamente reemplazada. Como tal, este algoritmo simplemente ignora cualquier agua previamente reemplazada, lo que significa que no tengo que desperdiciar bytes tratando de manejarlo. Esto también significa que no vas a ver morir al bot, lo siento. Nunca se mueve más allá del rango en el que sabe que está garantizado para sobrevivir.
La razón por la que necesitamos ambos
X
yY
(y un poco de código adicional para asegurarnos de tener laX
mayor parte de la estrategia, pero de vezY
en cuando al final) es que la especificación requiere que se publique la versión final del mapa. La forma más fácil de implementar esto es dejar el mapa completamente intacto (aparte de nuestro camino a través de cuadrados inicialmente vacíos), especialmente porque un cuadrado que comenzó con9
agua terminaría con10
(rompiendo el arte ASCII) si estuviera en el camino y solo usamosX
y, por lo tanto, necesitamos encontrar alguna solución que evite dejar caer agua adicional en el mapa. El algoritmo aquí "naturalmente" arrojaría 1 unidad adicional de agua en cada cuadrado de la ruta; Como tal, el penúltimo tiempo que visitamos cada cuadrado, reducimos la cantidad de agua que cae en 1 mediante el uso de Y en lugar de X, por lo que en nuestra visita final, drenamos el cuadrado a su cantidad original de agua, en lugar de dejándolo un poco más húmedo que cuando empezamos.Recomiendo no ejecutar esto en un mapa grande, porque tiene un rendimiento O (2 ^ n) (aunque el bot nunca muere de sed, es posible pensar que moriría de hambre usando una estrategia como esta).
Versión legible:
fuente