Policías y ladrones

11

Todos siempre quieren implementar el Juego de la vida de Conway. ¡Eso es aburrido! ¡Hagamos policías y ladrones en su lugar!

Tendrás dos equipos: los policías y los ladrones. Cada equipo tiene 5 miembros con 50 de salud cada uno. El programa se repetirá continuamente. Cada iteración, ocurrirá lo siguiente:

  • Para cada equipo, imprime la primera carta ( Cpara los policías, Rpara los ladrones), un espacio, una lista separada por espacios de los HP de los miembros y una nueva línea. Este es el estado de los equipos. Después de que ambos estén listos, imprima otra nueva línea. Por ejemplo, esto es lo que podría parecer la primera ronda:

    C 50 50 50 50 50
    R 50 50 50 50 50
    
  • Elija un número aleatorio del 1 al 10 (incluidos 1 y 10). Llamaremos al número N. Si Nes par, los ladrones pierden esta ronda; si es extraño, la policía pierde.

  • Elija un miembro aleatorio del equipo perdedor cuyo HP sea mayor que 0 y deduzca NHP. El HP de los miembros nunca debería aparecer debajo de 0 en el estado.

  • Reinicia el bucle.

El juego termina cuando todos los miembros de un equipo pierden todos sus HP. Luego, se imprimirá lo siguiente si la policía gana:

C+
R-

y si los ladrones ganan:

R+
C-

Este es el código de golf, por lo que gana el menor número de caracteres.

Aquí hay una implementación de muestra en Python 2:

import random

cops = [50]*5
robbers = [50]*5

while any(cops) and any(robbers):
    # print the status
    print 'C', ' '.join(map(str, cops))
    print 'R', ' '.join(map(str, robbers))
    print
    # pick N
    N = random.randint(1, 10)
    # pick the losing team (robbers if N is even, else cops)
    losers = robbers if N % 2 == 0 else cops
    # pick a member whose HP is greater than 0
    losing_member = random.choice([i for i in range(len(losers)) if losers[i]])
    losers[losing_member] -= N
    # make sure the HP doesn't visibly drop below 0
    if losers[losing_member] < 0: losers[losing_member] = 0

if any(cops):
    # robbers lost
    print 'C+'
    print 'R-'
elif any(robbers):
    # cops lost
    print 'C-'
    print 'R+'
kirbyfan64sos
fuente
Menor ironía: de las 3176+ preguntas en este sitio, no se etiquetan más de 11 game-of-life.
Sanchises
3
@sanchises ironía extendida: ¡y 14 están etiquetados cops-and-robbers!
Runer112
@sanchises Me refería en gran medida a la programación en general (por ejemplo, "¡Ayúdame! ¡Estoy tratando de implementar Conway's Game of Life!") ... pero eso sigue siendo bastante irónico.
kirbyfan64sos
@ kirbyfan64sos Lo sé (he estado allí, hecho eso), pero este es exactamente el tipo de sitio donde la gente va después de haber implementado GoL y quiere más ... De todos modos, tal vez intentaré esto en> <> , veamos si puedo hacer eso.
Sanchises
He eliminado la etiqueta CnR nuevamente. Por aquí, esta etiqueta tiene un significado muy específico y describe los desafíos en los que en realidad hay dos partes (no necesariamente disjuntas) que compiten entre sí en ciertas tareas (eche un vistazo a los otros desafíos con esa etiqueta).
Martin Ender

Respuestas:

3

CJam, 86 bytes

Llego un poco tarde a la fiesta, ¡pero les traigo el regalo de CJam! ... Hey, espera, ¿a dónde vas?

50aA*{"CR"1$+2/zSf*Nf+oNoAmr{_AmrE&+:P2$=:H!}gPH@)-Ue>t_2/z::+0#:L)!}g;'CL'+'-?N'R2$6^

Pruébalo en línea.

Explicación

