Alice y Bob se pelean

24
  • Alice (A) y Bob (B) decidieron tener una batalla.
  • Cada combatiente tiene 10 de salud.
  • Se turnan para tirar un dado de 6 lados por daños.
  • Ese daño se elimina de la salud de su oponente.
  • Al final, ya sea Alice o Bob, vencerán a su enemigo.

Muéstrame cómo fue la batalla. Salida de estos códigos para las acciones que han tenido lugar.

Ataque

B a A    
^ Combatant
  ^ Action (attack)
    ^ Target

Rodar

B r 4
^ Combatant
  ^ Action (roll)
    ^ Value

Cambio de salud

A h 6
^ Combatant
  ^ Attribute (health)
    ^ Value   

Ganar

A w 
^ Combatant
  ^ Action (win)

Salida de ejemplo:

A a B
A r 4
B h 6
B a A
B r 6
A h 4
A a B
A r 6
B h 0        
A w

Estas son las reglas:

  • Escribe en cualquier idioma.
  • Una sola tirada del dado debe tener la misma probabilidad de resultar en cualquiera de los números 1, 2, 3, 4, 5 o 6.
  • Alice siempre comienza (Bob es caballeroso, a la antigua).
  • Produce una acción para cada turno.
  • Debes informar el ataque, tirar, dañar y ganar acciones.
  • Los combatientes son mayúsculas, las acciones son minúsculas.
  • No debe producir constantemente el mismo resultado.
  • Debe haber al menos un carácter de espacio en blanco entre un combatiente de salida, acción y valor.
  • La acción ganadora tiene lugar cuando el oponente tiene cero o menos salud.
  • Todas las partes de una acción deben estar en la misma línea.
  • Debe haber una acción por línea.
  • Pocos bytes ganan.

¡Tienen en él!

AJFaraday
fuente
99
Los nombres Alice (A) y Bob (B) me están dando recuerdos de la clase de seguridad de red. La actriz Alice (A) envía un paquete a Bob (B) con la llave ... etc ...
Magic Octopus Urn
21
@MagicOctopusUrn esos son ellos. Por lo general, intentan comunicarse. Lamentablemente, a menudo se produce un conflicto cuando se rompe la comunicación.
AJFaraday
77
Extraño los días en que estábamos tratando de descubrir cómo esconder nuestros secretos de Mallory ... esos eran tiempos más simples ...
Bob
44
@Bob Mallory es realmente una distracción. Es a Eva a quien debes tener cuidado.
AJFaraday
3
@ msh210 bueno, el detalle importante en el código de golf es que todos toman el mismo desafío, pero aquí está la lógica: si estuvieras jugando Dungeons and Dragons, dirías "Voy a patear al duende", entonces tú ' d rodar por efectividad, luego implementar el resultado del rollo. Un rollo no tiene sentido si nadie sabe para qué estás rodando.
AJFaraday

Respuestas:

5

05AB1E , 49 bytes

