Guardie e ladri


11

Tutti vogliono sempre implementare il gioco della vita di Conway. È noioso! Facciamo invece poliziotti e ladri!

Avrai due squadre: i poliziotti e i ladri. Ogni squadra ha 5 membri con 50 salute ciascuno. Il programma eseguirà un ciclo continuo. Ad ogni iterazione, si verificherà quanto segue:

  • Per ogni squadra, stampa la prima lettera ( Cper i poliziotti, Rper i ladri), uno spazio, un elenco separato da spazi di HP dei membri e una nuova riga. Questo è lo stato delle squadre. Al termine di entrambi, stampare un'altra riga. Ad esempio, ecco come potrebbe apparire il primo round:

    C 50 50 50 50 50
    R 50 50 50 50 50
    
  • Scegli un numero casuale da 1 a 10 (inclusi sia 1 che 10). Chiameremo il numero N. Se Nè pari, i ladri perdono questo round; se strano, la polizia perde.

  • Scegli un membro a caso del team perdente il cui HP è maggiore di 0 e deduci NHP. Gli HP dei membri non dovrebbero mai apparire andare sotto lo 0 sullo stato.

  • Riavvia il ciclo.

Il gioco termina quando tutti i membri di una squadra perdono tutti i loro HP. Quindi, se i poliziotti vincono, verrà stampato quanto segue:

C+
R-

e se i ladri vincono:

R+
C-

Questo è il golf del codice, quindi vince il numero più breve di caratteri.

Ecco un'implementazione di esempio in 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+'

Minor ironia: su 3176+ domande su questo sito, non più di 11 sono taggate game-of-life.
Sanchises,

3
@sanchises Extended ironia: e 14 sono taggati cops-and-robbers!
Runer112,

@sanchises Mi riferivo in gran parte alla programmazione in generale (ad es. "Aiutami! Sto cercando di implementare Conway's Game of Life!") ... ma è ancora piuttosto ironico.
Kirbyfan64sos,

@ kirbyfan64sos Lo so (ci sono stato, l'ho fatto), ma questo è esattamente il tipo di sito in cui le persone vanno dopo aver implementato GoL e vogliono di più ... Comunque, forse ci proverò in> <> , vediamo se posso farlo.
Sanchises,

Ho rimosso di nuovo il tag CnR. Da queste parti, questo tag ha un significato molto specifico e descrive le sfide in cui in realtà ci sono due (non necessariamente disgiunte) parti in competizione tra loro in determinati compiti (dai un'occhiata alle altre sfide con quel tag).
Martin Ender,

Risposte:


3

CJam, 86 byte

Sono un po 'in ritardo alla festa, ma porto il regalo di CJam! ... Ehi aspetta, dove stai andando?

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

Provalo online.

Spiegazione

Poiché le domande chiedono di emulare un processo semplice, questa è una risposta relativamente semplice. Forse una scelta interessante che ho fatto è stata quella di mantenere la salute di entrambe le squadre intervallate nella stessa lista. Questo costa 3 byte per la conversione in due elenchi separati, necessari sia per la visualizzazione dello stato che per la verifica della perdita di un team. Ma (penso) questo è compensato dai 2 byte salvati nell'inizializzazione e da una logica molto più semplice per la gestione dei danni.

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.";

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

Anche perché l' rep(which(x>0),2)opposto di solo which(x>0)?
MickyT

1) Sto contando i personaggi EOL, non l'ultimo però. 2) sum(R*C)e sum(R)*sum(C)non sono la stessa cosa. Ad esempio, non vorrai uscire se C = c (0,0,0,10,10) e R = c (10, 10, 10, 0, 0). In tal caso, salvo assegnando S=sum. 3) Il problema sampleè che se il primo argomento è un singolo numero, ad esempio sample(5, 1), sarà lo stesso di fare sample(1:5, 1): invece di tornare sempre 5, restituirà qualsiasi numero da 1a 5. Quindi sample(rep(x, 2), 1)è il mio trucco per scegliere sempre un numero xanche nel caso in cui lo length(x)sia 1.
flodel

Scusa il mio cattivo ... Ovviamente non abbastanza caffè. Grazie per la spiegazione sul trucco rep (). Pensavo che ci fosse un motivo, non riuscivo a vederlo
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
∇

Spiegazione:

  • S←2 5⍴50: all'inizio, imposta Suna matrice 5 per 2 dove ogni valore è 50. La riga superiore della matrice rappresenta i poliziotti, la seconda riga rappresenta i ladri.
  • J←∨/S>0: per ogni riga della matrice, memorizzare Jse uno degli HP è maggiore di zero.
  • →6/⍨~∧/J: se non entrambe le squadre hanno membri vivi, passa alla linea 6. (fine)
  • ⎕←3↑'CR',0⌈S: per ogni valore nella matrice, genera il massimo e 0, anteponi una "C" alla prima riga e una "R" alla seconda e aggiungi una terza riga (vuota).
  • N←?10: ottieni un numero casuale nell'intervallo [1,10] e memorizzalo in N.
  • L←1+~2⊤N: imposta L(la squadra perdente) su 1se il numero era dispari e su 2se fosse pari.
  • M←(0<S[L... ;])/⍳5: ottieni gli indici dei membri viventi di quella squadra e conservaliM
  • M[?⍴M... ]: selezionare un valore casuale daM
  • S[L;M... ]-←N: sottrai Ndal valore del membro del team selezionato
  • →2: passa alla linea 2 (il test per i membri viventi)
  • ⎕←'CR',⍪'+-'⌽⍨J⍳0: mostra lo stato finale, mettendo +davanti alla squadra vincente e -davanti alla squadra perdente.

Uscita campione


1

Ruby, 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-'

1

Mathematica, 246 241 byte

Probabilmente potrebbe essere ulteriormente giocato a 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]

