Policiais e ladrões

11

Todo mundo sempre quer implementar o Jogo da Vida de Conway. Isto é chato! Vamos fazer policiais e ladrões!

Você terá duas equipes: os policiais e os ladrões. Cada equipe tem 5 membros com 50 pontos de vida cada. O programa fará um loop contínuo. A cada iteração, ocorrerá o seguinte:

  • Para cada equipe, imprima a primeira carta ( Cpara os policiais, Rpara os assaltantes), um espaço, uma lista separada por espaços do HP dos membros e uma nova linha. Este é o status das equipes. Depois que os dois estiverem prontos, imprima outra nova linha. Por exemplo, eis a aparência da primeira rodada:

    C 50 50 50 50 50
    R 50 50 50 50 50
    
  • Escolha um número aleatório de 1 a 10 (incluindo 1 e 10). Vamos ligar para o número N. Se Nfor par, os ladrões perdem esta rodada; se estranho, a polícia perde.

  • Escolha um membro aleatório da equipe perdida cujo HP seja maior que 0 e deduza o NHP. O HP dos membros nunca deve aparecer abaixo de 0 no status.

  • Reinicie o loop.

O jogo termina quando todos os membros de uma equipe perdem todo o HP. Em seguida, o seguinte será impresso se os policiais vencerem:

C+
R-

e se os ladrões vencerem:

R+
C-

Isso é código de golfe, então o menor número de caracteres vence.

Aqui está uma implementação de exemplo no 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
fonte
Ironia menor: das 3176+ perguntas neste site, mais de 11 estão marcadas game-of-life.
Sanchises
3
@sanchises Ironia prolongada: e 14 estão marcadas cops-and-robbers!
precisa saber é o seguinte
@sanchises Eu estava me referindo amplamente à programação em geral (por exemplo, "Me ajude! Estou tentando implementar o Jogo da Vida de Conway!") ... mas isso ainda é bastante irônico.
precisa saber é o seguinte
@ kirbyfan64sos eu sei (já estive lá, fiz isso), mas esse é exatamente o tipo de site para onde as pessoas vão depois de implementarem o GoL e querem mais ... Enfim, talvez eu tente isso em> <> , vamos ver se consigo fazer isso.
Sanchises
Eu removi a tag CnR novamente. Por aqui, essa tag tem um significado muito específico e descreve os desafios em que na verdade existem duas partes (não necessariamente disjuntas) competindo entre si em determinadas tarefas (dê uma olhada nos outros desafios dessa tag).
Martin Ender

Respostas:

3

CJam, 86 bytes

Estou um pouco atrasado para a festa, mas trago o presente de CJam! ... Ei, espere, onde você está indo?

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

Experimente online.

Explicação

Como as perguntas pedem para imitar um processo direto, essa é uma resposta relativamente direta. Talvez uma escolha interessante que fiz foi manter a saúde de ambas as equipes intercaladas na mesma lista. Isso custa 3 bytes para converter em duas listas separadas, necessárias para a saúde exibir e verificar se uma equipe perdeu. Mas (eu acho) isso é compensado pelos 2 bytes salvos na inicialização e pela lógica muito mais simples de lidar com danos.

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
fonte
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)])
modelo
fonte
Também porque o rep(which(x>0),2)oposto de apenas which(x>0)?
MickyT
1) Estou contando os caracteres EOL, mas não o último. 2) sum(R*C)e sum(R)*sum(C)não são a mesma coisa. Por exemplo, você não gostaria de sair se C = c (0,0,0,10,10) e R = c (10, 10, 10, 0, 0). Nesse caso, eu salvo atribuindo S=sum. 3) O problema sampleé que, se o primeiro argumento for um único número, por exemplo sample(5, 1), será o mesmo que fazer sample(1:5, 1): em vez de sempre retornar 5, ele retornará qualquer número de 1para 5. Assim sample(rep(x, 2), 1)é o meu truque para sempre escolher um número, xmesmo no caso em que length(x)é 1.
usar o seguinte código
Desculpe meu mal ... Obviamente, não basta café. Obrigado pela explicação sobre o truque rep (). Eu pensei que deve haver uma razão, simplesmente não podia vê-lo
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
∇