"BaABr0Aha"S3ô»D„AB‡[6LΩ©Tǝ¤H®-©16ǝ=®0‹#s]н…ÿ w?

Pruébalo en línea!

Explicación

"BaABr0Aha"                                        # push the initial state of B
           S                                       # split to list of characters
            3ô                                     # divide into 3 parts
              »                                    # join each part on space and all on nl
               D„AB‡                              # make a copy with A and B inverted
                     [                             # start a loop
                      6LΩ©                         # pick a random number in [1 ... 6]
                          Tǝ                       # insert at position 10 of the string
                            ¤H                     # get the last char of the string and
                                                   # convert from hex
                              ®-©                  # subtract the random number
                                 16ǝ=              # insert at position 16 and print
                                     ®0‹#          # if the hp is less than 0, break
                                         s         # swap the other string to the stack top
                                          ]        # end loop
                                           н…ÿ w?  # print the winner
Emigna
fuente
13

Python 3 , 131 bytes

x,y="AB"
from random import*
X=Y=10
p=print
while X>0:p(x,"a",y);d=randint(1,6);p(x,"r",d);Y-=d;p(y,"h",Y);x,y,X,Y=y,x,Y,X
p(y,"w")

Pruébalo en línea!

-8 bytes gracias a officialaimm
-2 bytes gracias a ChooJeremy

Hiperneutrino
fuente
55
predefinir p=printle ahorrará alrededor de 8 bytes.
officialaimm
Dado que y siempre gana en este punto (y solo X ataca en el ciclo, que luego se cambia a Y), no es necesario verificar si y ha perdido. - ChooJeremy - De la opinión
NoOneIsHere
@NoOneIsHere gracias por pasarme el mensaje: D
HyperNeutrino
randint(1,6)podría reemplazarse id(X+Y)//3%6+1, aunque la distribución no es bastante uniforme.
Vincent
@Vincent No veo el punto de doblar las reglas si ni siquiera ayuda a
acortarlo
7

C (gcc) , 146 141 bytes

f(A,B,r,t,a,b){for(A=B=10;r=1+clock()%6,A*B>0;t=!t)printf("%c a %c\n%c r %u\n%c h %i\n",a=65+t,b=66-t,a,r,b,t?A-=r:(B-=r));printf("%c w",a);}

Pruébalo en línea!

De-golf:

f(A,B,r,t,a,b){
    for(A=B=10; //Initialize HP
        r=1+clock()%6, // Get the number of processor cycles the program has consumed. This is relatively random, so I call it good enough.
        A*B>0;t=!t) // Flip t for change of turns
        printf("%c a %c\n%c r %u\n%c h %i\n", // Print the turn
            a=65+t,b=65+!t,a,r,b, // 65 is ASCII for 'A', 66 for 'B'
            t?A-=r:(B-=r)); // Deduct the damage.
    printf("%c w",a); // Print the winner
}

fuente
2
¿Podría guardar un byte usando a=65+t,b=66-t?
moopet
A*B>0te ahorrará unos pocos bytes.
Olivier Grégoire
A*Bahorrará aún más, pero estoy un poco apurado. Actualizaré por la noche
Encontró un error en los dados seq {6,4,3,1,5}. b gana con salud -4. Vea el TIO . Cambié su calculadora de dados para demostrar este error.
GPS
@GPS Gracias, lo arreglaré ahora.
7

Python 3 , 127 bytes

Esta es una mejora en la respuesta de @HyperNeutrino que no cabe en un comentario. Vea la explicación a continuación.

x,y="AB"
s=id(0)
X=Y=10
p=print
while X>0:p(x,"a",y);s=s**7%~-2**67;d=s%6+1;p(x,"r",d);Y-=d;p(y,"h",Y);x,y,X,Y=y,x,Y,X
p(y,"w")

Pruébalo en línea!


Una búsqueda épica para un lanzamiento de dados de pitón más corto

TL; DR: es posible eliminar 4 bytes de la tirada de dados estándar de Python mediante el cifrado RSA.

Quería ver si la tirada de dados estándar de Python ( 32 bytes ) podría acortarse un poco:

from random import*;randint(1,6)

En particular, id(x)es bastante conveniente aportar algún valor no determinista al programa. Mi idea era, de alguna manera, hash este valor para crear una aleatoriedad real. Intenté algunos enfoques, y uno de ellos valió la pena: cifrado RSA .

Cifrado RSA, debido a su simplicidad, sólo requiere unos pocos bytes: m**e%n. El siguiente valor aleatorio se puede crear cifrando el anterior. Suponiendo que la (e,n)clave esté disponible, la tirada de dados se puede escribir con 22 bytes :

s=id(0);s=s**e%n;s%6+1

Eso significa que tenemos unos 10 bytes para definir una clave RSA válida. Aquí tuve suerte. Durante mis experimentos, comencé a usar el Mersenne prime M67 solo para darme cuenta más tarde de que Mersenne cometió un error al incluir el M67 en su lista. Resulta ser el producto de p=193707721y q=761838257287. Había encontrado mi módulo:

n=~-2**67

Ahora, el exponente y el paciente de Charmichael (p-1)*(q-1) deben ser coprimos. Afortunadamente, el primer número primo que no divide el total de n tiene solo un dígito de largo: 7. La tirada de dados se puede escribir usando 28 bytes (4 bytes menos que el enfoque estándar):

s=id(0);s=s**7%~-2**67;s%6+1

Una buena cosa con M67 es que el valor aleatorio generado tiene 66 bits, que es más que el RNG habitual de 64 bits. Además, el uso de RSA hace posible retroceder en el tiempo descifrando el valor actual varias veces. Aquí están las claves de cifrado y descifrado:

Encryption: (7,                    147573952589676412927)
Decryption: (42163986236469842263, 147573952589676412927)

Definitivamente no soy un experto en estadística o criptografía, por lo que realmente no puedo decir si este RNG verifica o no los criterios de "buena aleatoriedad". Hice escribir un pequeño punto de referencia que compara la desviación estándar de las ocurrencias de los 1 a 6 dados rollos utilizando diferentes generadores de números aleatorios. Parece que la solución propuesta funciona igual que otras.

Vincent
fuente
3
Impresionante trabajo! :)
HyperNeutrino
4

