Encuentra el resultado de un juego de guerra
Cuando estaba en la escuela primaria, había un juego al estilo "Piedra-Papel-Tijera" que jugábamos durante las asambleas, cuando esperábamos a nuestro maestro, en el recreo, etc. Lo llamamos "Guerra". Sin embargo, después de buscar un poco, resulta que esta es una variante mucho más simple del "Juego de escopeta" (según WikiHow) . Voy a llamarlo "Guerra" ya que las reglas son ligeramente diferentes:
2 personas se sientan una frente a la otra. El objetivo del juego es "matar" al otro jugador. Cada turno, puedes jugar uno de 3 movimientos:
Recargar : tienes una pistola que tiene un solo disparo. Debe recargarse antes de poder dispararse cada vez. Recargar cuando ya tienes munición es legal, pero no hace nada. Una recarga se simbolizó tocando las sienes con ambas manos. Cada jugador comienza con 0 municiones.
Guardia : el único movimiento seguro. Si te disparan mientras vigilas, no mueres. La protección se simboliza cruzando los brazos sobre el pecho.
Fuego : dispara tu arma. Para disparar con éxito, debe haber recargado desde el último disparo. Si tu oponente está recargando, tú ganas. Si también disparan, y ambos tienen munición, es un empate. Si están vigilando, desperdiciaste la munición. Si bien disparar sin munición es un movimiento legal, no hace nada y te deja vulnerable como recargar. Disparar se simboliza señalando al otro jugador.
Se jugó de manera similar a RPS, ya que cada jugador lanza simultáneamente su elección (golpeamos nuestras piernas dos veces entre turnos para mantener el ritmo entre ellos, pero eso no es importante para el desafío).
El reto:
Tu tarea es encontrar el resultado de un juego de guerra. Puede ser una función o un programa completo.
Entrada
La opción que cada jugador eligió en cada turno estará representada por un personaje / cadena:
r : recargar
g : guardia
f : fuego
La entrada será una lista de pares, una cadena delimitada / no delimitada, o cualquier otra cosa a lo largo de estas líneas.
Un ejemplo de entrada en Python podría ser [("r", "g"), ("f", "r")]
, es decir, en el primer turno, el primer jugador volvió a cargar y el segundo jugador guardó. En el segundo turno, el primer jugador dispara, mientras que el segundo jugador se recarga. El jugador uno gana este juego. La misma entrada opcionalmente podría ser representado como "r g f r"
, "rgfr"
, "rg fr"
"rg-fr"
...
Puede asumir lo siguiente:
La entrada coincidirá con el formato elegido y solo contendrá caracteres válidos.
Alguien morirá en 100 turnos.
Sin embargo, no puede suponer que los turnos terminan cuando alguien muere.
Salida
Un valor que indica quién ganó (o quién ganó primero *
). Puede elegir qué generar para cada escenario, pero debe tener en cuenta lo siguiente:
El jugador 1 gana
El jugador 2 gana
Se matan unos a otros (dibujar)
Cada resultado debe tener un valor de distrito y siempre debe ser el mismo para cada escenario.
Como ejemplo: podría salir 1
cuando el jugador 1 gana, 2
cuando el jugador 2 gana y 0
en caso de empate. Luego, siempre debe salir 1
cuando el jugador 1 gana, 2
cuando el jugador 2 gana y 0
en caso de empate.
Se puede devolver o imprimir en la salida estándar. El espacio en blanco al final está bien.
Para que quede claro, el único escenario que conduce a un empate es si ambos jugadores disparan y ambos tienen munición.
*
Dado que en este desafío, los turnos pueden continuar después de que alguien muere, es posible que más de 1 jugador gane eventualmente. Debes encontrar quién ganó primero según la entrada.
Casos de prueba (suponiendo 1
que P1 gana, 2
cuando P2 gana y 0
para un empate):
"rg fr" => 1 (P1 shot P2 while they were reloading)
"rg ff" => 1 (They both shot, but only P1 had ammo)
"rr ff" => 0 (Both had ammo and shot each other)
"rr ff rr fg" => 0 (Both had ammo and shot each other. Everything after the first win is ignored)
"rr fg rf" => 2 (P2 shot P1 while they were reloading)
"rf gg rr fg rr fr" => 1
(P2 tried to shoot but didn't have any ammo, then they both guarded, then they both reloaded, then P2 blocked a shot, then they both reloaded again [but P2 still only has 1 ammo!], then P1 shoots P2 while they're reloading.
"rr gf fr rf gg rg ff" => 1
^ Player 1 wins here. The rest to the right has no effect on the output
Este es el código de golf, por lo que gana el menor número de bytes.
Tenga en cuenta que, como muestran los casos de prueba, debe manejar movimientos "tontos". Es perfectamente válido para un jugador intentar disparar cuando no tiene munición, o recargar 2 turnos seguidos (y solo acumular una sola munición).
{"rff","rgf"}
?Respuestas:
Retina , 36 bytes
El formato de entrada debe ser pares separados por salto de línea, p. Ej.
La salida es si el
!_
jugador 1 gana,_!
si el jugador 2 gana y!!
si hay un empate.Pruébalo en línea!(Un conjunto de pruebas que utiliza la separación del espacio por conveniencia).
Debo haber pasado por alto completamente este desafío. Estoy seguro de que habría intentado esto en Retina antes de lo contrario. :)
Explicación
Comenzamos marcando disparos "válidos" convirtiendo el primero
f
después de cada unor
en!
. Hacemos esto haciendo coincidir cada unof
de los cuales puede encontrar unr
en el mismo jugador sin cruzar sobre otrof
. Limitar la búsqueda ar
s en el mismo jugador es fácil al ir siempre con tres caracteres a la vez.Ahora descartamos todos los turnos en los que alguien se protegió, porque el turno final no puede ser uno de esos.
Ahora mantenemos solo el primer turno que contiene un
!
. Si ocurre un tiro válido (y sabemos que nadie guardó) el juego termina.Finalmente, necesitamos consolidar la cadena para obtener resultados consistentes, y simplemente hacemos esto convirtiendo los no
!
caracteres (ya sear
of
) en_
.fuente
Python, 139 bytes
Toma entrada en stdin en forma de una lista de cadenas de 2 caracteres (por ejemplo, ['rf', 'rr', 'rg', 'ff']). Salidas 1 si el jugador 1 gana, -1 si gana el jugador 2 y 0 para un empate.
Explicación: Primero verifica si alguien disparó una bala, si es así, el juego termina. Luego determinamos si los jugadores han recargado sus armas o malgastado su munición.
Esta es mi primera publicación de codegolf :)
fuente
JavaScript (ES6),
10810793918985 bytesGuardado 4 bytes con la ayuda de Titus
Toma información como una serie de cadenas de 2 caracteres que describen los movimientos jugados por cada jugador.
Devoluciones:
1
si el jugador 1 gana2
si el jugador 2 gana3
para un empateCómo funciona
Mantenemos una máscara de bits
b
que describe quién tiene una viñeta cargada:Usamos la secuencia De Bruijn
'ffrfgrrggf'
para identificar las 9 combinaciones posibles de movimientos. Utilizamos máscaras de bits OR y AND para actualizar deb
acuerdo con la combinación de movimientos. Usamos un tercer conjunto de máscaras de bits con las que se AND 'b
para determinar el ganadorw
. (Las únicas tres combinaciones ganadoras sonff
,fr
yrf
.)Vale la pena señalar que las máscaras OR y AND se pueden almacenar con el mismo patrón, desplazado por dos posiciones.
Casos de prueba
Mostrar fragmento de código
fuente
0
(a nadie le dispararon) o3
(los jugadores se matan entre sí) en caso de empate. No estoy seguro si esto está permitido. Si no, puedo regresarw%3
en su lugar.&
máscara puede ser 0 parafr,rf,ff
.'312'['0210231'[m='ffrfgrrggf'.search(c)]|'233331'[m-3]&b]
o'123'['2100231'[m='frffgrrggf'.search(c)]|'233331'[m-3]&b]
guardar un byte; pero funcionan?["rr","fg","fr","rf"]
&
tiene mayor precedencia que|
, por lo que cambiar el orden no debería cambiar nada allí (aparte de guardar el byte). Pero la asignación faltaba en mi código. Tratar...'123'[b='2100231'...
.Perl 6 ,
7162 bytesSolución basada en expresiones regulares.
Toma la entrada como una cadena en el formulario
"rg fr"
.Las tres salidas posibles son los valores de enumeración
More
(1 reproductor de won),Less
(2 reproductor de won),Same
(Draw) - que se convierten en esas palabras cuando se imprime, o dentro de1
,-1
,0
cuando coaccionado a los números.Pruébalo en línea!
Cómo funciona
Realiza dos coincidencias de expresiones regulares en la entrada. Después de la interpolación, las dos expresiones regulares son:
r[..[r|g]]*.[r|f]f
- Coincide con el primer disparo exitoso del jugador 2.r[..[r|g]]*..f[r|f]
- Coincide con el primer disparo exitoso del jugador 1.En cada caso, devuelve la posición final del partido (
.to
), o infinito si no hubo coincidencia.Aplica al
<=>
operador a las dos posiciones finales del partido. Devuelve un valor de laOrder
enumeración (More
,Less
oSame
), dependiendo de si el primer argumento es mayor, menor o igual que el segundo.fuente
some number
? ¿Y realmente usa caracteres como ese en el código Perl común, o es solo para jugar al golf?[Menu] i n f
(se llama una secuencia de composición ). Sin embargo, todos los símbolos Perl 6 tienen versiones ASCII, por ejemplo,Inf
y∞
son sinónimos, por lo que no es necesario usar símbolos Unicode en el código Perl 6. Simplemente me gusta ... :)Haskell ,
101 9187 bytesPruébalo en línea! La función infijo
#
toma dos cadenas que representan las acciones de cada uno de los dos jugadores y regresa(0,1)
si el jugador 1 gana,(1,0)
para el jugador 2 y(0,0)
para un empate.Ejemplo de uso:
Explicación:
La función infijo
!
traduce una secuencia de acciones'r'
(recargar),'f'
(fuego) y'g'
(guardia) a una secuencia de acciones observables0
(fuego real),1
(sin acción) y2
(guardia), donde una acción de fuego solo se cuenta como acción de fuego real si se carga una viñeta, y de lo contrario no se realiza ninguna acción . Para lograr esto, el primer argumenton
es0
si una bala está cargada y1
si la pistola no está cargada. De esta manera, cada uno'f'
simplemente puede ser reemplazado por el actualn
. (n=0
-> cargado -> fuego real ->0
,n=1
-> descargado -> sin acción ->1
)Las nueve posibilidades resultantes son entonces
(0,0)
: Ambos jugadores disparan y mueren, el juego termina.(0,1)
o(1,0)
: Un jugador dispara al otro, el juego termina.(0,2)
o(2,0)
: Un jugador dispara pero los otros guardias, el juego continúa.(1,1)
,(1,2)
,(2,1)
O(2,2)
: Ningún jugador golpea, el juego continúa.Por diseño, la suma de las opciones de finalización del juego es menor que 2 y la suma de cada posibilidad de continuación del juego es mayor o igual a 2. El resultado del juego es entonces la primera tupla con una suma menor que 2.
fuente
Lote, 249 bytes
La entrada es en forma de pares de caracteres para cada turno y sale por nivel de error (0 = empate, 1 = jugador 1, 2 = jugador 2).
x
yy
hacer un seguimiento de si el jugador tiene munición, de modo que cuando ambos disparan, el resultado es3-x-x-y
, a menos que sea 3, en cuyo caso seguimos adelante. En la línea 5 abusé del analizador de Batch -%1
(que es el movimiento actual) se sustituye antes de que lashift
declaración se ejecute y la elimine, por lo que aún vamos a la etiqueta correcta.fuente
Clojure, 168 bytes
Menos golf (si ambas personas están vivas usamos
M
para actualizar su munición y el estado de vida del enemigo, de lo contrario devolveremos el estado actual):Ejemplo de uso (el primer elemento indica si el jugador 1 está vivo al final del juego, el segundo elemento indica si el jugador 2 está vivo, el tercero y el cuarto indican el estado de la munición que no es relevante al determinar el ganador):
Actualización: ¡Mira eso,
loop
tiene una longitud idéntica! Creo que lareduce
versión es más fácil de desarrollar, ya que puede inspeccionar fácilmente los estados intermedios si la usareductions
.fuente
[l1 l2 r1 r2]
(sus valores modificados enlet
y sus valores originales) y esasfn
firmas.loop
. Me parece que conduce a un código más ordenado. Tan pronto como necesito doblar con más de 1 acumulador, cambio.PHP,
10710190 bytesusando una máscara de bits $ d para el estado de carga y una secuencia DeBruijn para los movimientos de disparo.
toma la entrada como argumentos de línea de comando de 2 caracteres, ejecuta con
-nr
.Descompostura
fr
:: posición = 1 = incendios P1;rf
= posición 2 = incendios P2,ff
= posición 3 = ambos disparang<$m
<=>f<$m[0]
(f<$m
siempre es cierto, porque hay un segundo carácter).fuente
Python, 200 bytes
fuente
turns
lugar de solot
, lo que significa que el programa es mucho más grande de lo necesario. Además, comience su envío con algo como#Python 2, 200 bytes
(suponiendo que esto sea 2, y el programa tiene una longitud de 200 bytes) para que el lenguaje que esté usando sea claro.Clojure,
180173 bytes-7 bytes cambiando la función a una función completa en lugar de usar una macro. Eso me permitió hacer las macros de funciones internas, lo que ahorra un poco.
Esta es una solución muy literal. Estoy un poco alucinado ya que acabo de escribir una versión completa del juego, y esta es básicamente una versión muy reducida del algoritmo que utilicé. Probablemente hay muchas optimizaciones que podría hacer, pero estoy bastante feliz con eso. Consulte el código pregolfed para obtener una explicación.
fuente