Polisi dan pencuri

11

Semua orang selalu ingin menerapkan Game of Conway's Life. Itu membosankan! Mari kita lakukan polisi dan perampok sebagai gantinya!

Anda akan memiliki dua tim: polisi dan perampok. Setiap tim memiliki 5 anggota dengan masing-masing 50 kesehatan. Program akan berulang terus menerus. Setiap iterasi, berikut ini akan terjadi:

  • Untuk setiap tim, cetak huruf pertama ( Cuntuk polisi, Runtuk perampok), spasi, daftar HP anggota yang dipisahkan spasi, dan baris baru. Ini adalah status tim. Setelah keduanya selesai, cetak baris baru lainnya. Misalnya, inilah yang kelihatannya seperti babak pertama:

    C 50 50 50 50 50
    R 50 50 50 50 50
    
  • Pilih angka acak dari 1 hingga 10 (termasuk 1 dan 10). Kami akan memanggil nomornya N. Jika Nbahkan, perampok kehilangan putaran ini; jika aneh, polisi kalah.

  • Pilih anggota acak dari tim yang kalah yang HP-nya lebih besar dari 0 dan kurangi NHP. HP anggota tidak boleh muncul di bawah 0 pada status.

  • Mulai ulang loop.

Permainan berakhir ketika semua anggota satu tim kehilangan semua HP mereka. Kemudian, yang berikut ini akan dicetak jika polisi menang:

C+
R-

dan jika perampok menang:

R+
C-

Ini adalah kode golf, sehingga jumlah karakter terpendek menang.

Berikut ini contoh implementasi dalam 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
sumber
Ironi kecil: dari 3176+ pertanyaan di situs ini, tidak lebih dari 11 yang ditandai game-of-life.
Sanchises
3
@sanchises Extended irony: dan 14 ditandai cops-and-robbers!
Runer112
@sanchises Saya sebagian besar mengacu pada pemrograman secara umum (misalnya, "Tolong saya! Saya mencoba menerapkan Permainan Kehidupan Conway!") ... tapi itu masih sangat ironis.
kirbyfan64sos
@ kirbyfan64sos Saya tahu (pernah ke sana, melakukan itu), tapi ini adalah jenis situs tempat orang-orang pergi setelah mereka menerapkan GoL dan ingin lebih ... Pokoknya, mungkin saya akan mencoba ini di> <> , mari kita lihat apakah saya bisa melakukan itu.
Sanchises
Saya telah menghapus tag CnR lagi. Di sekitar sini, tag ini memiliki makna yang sangat spesifik dan menggambarkan tantangan di mana sebenarnya ada dua (tidak harus terpisah) pihak yang bersaing satu sama lain pada tugas tertentu (lihat tantangan lain dengan tag itu).
Martin Ender

Jawaban:

3

CJam, 86 byte

Saya agak terlambat ke pesta, tapi saya membawa hadiah CJam! ... Hei tunggu, kemana kamu akan pergi?

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

Cobalah online.

Penjelasan

Ketika pertanyaan ditanyakan untuk meniru proses langsung, ini adalah jawaban yang relatif langsung. Mungkin satu pilihan menarik yang saya buat adalah menjaga kesehatan kedua tim yang disisipkan dalam daftar yang sama. Biaya ini 3 byte untuk dikonversi ke dua daftar terpisah, yang diperlukan untuk menampilkan kesehatan dan memeriksa apakah tim telah hilang. Tapi (saya pikir) ini dibuat oleh 2 byte yang disimpan dalam inisialisasi dan logika kerusakan-berurusan jauh lebih sederhana.

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
sumber
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
sumber
Juga mengapa yang rep(which(x>0),2)bertentangan dengan adil which(x>0)?
MickyT
1) Saya menghitung karakter EOL, bukan yang terakhir. 2) sum(R*C)dan sum(R)*sum(C)bukan hal yang sama. Misalnya, Anda tidak ingin keluar jika C = c (0,0,0,10,10) dan R = c (10, 10, 10, 0, 0). Dalam hal ini, saya menyimpan dengan menetapkan S=sum. 3) Masalahnya sampleadalah bahwa jika argumen pertama adalah angka tunggal, misalnya sample(5, 1), maka itu akan sama dengan melakukan sample(1:5, 1): alih-alih selalu kembali 5, itu akan mengembalikan nomor dari 1ke 5. Jadi sample(rep(x, 2), 1)trik saya untuk selalu memilih nomor kalangan xbahkan dalam kasus ketika length(x)adalah 1.
flodel
Maaf saya buruk ... Jelas tidak cukup kopi. Terima kasih atas penjelasannya pada trik rep (). Saya pikir pasti ada alasan, tidak bisa melihatnya
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
∇

