Alice and Bob have a fight
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")
Try it online!
-8 bytes thanks to officialaimm
-2 bytes thanks to ChooJeremy
Python 3, 127 bytes
This is an improvement on @HyperNeutrino answer that wouldn't fit in a comment. See the explanation below.
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")
Try it online!
An epic quest for a shorter python dice roll
TL;DR: It's possible to shave 4 bytes off the standard python dice roll by using RSA encryption.
I wanted to see if the standard python dice roll (32 bytes) could be shortened a bit:
from random import*;randint(1,6)
In particular, id(x)
is quite convenient to bring some non-deterministic value into the program. My idea then was to somehow hash this value to create some actual randomness. I tried a few approaches, and one of them paid off: RSA encryption.
RSA encryption, due to its simplicity, only requires a few bytes: m**e%n
. The next random value can then be created by encrypting the previous one. Assuming the (e,n)
key is available, the dice roll can be written with 22 bytes:
s=id(0);s=s**e%n;s%6+1
That means we have about 10 bytes to define a valid RSA key. Here I got lucky. During my experiments, I started to use the Mersenne prime M67 only to realize later on that Mersenne made a mistake including M67 in his list. It turns out to be the product of p=193707721
and q=761838257287
. I had found my modulus:
n=~-2**67
Now, the exponent and the Charmichael totient lcm(p-1,q-1)
need to be coprime. Luckily again, the first prime number that do not divide the totient of n is only one digit long: 7. The dice roll can then be written using 28 bytes (4 bytes less than the standard approach):
s=id(0);s=s**7%~-2**67;s%6+1
One good thing with M67 is that the random value generated has 66 bits, which is more than the usual 64 bits RNG. Also, the use of RSA makes it possible to go back in time by decrypting the current value multiple times. Here are the encrypting and decrypting keys:
Encryption: (7, 147573952589676412927)
Decryption: (42163986236469842263, 147573952589676412927)
I'm definitely not an expert in statistics or cryptography, so I can't really tell whether or not this RNG checks the criteria for "good randomness". I did write a small benchmark that compares the standard deviation of the occurrences of the 1 to 6 dice rolls using different RNGs. It seems like the proposed solution works just like other ones.
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);}
Try it online!
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
}