JavaScript (ES6), 122 bytes

f=(h=[10,10,p=0])=>`${x='AB'[p]} a ${y='BA'[p]}
${x} r ${d=Math.random()*6+1|0}
${y} h ${H=h[p^=1]-=d}
${H<1?x+' w':f(h)}`

Pruébalo en línea!

Arnauld
fuente
4

Java (JDK 10) , 180 bytes

v->{var r="";int p=0,H[]={10,10},h=0;for(;H[0]*H[1]>0;)r+=r.format("%3$c a %4$c%n%3$c r %d%n%4$c h %d%n",h+=Math.random()*6-h+1,H[p]-=h,p+65,(p^=1)+65);return r+(char)(66-p)+" w";}

Pruébalo en línea!

Créditos

Olivier Grégoire
fuente
1
Java 10 tiene var? o.Ô Realmente necesito investigar algunas de las nuevas especificaciones pronto ... De todos modos, puedes jugar golf 4 bytes cambiando el conjunto de caracteres a int-array:v->{var r="";int P[]={65,66},p=0,H[]={10,10},h=0;for(;H[0]*H[1]>0;)r+=r.format("%3$c a %4$c%n%3$c r %d%n%4$c h %d%n",h+=Math.random()*6-h+1,H[p]-=h,P[p],P[p^=1]);return r+=P[p^1]+" w";}
Kevin Cruijssen
1
@KevinCruijssen Sí, Java 10 tiene var. No es necesario seguir leyendo, es básicamente el único cambio que podemos usar para nosotros los golfistas. Y no, no puedo hacer lo que sugieres: verifica la última línea del resultado: se convierte en 65 wlugar de A w. Por eso lo extraje de la int ...declaración: jugar al golf unos pocos bytes ;-)
Olivier Grégoire
1
@KevinCruijssen Cumplí algunos ejemplos aquí: codegolf.stackexchange.com/a/159922/16236
Olivier Grégoire
3

Ruby , 122 120 96 92 91 bytes

f=->x=?A,y=?B,m=10,n=m{p [x,?a,y],[x,?r,r=1+rand(6)],[y,?h,t=n-r]
t<1?p([x,?w]):f[y,x,t,m]}

Guardado 1 byte gracias a Asone Tuhid .

Pruébalo en línea!

Cristian Lupascu
fuente
1
Es como si ya no supiera cómo Ruby;)
AJFaraday
Me temo que su alternativa no funciona, "Todas las partes de una acción deben estar en la misma línea". Sin embargo, ¿podría ser posible hacer la misma optimización con un carácter de tabulación?
AJFaraday
@AJFaraday ¿Sería aceptable generar líneas en el formato ["A", "a", "B"]? Si es así, tengo esta solución de 96 bytes.
Cristian Lupascu
Si salen uno por línea. Eso debería hacer.
AJFaraday
-1 byte si lo reemplaza ?(p [x,?w]):con?p([x,?w]):
Asone Tuhid
3

Java 8, 230 bytes

v->{for(int h=104,a=h,x=0,y=1,A=10,B=A,r=0,t=0,T;a<119;)System.out.printf("%c %3$c %c%n",(x=a>h|A*B<1?x^1:x)+65,y=(a<98?t=r+=Math.random()*6-r+1:a>h?(T=x<1?A-=t:(B-=t))<0?0:T:A*B<1?-16:(x^1)+17)+48,a=a<98?114:a>h?104:A*B<1?119:97);}