Como las preguntas piden emular un proceso sencillo, esta es una respuesta relativamente sencilla. Quizás una elección interesante que hice fue mantener la salud de ambos equipos intercalados en la misma lista. Esto cuesta 3 bytes para convertirlo en dos listas separadas, lo cual es necesario tanto para mostrar la salud como para verificar si un equipo ha perdido. Pero (creo) esto se compensa con los 2 bytes guardados en la inicialización y una lógica mucho más simple de reparación de daños.

50aA*           "Initialize the health list to 10 copies of 50. Even indices
                 hold the health of cops and odd indices hold the health of
                 robbers.";
{               "Do:";
  "CR"1$+2/z      "Split the health list into the two teams for output, adding
                   the corresponding team letter to the start of each.
                       [a b c d e f g h i j]
                    -> [['C a c e g i] ['R b d f h j]]";
  Sf*Nf+          "Insert a space between each element in each team health list
                   and append a newline to the end of each team health list.";
  oNo             "Print the health status for each team and an extra newline.";
  Amr             "Generate the damage amount minus one. If the damage amount is
                   even (robbers lose), then this is odd and aligns with robbers
                   being at odd indices in the health list, and vice versa.";
  {               "Do:";
    _AmrE&+:P       "Add a random even number from [0, 10) to the damage amount
                     minus one. This value modulo the size of the health list
                     (10) selects a person on the losing team to be damaged.";
    2$=:H!
  }g              "... While the selected person's health is zero.";
  PH@)-Ue>t       "Set the damaged person's new health to the maximum of their
                   current health minus the damage amount and zero.";
  _2/z::+0#:L     "Split the health list into the two teams, sum each team's
                   health, and search for a team's health equal to zero.";
  )!
}g              "... While no team's health was found equal to zero.";
;               "Discard the health list.";
'C              "Produce a 'C'.";
L'+'-?          "Produce a '+' if team 1 (robbers) lost, or '-' otherwise.";
N               "Produce a newline.";
'R              "Produce an 'R'.";
2$6^            "Produce the opposite of the sign produced before.";
                "Implicitly print these final results.";
Runer112
fuente
3

R - 201

S=sum
Z=sample
C=R=rep(50,5)
while(S(R)*S(C)){cat("C",C,"\nR",R,"\n\n")
N=Z(10,1)
F=function(x,i=Z(rep(which(x>0),2),1)){x[i]=max(0,x[i]-N);x}
if(N%%2)R=F(R)else C=F(C)}
cat(c("R+\nC-\n","C+\nR-\n")[1+!S(R)])
flodel
fuente
Además, ¿por qué lo rep(which(x>0),2)opuesto a lo justo which(x>0)?
MickyT
1) Estoy contando los caracteres EOL, no el último. 2) sum(R*C)y sum(R)*sum(C)no son lo mismo. Por ejemplo, no querrá salir si C = c (0,0,0,10,10) y R = c (10, 10, 10, 0, 0). En ese caso, guardo asignando S=sum. 3) El problema con samplees que si el primer argumento es un número único, por ejemplo sample(5, 1), será lo mismo que hacerlo sample(1:5, 1): en lugar de devolver siempre 5, devolverá cualquier número de 1a 5. Así sample(rep(x, 2), 1)es mi truco para elegir siempre un número xincluso en el caso cuando length(x)es 1.
flodel
Lo siento, mi mal ... Obviamente no hay suficiente café. Gracias por la explicación sobre el truco rep (). Pensé que debía haber una razón, simplemente no podía verla
MickyT
2

APL (Dyalog) (101)

∇K
S←2 5⍴50
→6/⍨~∧/J←∨/S>0
⎕←3↑'CR',0⌈S
S[L;M[?⍴M←(0<S[L←1+~2⊤N;])/⍳5]]-←N←?10
→2
⎕←'CR',⍪'+-'⌽⍨J⍳0
∇