Penjelasan:

  • S←2 5⍴50: pada awalnya, atur Ske matriks 5-by-2 dengan nilai masing-masing adalah 50. Baris atas matriks mewakili polisi, baris kedua mewakili perampok.
  • J←∨/S>0: untuk setiap baris matriks, simpan Japakah salah satu HP lebih besar dari nol.
  • →6/⍨~∧/J: jika tidak kedua tim memiliki anggota yang masih hidup, lompat ke baris 6. (akhir)
  • ⎕←3↑'CR',0⌈S: untuk setiap nilai dalam matriks, hasilkan nilai maksimumnya dan 0, tambahkan 'C' ke baris pertama dan 'R' ke baris kedua, dan tambahkan baris ketiga (kosong).
  • N←?10: dapatkan nomor acak dalam interval [1,10] dan simpan di N.
  • L←1+~2⊤N: set L(tim yang kalah) untuk 1apakah nomor itu ganjil dan 2jika itu genap.
  • M←(0<S[L... ;])/⍳5: dapatkan indeks anggota yang masih hidup dari tim itu, dan simpan diM
  • M[?⍴M... ]: pilih nilai acak dariM
  • S[L;M... ]-←N: kurangi Ndari nilai anggota tim yang dipilih
  • →2: lompat ke baris 2 (ujian untuk anggota yang masih hidup)
  • ⎕←'CR',⍪'+-'⌽⍨J⍳0: output status akhir, menempatkan +di depan tim yang menang dan -di depan tim yang kalah.

Output sampel

marinus
sumber
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-'
histokrat
sumber
1

Mathematica, 246 241 byte

Mungkin bisa bermain golf lebih lanjut ...

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

PHP - 416 byte

Saya baru bermain golf dan meskipun tantangan ini akan cukup mudah untuk mencobanya. Jadi inilah yang saya pikirkan.

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

Dengan penjelasan:

<? 
$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
sumber
Saya bukan pengguna PHP, tapi saya rasa mungkin Anda akan memotong beberapa karakter dengan menghapus != 0dan mengganti cek menjadi sama dengan nol dengan operator yang tidak ( !array_sum($r)).
kirbyfan64sos
@ kirbyfan64sos yang tidak berfungsi
Timo
Oh Dalam sebagian besar bahasa, itu akan terjadi.
kirbyfan64sos
1

C, 390 384 371 byte

Golf pertama saya, jika ada peningkatan yang mungkin, katakan saja kepada saya :)

versi 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 yang agak tidak bercabang:

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

sunting: Saya menemukan cara untuk mempersingkat sedikit dan memperbaiki bug kecil

Metaforce
sumber
Peningkatan kecil: Anda dapat mengganti loop (misalnya for(j=0;j<10;j++)) dengan versi yang lebih pendek ( for(j=10;--j;)).
kirbyfan64sos
Anda sepenuhnya benar, "memperbaiki" ini dan beberapa hal kecil lainnya, terima kasih.
Metaforce
0

Batch - 396 Bytes

Saya tidak tahu apakah ini secara teknis diperhitungkan - karena tidak benar-benar memilih anggota acak tim yang kesehatannya lebih besar dari 0 . Itu hanya memilih anggota acak, dan jika pengurangan kesehatan menghasilkan angka kurang dari 0, maka jumlahnya menjadi 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!-
hapus clemeat
sumber
Syaratnya adalah bahwa nilai tidak pernah menunjukkan di bawah 0 pada status cetak. Saya melakukan hal yang sama pada contoh yang saya tunjukkan.
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
sumber
0

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

Saya menyerah memeriksa apakah pemotretan karakter di atas nol - ini hanya akan signifikan jika kami dipaksa untuk menampilkan keadaan di setiap belokan - di sini kami hanya secara acak melewatkan satu nomor acak dari RNG, menjadikannya lebih acak.

Juga diganti

t=max(0,t)

dengan lebih pendek

t.*=t>0


[note - ini mencetak 'C + R-' tanpa baris baru - ini diperbaiki dalam versi 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))

Saya berubah repmat(50,5,2)menjadi repmat(5)- jadi kami memiliki matriks 5x5 dan bukan 5x2 sekarang (3 kolom tambahan tidak memengaruhi algoritme). Saya juga menemukan cara untuk mengompresi 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

Pada dasarnya, kami membuat matriks 5x2, di mana kolom pertama adalah polisi dan kolom kedua adalah perampok:

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

The sumberfungsi bila satu argumen diterapkan membuat sum dengan kolom, jadi awalnya:

250    250

Ketika salah satu dari mereka mencapai nol, prod(sum(t))evaluasi ke nol melanggar loop. Lalu kita bisa memeriksa siapa yang menang memeriksa kolom yang jumlahnya nol.

pawel.boczarski
sumber