Es el sprint final ... y la mitad de tu equipo está enfermo. Estás trabajando hasta tarde, solo haces tu último compromiso para el día, esperando ... ¿por qué se han apagado las luces? No recuerdo al tipo de seguridad que viene ... ¡oh no! ¡Dejé mis llaves en casa!
A medida que se hunde el horror de la situación, decides que vas a escapar .
Resumen de tareas
Para lograr tu escape, ¡necesitas un plan! Sin embargo, usted sabe que cualquier plan tiene la posibilidad de fallar, y diferentes planes requieren diferentes cantidades de esfuerzo.
Al estar hambriento, cansado e ingeniero, decide escribir un programa corto para determinar la mejor manera de escapar del complejo, equilibrando las preocupaciones sobre la probabilidad de éxito y el esfuerzo que requerirá.
Haces un mapa del edificio:
#######################
# = #
! = ! <-- window
# ! = # (freedom!)
#################= #
# # = #
# # = #
# # = #
# o ! # # ! = #
##| ! ## # ! = #
#######################
^ ^ ^
me my door ludicrously high shelves
(locked) (climbable)
Para escapar de la oficina, tendrás que alejarte del mapa. Aquí puede ver que hay 2 ventanas ( !
), cualquiera de las dos lo llevaría a la libertad, pero solo una de ellas es accesible. Definimos 'fuera del mapa' como tener los pies fuera de los límites del mapa.
Tipos de células
- empty, you can be here (i.e. the escapee can consume this cell)
# - solid (your desk, your in-tray), you can't be here, but you can stand on it
! - destructible, (co-worker's desk, door, window), you can't be here until you smash it first (turning it into an empty cell)
= - climbable, (fire ladder, filing cabinet, etc.), you can be here
Las células originalmente consumidas por el fugitivo se consideran vacías.
Especificaciones de acción
Tiene varias acciones posibles a su disposición. Estos se definen por transiciones de estado simples con alguna probabilidad de éxito de enteros. Por ejemplo, para caminar, mueves una celda del fugitivo, que representamos con esta transición:
Paso
1 stp, 100%, espejo
o. o
|. --> |
# #
Los puntos muestran celdas que deben estar vacías (o escalables, pero no sólidas o destructibles) ya sea porque nos movemos hacia él o a través de él. El 100% significa que tienes un 100% de posibilidades de no lastimarte y terminar tu atrevida fuga. Todas las probabilidades serán porcentajes enteros entre 1% y 100% inclusive. El primer diagrama muestra el estado inicial (parado sobre algo sólido, parado al lado de algún espacio vacío). El segundo diagrama muestra el estado terminal (movido al espacio vacío). No hay requisitos para que ninguna celda no especificada (espacios ) a la izquierda (estado inicial) sea algo en particular. Celdas no especificadas (espacio,
) a la derecha (estado terminal) debe ser el mismo que antes (p. ej., lo que estaba detrás del fugitivo, o lo que sea que esté caminando (ya sea un espacio vacío o de otra manera). Tenga en cuenta que todo está a la derecha (estado terminal ) los diagramas solo cambiarán las celdas de destructibles a vacías, no pueden ocurrir otros cambios. "1 stp" significa que cuesta 1 stp: definimos "stp" como la cantidad de energía requerida para dar un paso.
"espejo" significa que esta acción tiene dos formas. Se muestra la acción "derecha", la acción "izquierda" es un espejo exacto, por ejemplo:
.o
.|
#
es la forma espejo (izquierda) de
o.
|.
#
La acción derecha se llama "Derecha" (por ejemplo, "Paso a la derecha") La acción izquierda se llama "Izquierda" (por ejemplo, "Paso a la izquierda")
En estos diagramas, el fugitivo se muestra por
o
|
cuando está de pie (2 unidades de altura) y
%
al agacharse (1 unidad de altura). Las células que deben ser sólidos o destructible se indican mediante un hash, #
. Las celdas que no deben ser sólidas o destructibles se indican con un punto .
. Las celdas que deben ser destructibles se indican mediante una explosión !
. Un espacio vacío recién creado se muestra con un guión bajo _
.
x
es un punto de referencia que no se mueve (no existe, sin restricciones sobre lo que debe ser esa celda (como un espacio )).
Nota: ignoramos el problema de la desaceleración rápida cuando tocas el piso, y sí, en este juego puedes hacer saltos totalmente épicos en las escaleras)
Paso
1 stp, 100%, espejo
o. o
|. --> |
x# x#
Bajar
1 stp, 100%, espejo
= =
o. --> o
|. |
x= x=
Barajar
3 stp, 100%, espejo
%. %
x# --> x#
Subir
10 stp, 95%, espejo
o. %
|# --> #
x# x#
soltar
0 stp, 100%
o
| --> o
x. x|
Soltar
0 stp, 100%
% o
x. --> x|
Subir
2 stp, 100%
= o
o --> |
x| x
Agacharse
2 stp, 100%
o
| --> %
x# x#
Estar
4 stp, 100%
. o
% --> |
x# x#
Salto corto
4 stp, 95%, espejo
o.. o
|.. --> |
x# x#
Salto largo
7 stp, 75%, espejo
o... o
|... --> |
x# x#
Salto alto
12 stp, 90%, espejo
.. o
o. --> |
|
x# x#
¡Dale la espalda!
20 stp, 80%, espejo
o!. _o
|!. --> _|
x# x#
Puñetazo
8 stp, 90%, espejo
o! o_
| --> |
x# x#
Patada
8 stp, 85%, espejo
o o
|! --> |_
x# x#
Sello
8 stp, 90%
o o
| --> |
x! x_
Planes
Un plan es una secuencia de las acciones definidas anteriormente. Por ejemplo:
Step Left
High Jump Left
Crouch
Shuffle Left
Shuffle Left
Stand
Long Jump Left
Put your back into it! Left
Step Left
Tenga en cuenta la inclusión de las gotas. Las reglas deben establecerse para que dejes de hacer cualquier cosa que no sea caer, ¡pero aún tienes que planearlo!
Cualquier plan tiene un esfuerzo requerido, que es la suma de los esfuerzos para cada paso. También hay una probabilidad de éxito, que es el producto de las probabilidades de éxito de cada acción. Ejemplo simple:
Step Right: 1stp, 100%
Long Jump Right: 7stp, 75%
Step Right: 1stp, 100%
Stamp: 8stp, 90%
Drop: 0stp, 100%
Drop: 0stp, 100%
Drop: 0stp, 100%
Drop: 0stp, 100%
Step Left: 1stp, 100%
Step Left: 1stp, 100%
High Jump Left: 12stp, 90%
Effort = 1+7+1+8+1+1+12 = 31
Success Probability = 75%*90*90% = 60.75%
Un 'ejemplo trabajado' para el mapa en la parte superior de la página se puede encontrar como una idea general .
Entrada
La entrada viene en dos partes, un número entero y una matriz o cadena de caracteres.
El entero es su probabilidad mínima aceptable (porcentaje) de éxito. Debe interpretarse como un porcentaje, por lo que 80 significa que su plan debe tener éxito con una probabilidad no inferior al 80%.
Un mapa válido es un rectángulo que incluye el fugitivo de pie (tamaño mínimo de 1x2) y sin símbolos no especificados. Todas las filas serán de la misma longitud. Puede aceptar la entrada como una cadena delimitada unidimensional (el delimitador debe ser un solo carácter consistente, o uno de par CRLF y LFCR), como una matriz unidimensional similar o una matriz bidimensional. Si el formato de entrada elegido no indica el ancho o la altura del mapa de alguna manera, puede aceptar argumentos adicionales para estos (debe indicarlo claramente en su respuesta). Puede mezclar argumentos de línea de comando y entrada estándar si le conviene (por ejemplo, mapa de stdin, probabilidad mínima de éxito de argv). Los siguientes son ejemplos de mapas válidos e inválidos.
Válido:
o
|
Válido:
# #
! o #
! | #
#########
Inválido (sin fugitivo):
# #
! #
! #
#########
Inválido (el fugitivo siempre comienza a pararse):
# #
! #
! % #
#########
Inválido (símbolo inválido):
# #
! ~ #
! #
#########
Inválido (no un rectángulo / filas de diferente longitud):
# #
! o #
! | #
#########
Puede suponer que su entrada es válida (no me importa lo que haga su programa si recibe una entrada no válida).
Salida
La salida es texto (ASCII). Puede devolverse como una cadena o imprimirse en salida estándar. El plan debe estar delimitado por un LF, CRLF o LFCR. Del mismo modo, debe haber otro LF, CRLF o LFCR después del esfuerzo requerido. Un salto de línea final es opcional.
Debe generar un plan óptimo junto con el esfuerzo que requiere, o "¡No hay esperanza!" si no existe tal plan. No necesita generar la probabilidad de éxito. Este texto puede tener o no un salto de línea final.
Un plan óptimo se define como un plan (ver arriba) que requiere el mínimo esfuerzo con al menos la probabilidad de éxito dada. Tenga en cuenta que sus cálculos de probabilidad deben ser exactos, no puede suponer que el punto flotante es lo suficientemente bueno (es por eso que no espero que los genere). Intentaré diseñar casos de prueba para probar esto de manera justa (si los aprueba y no hace suposiciones tontas, entonces puede considerar que su envío es válido).
Formato:
Required Effort: <effort>
<plan>
Por ejemplo, para la entrada
50
# #
! o #
! | #
#########
Un resultado apropiado sería:
Required Effort: 23
Step Left
Step Left
Step Left
Kick Left
Punch Left
Step Left
Step Left
Step Left
Step Left
La probabilidad de éxito aquí es 76.5%.
Para el mismo mapa, pero con una probabilidad mínima de éxito del 80%, debería "poner su espalda en él", lo que requeriría más esfuerzo pero cumpliría los criterios de probabilidad de éxito. Si la probabilidad mínima de éxito fuera mayor al 80%, necesitaría pensar un poco más (golpear o patear una parte de la puerta y arrastrarse). Si la probabilidad mínima de éxito fuera del 100%, tendría que imprimir "¡No hay esperanza!"
Ejemplos
Es posible que haya más de un plan válido para una entrada, su salida no necesita ser exactamente, pero debe tener el esfuerzo requerido correcto y ser un plan válido. Puede usar el verificador para verificar sus soluciones (ver más abajo)
Entrada:
100
o
|
Salida:
Required Effort: 0
Drop
Entrada:
5
# = #
# = !
# = ! ! !
# =#######
# = #
# = o #
# = ! | #
##########
Salida:
Required Effort: 57
Step Left
Kick Left
Step Left
Step Left
Step Left
Climb Up
Climb Up
Climb Up
Climb Up
Climb off Right
High Jump Right
Long Jump Right
Step Right
Drop
Kick Right
Crouch
Shuffle Right
Shuffle Right
Entrada:
60
#########
# ! # #
! ! ! o #
! # ! | #
#########
Salida:
Required Effort: 58
Step Left
Kick Left
Crouch
Shuffle Left
Shuffle Left
Stand
Punch Left
Clamber Up Left
Shuffle Left
Drop (Stand)
Kick Left
Crouch
Shuffle Left
Shuffle Left
Para el mismo mapa, pero 80%, la salida debería ser:
There is no hope!
Para el mismo mapa, pero 50%, el esfuerzo requerido se convierte en 56 con un plan diferente)
Entrada:
50
#######################
# # = #
! # = !
# # = #
###### #####!## =### #
#= ## # = #
#=############# = #
#= = #
#= o = #
#!!| = #
#######################
Salida:
Required Effort: 121
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Climb Up
Climb Up
Climb Up
Climb Up
Climb Up
Climb Up
Climb off Right
Long Jump Left
Step Left
Step Left
Stamp
Drop
Drop
Crouch
Shuffle Left
Shuffle Left
Shuffle Left
Shuffle Left
Shuffle Left
Shuffle Left
Stand
Clamber Up Left
Stand
Clamber Up Left
Stand
Step Left
Step Left
Step Left
Step Left
Punch Left
Clamber Up Left
Shuffle Left
Entrada:
66
######
# ###
#o ! !
#| ! !
### ##
######
Salida:
Required Effort: 37
Step Right
Put your back into it! Right
Kick Right
Crouch
Shuffle Right
Shuffle Right
Entrada:
Este está diseñado para verificar una serie de suposiciones falsas de las que uno puede ser víctima y, en consecuencia, puede parecer un poco extraño
30
###################
# ## # # # # = #
! ## # # # = #
# # # = #
## ############= #
# ## # #= #
# = # #= #
! = # #= #
# = # #= #
#o= ! ==#
#|= ! =#
#!= # ==########==#
# # ! !! =#
# # !! ! = #
# # !!!!#########
# # # #
# # # #
###################
Salida con posibilidad de éxito restricción 30:
Required Effort: 199
Long Jump Right
Put your back into it! Right
<snip>
Salida con posibilidad de éxito restricción 32:
Required Effort: 200
Long Jump Right
Punch Right
<snip>
Usando el mapa en la parte superior como entrada, con una probabilidad de restricción de éxito del 1%, debe obtener un esfuerzo requerido de 116 (posibilidad de éxito ~ 32%, esto tardó unos 20 segundos en ejecutarse en mi programa de prueba).
Criterios de victoria
Este es el código de golf, que gane el código más corto.
Para ser elegible, su función o programa debe funcionar y poder resolver cada uno de los casos de prueba anteriores en menos de 30 minutos en una máquina razonable. Mi solucionador los hace cada uno en menos de 30 segundos. Si la secuencia de comandos de prueba (a continuación) se ejecuta en menos de 30 minutos, seguramente está listo para comenzar.
Ejemplo de Solver, Verifier, Test Script y TestCases (con soluciones)
El código C # para un solucionador y un verificador de solución está disponible aquí como una idea general . La esencia también contiene file.txt
, que es una forma legible por máquina (suficiente) de las acciones descritas anteriormente, y es necesaria para que el programa se ejecute. Cualquier discrepancia entre ese archivo y la especificación no es intencional.
La esencia también contiene una serie de casos de prueba (incluidos todos los ejemplos anteriores) y un script de PowerShell para ejecutar automáticamente un envío contra ellos. Si el script le dice que una prueba en particular ha fallado, puede ejecutarla OfficeEscapeSolver.exe testcase<n>.txt outputFromYourProgram.txt
para ver más detalles. Ejemplos de soluciones para estos casos de prueba están en otro Gist .
Todo el código es un completo desastre (aunque no está protegido), pero no debería tener que alejarse mucho static void Main(...)
para cambiar la cantidad de salida (no dude en usar esta información, ¡la he proporcionado para su beneficio!).
Pasar un caso de prueba no significa necesariamente que su salida esté bien formada, ya que el script y el verificador son muy generosos. Su salida debe coincidir con la especificación anterior para que su envío sea válido.
Si crees que has encontrado un error con el solucionador o el script de prueba, un error file.txt
o un caso de prueba dudoso, por favor comenta en esta publicación o envíame un mensaje en el Chat SE; Probablemente no notaré ningún otro intento de comunicarme.
No proporcionaré el script de prueba en Bash o Batch, porque no los conozco, pero estoy feliz de incluir una traducción y escribiré una versión de C # si la gente quiere una.
Post Amble
¿Tienes preguntas? ¡No se demore, pregúnteles hoy!
Esta tarea está destinada a requerir esfuerzo , para dar a los golfistas serios algo en lo que hundir sus dientes.
Mi agradecimiento a ais523 por sus comentarios sobre Entrada / Salida.
Puedo proporcionar más casos de prueba en el archivo GIS si la gente quiere más (no quiere que esta publicación se vuelva más larga), o si desea proporcionar algunos de los suyos.
fuente
Respuestas:
Perl 5,
142514641481146914851438 bytes¡Ese fue un desafío divertido! Y, sorprendentemente, ¡parece que tengo el código más corto hasta ahora en un poco menos de 1.5kB! :)
Estoy bastante seguro de que finalmente funcionó. El delimitador utilizado es
:
, y hay relleno adicional de dos filas en la parte superior y una columna a cada lado. Entonces, para su aporte de:mi programa tomaría: (Nota: debe haber dos puntos al final, ¡pero no al principio!)
Utilizo expresiones regulares para traducir de un mapa a otro y resolver por fuerza bruta. Sin embargo, no agrego mapas a la lista si ese mapa ya se ha alcanzado con menos esfuerzo y mayor o igual probabilidad. Los mapas se eliminan de la lista una vez que todos los movimientos posibles desde ese punto se han agotado. El programa finaliza con éxito cuando coincide con una expresión regular que muestra que he llegado al costado o al final y termina con "¡No hay esperanza!" cuando la lista de mapas está agotada.
Desafortunadamente, hubo una gran cantidad de eficiencia intercambiada para quitar algunos bytes, por lo que la versión de golf es bastante lenta;) Perl parece encontrar que las evaluaciones en particular son bastante dolorosas.
Sin más preámbulos,
En aras de la cordura, esto es lo mismo con las nuevas líneas y algunos comentarios:
Ya puedo ver un par de lugares para eliminar algunos bytes más, pero todavía no quiero volver a hacer todas las pruebas. ¡Más tarde! :)
Editar: se agregó un poco de relleno a continuación para que se ajuste más exactamente a su salida al escapar por el piso. Se eliminaron algunas de las evaluaciones, por lo que el código también podría ejecutarse más rápido ahora.
Editar: No estaba manejando escaleras y caídas del todo bien. Todavía no maneja las escaleras del todo bien ... Tratando de arreglar eso ahora.
fuente
C #,
181414811395 bytes¡Qué tarea! ¡Estoy realmente bastante satisfecho con esto ahora!
Pruébalo en línea
Programa completo, toma entrada a STDIN, salida a STDOUT. Esencialmente, una reescritura de mi solucionador original, utilizando un BFS simple e ineficientemente implementado para encontrar la ruta óptima. Es razonablemente rápido, no puede ser mucho más lento que mi otra implementación (aunque realmente no lo he cronometrado), ciertamente se ejecuta dentro del límite de tiempo. Gran parte del costo es la tabla de acciones, que está codificada como valores separados por comas que registran el nombre, el mapa 'match / smash' y otras propiedades de cada acción disponible.
Comienza leyendo en la probabilidad mínima de éxito y el mapa. Luego localiza al fugitivo, lo elimina del mapa y crea un "estado de búsqueda" que contiene esta información. Luego, realiza el BFS, que observa repetidamente el siguiente estado debido con el menor esfuerzo (asegurando que encuentre una solución óptima). Antes de expandir el nodo, compara su esfuerzo y probabilidad de éxito con los nodos anteriores con el mismo mapa y ubicación de escape, y se rechaza si ya se ha encontrado una mejor ruta a este estado. Si sobrevive a esto, se agrega a la tabla 'visto' para que pueda rechazar el estado más adelante. Todo esto es por rendimiento, y sin él el factor de ramificación sería enorme. Luego verifica si el fugitivo está fuera del mapa. Si es así, ¡entonces gana! Realiza un seguimiento del estado (cada estado anterior se registra con cada estado) y construye el plan (a la inversa) antes de salir del bucle BFS. De lo contrario, intenta aplicar todas las acciones y agrega las que se pueden aplicar a
due
cola, antes de ordenar esta cola para que obtengamos el estado de menor esfuerzo en la próxima iteración.Código formateado y comentado:
fuente