Explicación:

  • S←2 5⍴50: al principio, establezca Suna matriz de 5 por 2 donde cada valor sea 50. La fila superior de la matriz representa a los policías, la segunda fila representa a los ladrones.
  • J←∨/S>0: para cada fila de la matriz, almacene Jsi alguno de los HP es mayor que cero.
  • →6/⍨~∧/J: si no ambos equipos tienen miembros vivos, salte a la línea 6. (final)
  • ⎕←3↑'CR',0⌈S: para cada valor en la matriz, genere el máximo y 0, anteponga una 'C' a la primera fila y una 'R' a la segunda, y agregue una tercera línea (vacía).
  • N←?10: obtenga un número aleatorio en el intervalo [1,10] y guárdelo N.
  • L←1+~2⊤N: establece L(el equipo perdedor) en 1si el número era impar y 2si era par.
  • M←(0<S[L... ;])/⍳5: obtenga los índices de los miembros vivos de ese equipo y guárdelos enM
  • M[?⍴M... ]: seleccione un valor aleatorio deM
  • S[L;M... ]-←N: restar Ndel valor del miembro del equipo seleccionado
  • →2: salte a la línea 2 (la prueba para miembros vivos)
  • ⎕←'CR',⍪'+-'⌽⍨J⍳0: muestra el estado final, colocando el +frente del equipo ganador y el -frente del equipo perdedor.

Salida de muestra

marinus
fuente
1

Rubí, 184

c,r=[p,p].map{('50 '*5).split}
puts([?C,*c]*' ',[?R,*r]*' ')while (u,v=[r,c].map{|a|a.shuffle.find{|x|x>?0}}).all?&&[u,v][rand(1..10)%2].sub!(/.+/){eval"#$&-1"}
puts u ?'R+
C-':'C+
R-'
histocrat
fuente
1

Mathematica, 246 241 bytes

Probablemente podría jugar más golf ...

a=ConstantArray[50,{2,5}];b=Or@@(#<1&)/@#&;c=Print;d=StringJoin@Riffle[IntegerString/@#," "]&;e=RandomInteger;Label@f;Which[b@a[[1]],c@"R+\nC-",b@a[[2]],c@"C+\nR-",True,c["C "<>d@a[[1]]<>"\nR "<>d@a[[2]]];a[[Mod[g=e@9+1,2]+1,e@4+1]]-=g;Goto@f]
LegionMammal978
fuente
1

PHP - 416 bytes

Soy nuevo en el golf y, aunque este desafío sería lo suficientemente fácil como para probarlo. Así que aquí está lo que se me ocurrió.

<?$c=[50,50,50,50,50];$r=[50,50,50,50,50];while((array_sum($c)!=0)&&(array_sum($r)!=0)){$a="C ".join(" ",$c)."\n";$b="R ".join(" ",$r)."\n";echo$a,$b;$n=rand(1,10);$m=rand(0,4);if($n %2==0){while($r[$m]==0){$m=rand(0,4);}$r[$m]=$r[$m]-$n;if($r[$m]<0){$r[$m]=0;}}else{while($c[$m]==0){$m=rand(0,4);}$c[$m]=$c[$m]-$n;if($c[$m]<0){$c[$m]=0;}}if(array_sum($r)==0){echo"C+\nR-\n";}if(array_sum($c)==0){echo"R+\nC-\n";}}?>

Con explicación:

<? 
$c=[50,50,50,50,50];$r=[50,50,50,50,50];                       populate Arrays
while((array_sum($c) != 0) && (array_sum($r) != 0)){           loop until on array sums up to 0
    $a="C ".join(" ",$c)."\n";                                 set cops health to a
    $b="R ".join(" ",$r)."\n";                                 set robbers health to b
    echo$a,$b;                                                 print cop and robber health
    $n=rand(1,10);                                             chose random n
    $m=rand(0,4);                                              chose random member
    if($n % 2 == 0){                                           check if n is even
        while($r[$m] == 0){ $m=rand(0,4); }                    loop until value m of array r is not 0
        $r[$m]=$r[$m]-$n;                                      lower health of member m
        if($r[$m] < 0){ $r[$m]=0; }                            if health goes below 0 set it to 0
    }else{
        while($c[$m] == 0){ $m=rand(0,4); }                    same as above
        $c[$m]=$c[$m] - $n;
        if($c[$m] < 0){$c[$m]=0;}
    }
    if(array_sum($r) == 0){ echo"C+\nR-\n"; }                  check if r array sums up to 0 and print that cops won
    if(array_sum($c) == 0){ echo"R+\nC-\n"; }                  check if c array sums up to 0 and print that robbers won
}
?>
Timo
fuente
No soy un usuario de PHP, pero supongo que tal vez cortarías algunos caracteres al eliminar != 0y reemplazar la verificación para que sea igual a cero con el operador no ( !array_sum($r)).
kirbyfan64sos
@ kirbyfan64sos que no funciona
Timo
Oh. En la mayoría de los idiomas, lo haría.
kirbyfan64sos
1

C, 390 384 371 bytes

Mi primer golf, si hay posibles mejoras, solo dime :)