1

PHP - 416 byte

Sono nuovo nel golf e anche se questa sfida sarebbe abbastanza semplice da provare. Quindi ecco cosa mi è venuto in mente.

<?$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 spiegazione:

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

Non sono un utente PHP, ma immagino che forse avresti tagliato alcuni caratteri rimuovendo != 0e sostituendo il segno di spunta per essere uguale a zero con l'operatore non ( !array_sum($r)).
Kirbyfan64sos,

@ kirbyfan64sos che non funziona
Timo

Oh. Nella maggior parte delle lingue, sarebbe.
Kirbyfan64sos,

1

C, 390 384 371 byte

Il mio primo golf, se ci sono possibili miglioramenti, dimmelo :)

versione golfizzata:

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

versione un po 'non golfata:

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

modifica: ho trovato un modo per accorciarlo un po 'e ho corretto un piccolo bug


Un piccolo miglioramento: è possibile sostituire i loop (ad es. for(j=0;j<10;j++)) Con una versione più breve ( for(j=10;--j;)).
Kirbyfan64sos,

Hai perfettamente ragione, "risolto" questo e poche altre cose minori, grazie.
Metaforce

0

Lotto - 396 byte

Non so se questo conta tecnicamente, poiché in realtà non seleziona un membro casuale del team la cui salute sia maggiore di 0 . Seleziona solo un membro casuale e se la sottrazione dell'integrità genera un numero inferiore a 0, il numero diventa 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!-

Il requisito è che il valore non sia mai inferiore a 0 sullo stato stampato. Ho fatto la stessa cosa nell'esempio che ho mostrato.
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-')

0

Ottava, 182 177 158 145 byte

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

Ho rinunciato a controllare se il tiro del personaggio è sopra lo zero - questo sarebbe significativo solo se fossimo costretti a visualizzare lo stato in ogni turno - qui saltiamo casualmente un numero casuale da RNG, rendendolo più casuale.

Inoltre, sostituito

t=max(0,t)

con più corto

t.*=t>0


[nota: sta stampando 'C + R-' senza la nuova riga - è stato risolto nella versione da 145 byte]

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

Sono passato repmat(50,5,2)a repmat(5)- quindi ora abbiamo una matrice 5x5 anziché 5x2 (le 3 colonne aggiuntive non influiscono sull'algoritmo). Ho anche trovato un modo per comprimere l'output.

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

Fondamentalmente, creiamo una matrice 5x2, in cui la prima colonna sono poliziotti e la seconda colonna sono ladri:

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

La sumfunzione quando viene applicato un argomento fa una somma per colonne, quindi inizialmente:

250    250

Quando uno di essi raggiunge lo zero, viene prod(sum(t))valutato a zero interrompendo il ciclo. Quindi possiamo esaminare chi ha vinto controllando la cui colonna si somma a zero.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.