Nota: ya hay una respuesta Java mucho más corta, ¡así que asegúrate de votar la suya ! Sin embargo, uso un enfoque completamente diferente, así que pensé que valía la pena publicarlo también.

Explicación:

Pruébalo en línea.

v->{                     // Method with empty unused parameter and no return-type
  for(int h=104,         //  Temp integer with unicode for 'h' to save bytes
          a=h,           //  Second part (Action)
          x=0,           //  First part
          y=1,           //  Third part
          A=10,          //  Score player A, starting at 10
          B=A,           //  Score player B, starting at 10
          r=0,           //  Random dice-roll
          t=0,           //  Previous dice-roll
          T;             //  Temp integer
      a<119;)            //  Loop until there is a winner
     System.out.printf(  //   Print
      "%c %3$c %c,%n",   //    The three parts with spaces, and a new-line
      (x=                //    First part:
         a>h             //     If the previous action is 'r',
         |A*B<1?         //     or there is a winner:
           x^1           //      Change A→B or B→A
         :               //     Else:
          x)             //      A/B remains unchanged
       +65,              //     Add 65 to convert 0/1 to 65/66 (unicode values of A/B)
      (y=                //    Third part:
         (a<98?          //     If the previous action was 'a'
           t=r+=Math.random()*6-r+1
                         //      Roll the dice, and save it in `t`
          :a>h?          //     Else-if the previous action was 'r':
           (T=x<1?       //      If the first part changed to player A:
            A-=t         //       Subtract the previous dice-roll from A
           :             //      Else:
            (B-=t))      //       Subtract the previous dice-roll from B
           <0?           //      If this score is below 0:
            0            //       Use 0
           :             //      Else:
            T            //       Use this score
         :               //     Else (the previous action was 'h'):
          A*B<1?         //      Is there a winner:
           -16           //       Change the third part to a space
          :              //      Else:
           (x^1)+17)     //       Change the third part to the other player
       +48,              //     Add 48 to convert it to unicode
       a=                //    Second part:
         a<98?           //     If the previous action was 'a': 
          114            //      Change it to 'r'
         :a>h?           //     Else-if the previous action was 'r':
          h              //      Change it to 'h'
         :               //     Else (the previous action was 'h'):
          A*B<1?         //      If either score is 0:
           119           //       Use 'w'
          :              //      Else:
           97);}         //       Use 'a'
Kevin Cruijssen
fuente
3

C (gcc) , 142 bytes

#define R(c,t)r=rand()%6+1,c&&printf(#c" a "#t"\n"#c" r %d\n"#t" h %d\n",r,t-=t<r?t:r),t||puts(#c" w")
f(A,B,r){for(A=B=10;A*B;R(B,A))R(A,B);}

Pruébalo en línea!

nwellnhof
fuente
Solo un problema, esto no terminó en una victoria.
AJFaraday
@AJFaraday Oh sí, arreglado.
nwellnhof
2

Lote, 174 bytes

@set/aA=B=10
@set c=A
@set d=B
:g
@set/ar=%random%%%6+1,h=%d%-=r
@echo %c% a %d%
@echo %c% r %r%
@echo %d% h %h%
@if %h% gtr 0 set c=%d%&set d=%c%&goto g
@echo %c% w

Explicación: %las referencias variables se sustituyen en el tiempo de análisis. Esto tiene dos beneficios útiles:

  • %d%-=rresta rde la variable nombrada por d(es decir, referencia indirecta)
  • set c=%d%&set d=%c% es simplemente un intercambio directo.
Neil
fuente
2

PHP 7.1: 159 bytes

<?php $A=$B=10;$t='AB';while($A>0&&$B>0){$a=$t[0];$b=$t[1];$d=rand(1,6);$$b-=$d;echo"$a a $b\n$a r $d\n$b h {$$b}\n";$t=strrev($t);}echo($A>0?'A':'B')." w\n";

Ejecútelo en el navegador aquí!

PHP 5.6: 156 bytes

<?php $A=$B=10;$t='AB';while($A>0&&$B>0){list($a,$b)=$t;$d=rand(1,6);$$b-=$d;echo"$a a $b\n$a r $d\n$b h {$$b}\n";$t=strrev($t);}echo($A>0?'A':'B')." w\n";

Ejecútelo en el navegador aquí!

Así es como se ve la solución PHP 5.6 con formato y comentarios:

<?php
// Initialize both HP counters
$A = $B = 10;

// Set the turn order as a string (which 5.6 allows to be unpacked into a list)
$t = 'AB';

// Run this loop as long as both players have HP
while ($A > 0 && $B > 0) {
    // Unpack the turn string into $a and $b variables; on the first run, $a = 'A'
    // and $b = 'B'. This is no longer possible in PHP 7.0, so the PHP 7.0
    // solution needed to use an array instead.
    list($a, $b) = $t;

    // Set damage to a random number between 1 and 6
    $d = rand(1, 6);

    // Subtract the damage from the referenced value $b. On the first turn, this
    // is 'B', so this ends up subtracting $d from $B. Next turn, $b will be 'A',
    // so it'll subtract $d from $A
    $$b -= $d;

    // Echo the string (interpolated values)
    echo "$a a $b\n$a r $d\n$b h {$$b}\n";

    // Reverse the turn order string ('AB' becomes 'BA', which will affect the
    // call to list in the first line of the while-loop)
    $t = strrev($t);
}

// Someone's run out of HP; figure out whom by figuring out who still has HP
echo ($A > 0 ? 'A' : 'B') . " w\n";
Chris Forrence
fuente
1

Bash, 178 bytes

A=10 B=10 e=echo
a(){ $e $1 a $2;d=$((RANDOM%6+1));$e $1 r $d;eval $2=$((${!2}-$d));$e $2 h ${!2};[ ${!2} -gt 0 ];}
while a A B && a B A;do cd;done;[ $A -gt 0 ]&&$e A w||$e B w
crystalgecko
fuente
1

F #, 238 235 bytes

¡Pensé que me estaba yendo bien, pero todos ustedes me han superado!

let p=printfn
let mutable A=10
let mutable B=A
let x h a d=
 p"%s a %s"a d
 let i=(new System.Random()).Next(1,7)
 let j=h-i
 p"%s r %i"a i
 p"%s h %i"d j
 if j<=0 then p"%s w"a
 j
while A*B>0 do
 B<-x B"A""B"
 if B>0 then A<-x A"B""A"

Pruébalo en línea!

Gracias a Rogem por los brillantes consejos para usar A * B> 0 en lugar de A> 0 && B> 0 (quita 3 bytes).

Gracias también a officialaimm, cuya sugerencia sobre la predefinición de printf en la respuesta de Python también me ayudó a eliminar algunos bytes.

Ciaran_McCarthy
fuente
1
Un consejo que recibí de @OlivierGregoire: A*B>0te ahorrará un par más.
Eso es absolutamente brillante. Quiéralo. ¡Muchas gracias!
Ciaran_McCarthy
1

Haskell , 204 bytes

Mi intento con Haskell, lamentablemente no pude hacerlo más competitivo

import System.Random
main=getStdGen>>= \g->putStr$q(randomRs(1,6)g)10(10::Int)"A ""B "
(!)=(++)
l="\n"
q(x:z)a b p o=p!"a "!o!l!p!"r "!show x!l!o!"h "!show n!l!if n<1then p!"w"else q z n a o p where n=b-x

Pruébalo en línea!

Explicaciones:

import System.Random  --import random module
main=                        --main function, program entry point
 getStdGen                   -- get the global random number generator
   >>= \g->                  --using the random generator g
       putStr $ q            --print the result of function q, passing in ..
          (randomRs (1,6) g) --an infinite list of random numbers, 1 to 6 generated by g
           10 (10::Int)      --the starting health of both players, 
                             --type annotation sadly seems to be required
           "A " "B "         --The names of the players,
                             --with an extra space for formatting
(!)=(++) --define the operator ! for list (String) concatenation, 
         -- we do this a lot so we save a bit by having a one byte operator
l="\n"   -- define l as the newline character

q      --define function q                         
 (x:z) --our list of random numbers, split into the next number (x) and the rest (z)
 a     -- the health of the active player
 b     -- the health of the player getting attacked
 p     -- the name of the active player
 o     -- the name of the player getting attacked
=
  p!"a "!o!l --create the attack action string with a newline
 !p!"r "!show x!l -- append the roll action
 !o!"h "!show n!l -- append the health remaining
 !           -- append the result of the following if
  if n<1     -- if the player being attacked has been defeated
  then p!"w" -- append the win string for the active player
  else q z n a o p  --otherwise append the result of calling q again with 
                    --rest of the random numbers, and the active players swapped
  where n=b-x -- define the attacked player's new health n
              -- their current health b - the random roll x
puhlen
fuente
Puede echar un vistazo a nuestros Consejos para jugar al golf en Haskell . Por ejemplo, where m=b-xse puede poner en guardia: |m<-b-x=.
Laikoni
Se puede perder la lambda y un conjunto de paréntesis, reordenando algunos parámetros: main=putStr=<<q"A "10"B "10.randomRs(1,6::Int)<$>getStdGen. También puede usar una lista y concatenarla para deshacerse de la redefinición (++). El último lugar no parece ser beneficioso para usarlo en b-xtodas partes.
Angs
1

Julia 0.6 , 175 bytes

p=println()
f(l="AB",h=[10,10],a=1)=(while min(h...)>0;d=3-a;p(l[a]," a ",l[d]);r=rand(1:6);h[d]-=r;p(l[a]," r ",r);p(l[d]," h ",max(h[d],0));a=d;end;p(l[findmax(h)[2]]," w"))

Pruébalo en línea!

Versión larga y sin golf:

function status(player, health)
    println("$player h $(max(0,health))")
end

function roll(player)
    x = rand(1:6)
    println("$player r $x")
    x
end

function play()
    players = ["A","B"]
    healths = [10, 10]
    attacker = 1

    while min(healths...) > 0
        println("$(players[attacker]) a $(players[3-attacker])")
        healths[3-attacker]-=roll(players[attacker])
        status(players[3-attacker], healths[3-attacker])

        attacker = 3 - attacker
    end

    winner = findmax(healths)[2]
    println("$(players[winner]) w")
end
niczky12
fuente
No parece haber ninguna salida en su enlace TIO.
AJFaraday
Sí, no sé por qué a tio no le gusta. Funciona bien en mi máquina. Lo investigaré si tengo tiempo.
niczky12
1

VBA, 222 185 179 Bytes

Esta solución recursiva involucra 3 subs

  1. g es el comienzo del juego que comienza el primer turno
  2. Se llama t para cada turno . Utiliza la recursividad.
  3. p es más corto que Debug.Print cuando se usa más de 3 veces (solo 4 en esta solución) Editar: Ahora que aprendí que Debug.?es una alternativa aceptable Debug.Print, Debug.?xes más corto que llamar a un Sub para imprimir.
Sub g()
t "A",10,"B",10
End Sub
Sub t(i,j,x,h)
d=Int(Rnd()*6)+1
Debug.?i &" a "&x
Debug.?i &" r "&d
h=h-d
If h<1Then
Debug.?i &" w"
Else
Debug.?x &" h "&h
t x,h,i,j
End If
End Sub

Este fue un desafío divertido. Si conoce a un intérprete en línea como TIO para VB6 / VBScript / VBA, deje un comentario. Entonces puedo publicar un enlace a una solución de trabajo.

Si desea probar este código y tiene instalado Microsoft Excel, Word, Access o Outlook (solo Windows), presione Alt + F11 para abrir el IDE de VBA. Inserte un nuevo módulo de código (Alt + I, M) y borre la Opción explícita. Luego pegue el código y presione F5 para ejecutarlo. Los resultados deberían aparecer en la ventana Inmediato (presione Ctrl + G si no lo ve).

Edición 1: Espacio en blanco eliminado que el editor de VBA agregará automáticamente. Reducido en 37 bytes
Edición 2: Eliminado Sub p () * para guardar 6 bytes después de aprender Debug.?es una alternativa aceptable Debug.Print. Llamar a un Sub para que maneje Debug.?solo guarda bytes después de más de seis llamadas.

Ben
fuente