versión de golf:

#include <time.h>
#include <stdio.h>
int p[10],j,r,c,w,N,x;int s(){r=c=0;for(j=5;j--;){c+=p[5+j];r+=p[j];}return !!r-!!c;}void t(){for(j=10;j--;)printf("%s %d",j-4?j-9?"":"\n\nC":"\nR",p[j]*=p[j]>0);}main(){srand(time(0));for(j=10;j--;)p[j]=50;t();while(!(w=s())){N=rand()%10+1;while(!p[x=N%2*5+rand()%5]);p[x]-=N;t();}N=(x=w<1?'C':'R')-w*15;printf("\n\n%c+\n%c-",x,N);}

versión un tanto sin golf:

#include <time.h>
#include <stdio.h>
int p[10],j,r,c,w,N,x;

int s(){
    r=c=0;
    for(j=5;j--;){
        c+=p[5+j];
        r+=p[j];
    }
    return !!r-!!c;
}

void t(){
    for(j=10;j--;)printf("%s %d",j-4?j-9?"":"\n\nC":"\nR",p[j]*=p[j]>0);
}

main(){
    srand(time(0));
    for(j=10;j--;)p[j]=50;
    t();
    while(!(w=s())){
        N=rand()%10+1;
        while(!p[x=N%2*5+rand()%5]);
        p[x]-=N;
        t();
    }
    //w=-1 if cops won, w=1 if robbers won
    N=(x=w<1?'C':'R')-w*15;
    printf("\n\n%c+\n%c-",x,N);
}

editar: encontré una manera de acortarlo un poco y solucioné un pequeño error

Metaforce
fuente
Una pequeña mejora: puede reemplazar los bucles (por ejemplo for(j=0;j<10;j++)) con una versión más corta ( for(j=10;--j;)).
kirbyfan64sos
Tiene toda la razón, "arregló" esto y algunas otras cosas menores, gracias.
Metaforce
0

Lote: 396 bytes

No sé si esto técnicamente cuenta, ya que en realidad no selecciona a un miembro aleatorio del equipo cuya salud sea mayor que 0 . Simplemente selecciona un miembro aleatorio, y si la resta de salud genera un número menor que 0, el número se convierte en 0.

@echo off&setLocal enableDelayedExpansion&for %%a in (C R)do for %%b in (1 2 3 4 5)do set %%a%%b=50
:a
set/aN=%RANDOM%*10/32768+1
set/ac=%N%/2*2
if %c%==%N% (set T=C&set L=R)else set T=R&set L=C
set/aG=%RANDOM%*5/32768+1
set/a%T%%G%-=%N%
for %%a in (C R)do set %%a=0&for %%b in (1 2 3 4 5)do (if !%%a%%b! LEQ 0 set %%a%%b=0
set/a%%a+=!%%a%%b!)
if %C% NEQ 0 if %R% NEQ 0 goto :a
echo !T!+&echo !L!-
carne sin carne
fuente
El requisito es que el valor nunca se muestre por debajo de 0 en el estado impreso. Hice lo mismo en el ejemplo que mostré.
kirbyfan64sos
0

