Les flics et les voleurs

11

Tout le monde veut toujours implémenter Game of Life de Conway. C'est ennuyant! Faisons plutôt des flics et des voleurs!

Vous aurez deux équipes: les flics et les voleurs. Chaque équipe compte 5 membres avec 50 points de vie chacun. Le programme sera bouclé en continu. À chaque itération, les événements suivants se produisent:

  • Pour chaque équipe, imprimez la première lettre ( Cpour les flics, Rpour les voleurs), un espace, une liste des HP des membres séparés par un espace et une nouvelle ligne. Ceci est le statut des équipes. Une fois les deux terminés, imprimez une autre nouvelle ligne. Par exemple, voici à quoi cela pourrait ressembler au premier tour:

    C 50 50 50 50 50
    R 50 50 50 50 50
    
  • Choisissez un nombre aléatoire de 1 à 10 (y compris 1 et 10). Nous appellerons le numéro N. Si Nc'est égal, les voleurs perdent ce tour; si c'est étrange, les flics perdent.

  • Choisissez un membre aléatoire de l'équipe perdante dont les HP sont supérieurs à 0 et déduisez les NHP. Les HP des membres ne devraient jamais apparaître en dessous de 0 sur le statut.

  • Redémarrez la boucle.

Le jeu se termine lorsque tous les membres d'une équipe perdent tous leurs PV. Ensuite, ce qui suit sera imprimé si les flics gagnent:

C+
R-

et si les voleurs gagnent:

R+
C-

C'est le golf de code, donc le plus petit nombre de personnages gagne.

Voici un exemple d'implémentation dans 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
la source
Ironie mineure: sur les 3176+ questions sur ce site, pas plus de 11 sont marquées game-of-life.
Sanchises le
3
@sanchises Ironie prolongée: et 14 sont étiquetés cops-and-robbers!
Runer112
@sanchises Je parlais largement de la programmation en général (par exemple "Aidez-moi! J'essaie d'implémenter le jeu de la vie de Conway!") ... mais c'est encore assez ironique.
kirbyfan64sos
@ kirbyfan64sos Je sais (j'y suis allé, j'ai fait ça), mais c'est exactement le genre de site où les gens vont après avoir implémenté GoL et en veulent plus ... Quoi qu'il en soit, j'essaierai peut-être cela dans> <> , voyons si je peux le faire.
Sanchises
J'ai de nouveau retiré la balise CnR. Ici, cette balise a une signification très spécifique et décrit les défis où il y a en fait deux parties (pas nécessairement disjointes) en concurrence l'une contre l'autre pour certaines tâches (jetez un œil aux autres défis avec cette balise).
Martin Ender

Réponses:

3

CJam, 86 octets

Je suis un peu en retard à la fête, mais j'apporte le cadeau de CJam! ... Hé, attends, où vas-tu?

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

Essayez-le en ligne.

Explication

Comme la question demande d'imiter un processus simple, c'est une réponse relativement simple. Peut-être qu'un choix intéressant que j'ai fait a été de maintenir la santé des deux équipes entrelacées dans la même liste. Cela coûte 3 octets pour se convertir en deux listes distinctes, ce qui est nécessaire à la fois pour afficher la santé et vérifier si une équipe a perdu. Mais (je pense) cela est compensé par les 2 octets enregistrés dans l'initialisation et la logique de traitement des dommages beaucoup plus simple.

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
la source
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
la source
Aussi pourquoi le rep(which(x>0),2)par opposition à juste which(x>0)?
MickyT
1) Je compte les caractères EOL, pas le dernier cependant. 2) sum(R*C)et ce sum(R)*sum(C)n'est pas la même chose. Par exemple, vous ne voudriez pas quitter si C = c (0,0,0,10,10) et R = c (10, 10, 10, 0, 0). Dans ce cas, je sauvegarde en affectant S=sum. 3) Le problème avec sampleest que si le premier argument est un seul nombre, par exemple sample(5, 1), alors ce sera la même chose que faire sample(1:5, 1): au lieu de toujours retourner 5, il retournera n'importe quel nombre de 1à 5. Il en sample(rep(x, 2), 1)est de même de mon astuce pour toujours choisir un nombre parmi xmême dans le cas où l' length(x)est 1.
flodel
Désolé mon mauvais ... Manifestement, pas assez de café. Merci pour l'explication sur l'astuce rep (). Je pensais qu'il devait y avoir une raison, je ne pouvais tout simplement pas la voir
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
∇