Explicação:

  • S←2 5⍴50: no início, defina Suma matriz de 5 por 2, em que cada valor é 50. A linha superior da matriz representa os policiais, a segunda linha representa os ladrões.
  • J←∨/S>0: para cada linha da matriz, armazene Jse algum dos HPs é maior que zero.
  • →6/⍨~∧/J: se as duas equipes não tiverem membros vivos, pule para a linha 6. (final)
  • ⎕←3↑'CR',0⌈S: para cada valor na matriz, imprima o máximo e 0, coloque um 'C' na primeira linha e um 'R' na segunda e adicione uma terceira linha (vazia).
  • N←?10: obtenha um número aleatório no intervalo [1,10] e armazene-o N.
  • L←1+~2⊤N: defina L(o time perdedor) como 1se o número era ímpar e 2se era par.
  • M←(0<S[L... ;])/⍳5: obtenha os índices dos membros vivos dessa equipe e armazene-os emM
  • M[?⍴M... ]: selecione um valor aleatório deM
  • S[L;M... ]-←N: subtrair Ndo valor do membro da equipe selecionado
  • →2: pule para a linha 2 (o teste para membros vivos)
  • ⎕←'CR',⍪'+-'⌽⍨J⍳0: gera o status final, colocando +na frente da equipe vencedora e -na frente da equipe perdida.

Saída de amostra

marinus
fonte
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-'
histocrata
fonte
1

Mathematica, 246 241 bytes

Provavelmente poderia ser jogado ainda mais ...

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
fonte
1

PHP - 416 bytes

Sou novo no golfe e, embora esse desafio seja fácil o suficiente para testá-lo. Então aqui está o que eu criei.

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

Com explicação:

<? 
$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
fonte
Eu não sou usuário de PHP, mas acho que talvez você corte alguns caracteres removendo != 0e substituindo a verificação por ser igual a zero pelo operador not ( !array_sum($r)).
precisa saber é o seguinte
@ kirbyfan64sos isso não funcionar
Timo
Oh Na maioria dos idiomas, seria.
precisa saber é o seguinte
1

C, 390 384 371 bytes

Meu primeiro golfe, se houver alguma melhoria possível, é só me dizer :)

versão golfed:

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

versão um pouco não destruída:

#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: Encontrei uma maneira de encurtar um pouco e corrigi um pequeno bug

Metaforce
fonte
Uma pequena melhoria: você pode substituir os loops (por exemplo for(j=0;j<10;j++)) por uma versão mais curta ( for(j=10;--j;)).
precisa saber é o seguinte
Você está totalmente certo, "consertou" isso e algumas outras coisas menores, obrigado.
Metaforce
0

Lote - 396 bytes

Não sei se isso conta tecnicamente - pois, na verdade, ele não seleciona um membro aleatório da equipe cuja saúde é maior que 0 . Apenas seleciona um membro aleatório e, se a subtração de integridade gerar um número menor que 0, o número se tornará 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!-
desgrudar
fonte
O requisito é que o valor nunca seja exibido abaixo de 0 no status impresso. Eu fiz a mesma coisa no exemplo que mostrei.
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
fonte
0

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

Eu desisti de checar se o tiro do personagem está acima de zero - isso só seria significativo se fôssemos forçados a exibir o estado em cada turno - aqui estamos pulando aleatoriamente um número aleatório do RNG, tornando-o mais aleatório.

Além disso, substituiu

t=max(0,t)

com mais curto

t.*=t>0


[note - está imprimindo 'C + R-' sem a nova linha - está corrigido na versão 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))

Degolfado:

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

Eu mudei repmat(50,5,2)para repmat(5)- então temos matriz 5x5 em vez de 5x2 agora (as 3 colunas adicionais não afetam o algoritmo). Eu também encontrei uma maneira de comprimir a saída.

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

Degolfado:

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

Basicamente, criamos uma matriz 5x2, em que a primeira coluna é policial e a segunda coluna é ladrão:

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

A sumfunção quando um argumento aplicado faz uma soma por colunas, portanto é inicialmente:

250    250

Quando um deles chega a zero, o valor é prod(sum(t))zero, interrompendo o loop. Depois, podemos examinar quem ganhou a verificação de cuja coluna é igual a zero.

pawel.boczarski
fonte