Javascript: 410

function x(l){var t=this,o=t.p={n:l||"C",h:[50,50,50,50,50],s:function(){return o.h.reduce(function(a,b){return a+b})},r:function(){console.log(o.n+' '+o.h.join(' '))},d:function(m){while(o.h[z=~~(Math.random()*5)]<1){}o.h[z]=m>o.h[z]?0:o.h[z]-m}};o.r()}q=[new x(),new x('R')];while((c=q[0].p.s()>0)&&q[1].p.s()>0){q[(z=~~(Math.random()*10))%2].p.d(z);q[0].p.r();q[1].p.r()}console.log(c?'C+\r\nR-':'R+\n\rC-')
lógica8
fuente
0

Octava, 182177158145 bytes

145:

t=repmat(50,5);while prod(any(t))d=ceil(rand*10);c=2-mod(d,2);r=ceil(rand*5);t(r,c)-=d;t.*=t>0;end;p=2*any(t,1);['C-';'R+';'C+';'R-'](1+p:2+p,:)

Dejé de verificar si el disparo del personaje está por encima de cero, esto solo sería significativo si nos viéramos obligados a mostrar el estado en cada turno, aquí solo estamos saltando aleatoriamente un número aleatorio de RNG, haciéndolo más aleatorio.

Además, reemplazado

t=max(0,t)

con más corto

t.*=t>0


[nota: está imprimiendo 'C + R-' sin la nueva línea; está arreglado en la versión de 145 bytes]

158:

t=repmat(50,5);while prod(any(t))d=ceil(rand*10);c=2-mod(d,2);do r=ceil(rand*5);until t(r,c);t(r,c)-=d;t=max(0,t);end;p=4*any(t,1);disp('C-R+C+R-'(1+p:4+p))

Degolfed:

t=repmat(50,5);               #only first two columns (cops, robbers) relevant
while prod(any(t))
    d=ceil(rand*10);
    c=2-mod(d,2);
    do r=ceil(rand*5);until t(r,c);
    t(r,c)-=d;
    t=max(0,t);
end;
p=4*any(t,1);
disp('C-R+C+R-'(1+p:4+p))

Cambié repmat(50,5,2)a repmat(5), por lo que ahora tenemos una matriz de 5x5 en lugar de 5x2 (las 3 columnas adicionales no afectan el algoritmo). También encontré una forma de comprimir la salida.

177:

t=repmat(50,5,2);while prod(sum(t))d=ceil(rand*10);c=2-mod(d,2);do r=ceil(rand*5);until t(r,c);t(r,c)-=d;t=max(0,t);end;if sum(t)(1)printf "C+\nR-\n";else printf "C-\nR+\n";end

Degolfed:

t=repmat(50,5,2);
while prod(sum(t))
    d=ceil(rand*10);
    c=2-mod(d,2);                  #cops or robbers affected?
    do r=ceil(rand*5);until t(r,c);
    t(r,c)-=d;
    t=max(0,t);
end
if sum(t)(1)
    printf "C+\nR-\n"
else
    printf "C-\nR+\n"
end

Básicamente, creamos una matriz de 5x2, donde la primera columna son policías y la segunda columna son ladrones:

t =
50     50
50     50
50     50
50     50
50     50
[cops] [robbers]

La sumfunción cuando se aplica un argumento hace una suma por columnas, por lo que inicialmente es:

250    250

Cuando uno de ellos llega a cero, se prod(sum(t))evalúa a cero rompiendo el ciclo. Luego podemos examinar quién ganó comprobando qué columna suma cero.

pawel.boczarski
fuente