Explication:

  • S←2 5⍴50: au début, défini Ssur une matrice 5 par 2 où chaque valeur est 50. La ligne supérieure de la matrice représente les flics, la deuxième ligne représente les voleurs.
  • J←∨/S>0: pour chaque ligne de la matrice, indiquez Jsi l'un des HP est supérieur à zéro.
  • →6/⍨~∧/J: si les deux équipes n'ont pas de membres vivants, passez à la ligne 6. (fin)
  • ⎕←3↑'CR',0⌈S: pour chaque valeur de la matrice, sortez-en le maximum et 0, ajoutez un «C» à la première ligne et un «R» à la seconde, et ajoutez une troisième ligne (vide).
  • N←?10: obtenir un nombre aléatoire dans l'intervalle [1,10] et le stocker N.
  • L←1+~2⊤N: définissez L(l'équipe perdante) 1si le nombre était impair et 2s'il était pair.
  • M←(0<S[L... ;])/⍳5: récupérez les indices des membres vivants de cette équipe et stockez-les dansM
  • M[?⍴M... ]: sélectionnez une valeur aléatoire dansM
  • S[L;M... ]-←N: soustraire Nde la valeur du membre de l'équipe sélectionné
  • →2: passez à la ligne 2 (le test pour les membres vivants)
  • ⎕←'CR',⍪'+-'⌽⍨J⍳0: affiche le statut final en plaçant le +devant de l'équipe gagnante et le -devant de l'équipe perdante.

Exemple de sortie

marinus
la source
1

Rubis, 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-'
histocrate
la source
1

Mathematica, 246 241 octets

Pourrait probablement être joué au golf plus loin ...

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
la source
1

PHP - 416 octets

Je suis nouveau au golf et bien que ce défi soit assez facile à essayer. Voici donc ce que j'ai trouvé.

<?$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";}}?>

Avec explication:

<? 
$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
la source
Je ne suis pas un utilisateur PHP, mais je suppose que vous pourriez peut-être couper quelques caractères en supprimant != 0et en remplaçant le chèque pour être égal à zéro par l'opérateur not ( !array_sum($r)).
kirbyfan64sos
@ kirbyfan64sos qui ne fonctionne pas
Timo
Oh. Dans la plupart des langues, ce serait le cas.
kirbyfan64sos
1

C, 390 384 371 octets

Mon premier golf, s'il y a des améliorations possibles, dites-le moi :)

version golfée:

#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);}

version quelque peu non golfée:

#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);
}

edit: j'ai trouvé un moyen de le raccourcir un peu et j'ai corrigé un petit bug

Metaforce
la source
Une petite amélioration: vous pouvez remplacer les boucles (par exemple for(j=0;j<10;j++)) par une version plus courte ( for(j=10;--j;)).
kirbyfan64sos
Vous avez tout à fait raison, "corrigé" ceci et quelques autres petites choses, merci.
Metaforce
0

Lot - 396 octets

Je ne sais pas si cela compte techniquement - car il ne sélectionne pas réellement un membre aléatoire de l'équipe dont la santé est supérieure à 0 . Il sélectionne simplement un membre aléatoire, et si la soustraction de santé génère un nombre inférieur à 0, alors le nombre devient 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!-
dégrader
la source
La condition est que la valeur ne soit jamais inférieure à 0 sur l'état imprimé. J'ai fait la même chose dans l'exemple que j'ai montré.
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-')
logic8
la source
0

Octave, 182177158145 octets

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,:)

J'ai renoncé à vérifier si le tournage du personnage est supérieur à zéro - cela ne serait significatif que si nous étions obligés d'afficher l'état à chaque tour - ici, nous sautons simplement un nombre aléatoire de RNG, ce qui le rend plus aléatoire.

Aussi, remplacé

t=max(0,t)

avec plus court

t.*=t>0


[note - il imprime 'C + R-' sans la nouvelle ligne - il est corrigé dans la version 145 octets]

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))

Dégolfé:

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))

J'ai changé repmat(50,5,2)pour repmat(5)- nous avons donc une matrice 5x5 au lieu de 5x2 maintenant (les 3 colonnes supplémentaires n'affectent pas l'algorithme). J'ai également trouvé un moyen de compresser la sortie.

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

Dégolfé:

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

Fondamentalement, nous créons une matrice 5x2, où la première colonne sont des flics et la deuxième colonne sont des voleurs:

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

La sumfonction lorsqu'un argument appliqué fait une somme par colonnes, c'est donc initialement:

250    250

Lorsque l'un d'eux atteint zéro, l' prod(sum(t))évalue à zéro en rompant la boucle. Ensuite, nous pouvons examiner qui a gagné en vérifiant dont la colonne est égale à zéro.

pawel.boczarski
la source