Polisler ve soyguncular


11

Herkes her zaman Conway'in Hayat Oyununu uygulamak ister. Bu sıkıcı! Bunun yerine polisler ve soyguncular yapalım!

İki ekibiniz olacak: polisler ve soyguncular. Her takımın her biri 50 sağlık olan 5 üyesi vardır. Program sürekli olarak dönecektir. Her yineleme, aşağıdakiler gerçekleşir:

  • Her takım için ilk harfi ( Cpolisler, Rsoyguncular için), bir boşluk, üyelerin HP'nin boşlukla ayrılmış bir listesini ve bir yeni satır yazdırın. Bu takımların statüsüdür. Her ikisi de yapıldıktan sonra başka bir satır yazdırın. Örneğin, ilk tur gibi görünebilir:

    C 50 50 50 50 50
    R 50 50 50 50 50
    
  • 1'den 10'a kadar rastgele bir sayı seçin (hem 1 hem de 10 dahil). Numarayı arayacağız N. Eğer Nhatta olduğunu soyguncular bu raundu kaybetmek; eğer garipse, polisler kaybeder.

  • HP'si 0'dan büyük olan kaybeden ekibin rastgele bir üyesini seçin ve HP'yi kesin N. Üyelerin HP durumu hakkında hiçbir zaman 0'ın altına inmemelidir.

  • Döngüyü yeniden başlatın.

Oyun, bir takımın tüm üyeleri tüm HP'lerini kaybettiğinde sona erer. Daha sonra polisler kazanırsa aşağıdakiler yazdırılır:

C+
R-

ve soyguncular kazanırsa:

R+
C-

Bu kod golf, bu yüzden en kısa karakter sayısı kazanır.

Python 2'de örnek bir uygulama:

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+'

Küçük ironi: Bu sitedeki 3176+ sorudan en fazla 11 tanesi etiketlenmiştir game-of-life.
Sanchises

3
@sanchises Genişletilmiş ironi: ve 14 etiketlendi cops-and-robbers!
Runer112

@ sanchises Genel olarak programlamadan bahsediyordum (örn. "Yardım et! Conway'in Yaşam Oyunu'nu uygulamaya çalışıyorum!") ... ama bu hala oldukça ironik.
kirbyfan64sos

@ kirbyfan64sos Biliyorum (orada bulundum, bunu yaptım), ama bu tam olarak insanların GoL'yi uyguladıktan ve daha fazlasını istedikten sonra gittikleri bir site ... Her neyse, belki de bu konuda> <> Bakalım bunu yapabilir miyim.
Sanchises

CnR etiketini tekrar kaldırdım. Buralarda, bu etiket çok özel bir anlama sahiptir ve belirli görevlerde birbiriyle yarışan iki (mutlaka ayrık olmayan) partilerin olduğu zorlukları açıklar (bu etiketle ilgili diğer zorluklara bir göz atın).
Martin Ender

Yanıtlar:


3

CJam, 86 bayt

Partiye biraz geç kaldım ama CJam'ın hediyesini getirdim! ... Hey bekle, nereye gidiyorsun?

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

Çevrimiçi deneyin.

açıklama

Sorular basit bir süreci taklit etmeyi istediği için, bu nispeten basit bir cevaptır. Belki de ilginç bir seçim yaptığım her iki takımın sağlığını aynı listeye dahil etmekti. Bu, iki ayrı listeye dönüştürmek için 3 bayta mal oluyor, bu da bir ekibin kaybedilip kaybedilmediğini kontrol etmek için gerekli. Ancak (sanırım) bu başlatma sırasında kaydedilen 2 bayt ve çok daha basit hasar veren mantık tarafından yapılır.

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

Ayrıca neden tam rep(which(x>0),2)tersine which(x>0)?
MickyT

1) EOL karakterlerini sayıyorum, sonuncusu değil. 2) sum(R*C)ve sum(R)*sum(C)aynı şey değildir. Örneğin, C = c (0,0,0,10,10) ve R = c (10, 10, 10, 0, 0) ise çıkmak istemezsiniz. Bu durumda, atayarak kaydederim S=sum. 3) ile sorun sampleilk argüman tek sayı, örneğin eğer olmasıdır sample(5, 1), o zaman yapıyor aynı olacaktır sample(1:5, 1)yerine hep döndürmek: 5bu arasında bir sayı döndürür 1için 5. Yani sample(rep(x, 2), 1)her zaman arasında bir sayı seçmek için benim hiledir xbile durumda length(x)olduğunu 1.
flodel

Üzgünüm kötü ... Açıkçası yeterli kahve yok. Rep () numarasındaki açıklama için teşekkürler. Bir sebep olması gerektiğini düşündüm, sadece göremedim
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
∇

Açıklama:

  • S←2 5⍴50: başlangıçta, Sher bir değerin 50 olduğu 5'e 2 matris olarak ayarlanır . Matrisin üst sırası polisleri, ikinci sıra soyguncuları temsil eder.
  • J←∨/S>0: matrisin her satırı için J, HP'lerden herhangi birinin sıfırdan büyük olup olmadığını saklayın .
  • →6/⍨~∧/J: her iki takımın da yaşayan üyeleri yoksa 6. satıra atlayın. (son)
  • ⎕←3↑'CR',0⌈S: matristeki her değer için, en yüksek değeri ve 0 değerini girin, ilk satıra bir 'C', ikincisine bir 'R' ekleyin ve üçüncü (boş) bir satır ekleyin.
  • N←?10: [1,10] aralığında rastgele bir sayı al ve sakla N.
  • L←1+~2⊤N: sayının tek olup olmadığını ve çift olup olmadığını L(kaybeden takım) olarak ayarlayın .12
  • M←(0<S[L... ;])/⍳5: ekibin yaşayan üyelerinin endekslerini alıp,M
  • M[?⍴M... ]: 'dan rastgele bir değer seçM
  • S[L;M... ]-←N: Nseçilen ekip üyesinin değerinden çıkar
  • →2: 2. satıra atla (canlı üyeler için test)
  • ⎕←'CR',⍪'+-'⌽⍨J⍳0: +kazanan takımın -önüne ve kaybeden takımın önüne koyarak final statüsünü çıkar .

Örnek çıktı


1

Yakut, 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 bayt

Muhtemelen daha fazla golf olabilir ...

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 bayt

Golf için yeniyim ve bu meydan okuma denemek için yeterince kolay olsa da. İşte benim ortaya koyduğum şey.

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

Açıklama ile:

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

Ben bir PHP kullanıcısı değilim, ama != 0sıfıra eşit olup olmadığını kontrol operatörü ( !array_sum($r)) ile değiştirerek ve değiştirerek belki birkaç karakter kesmek olacağını tahmin ediyorum .
kirbyfan64sos

@ kirbyfan64sos çalışmıyor
Timo

Ah. Çoğu dilde, olurdu.
kirbyfan64sos

1

Cı, 390 384 371 bayt

İlk golfüm, olası iyileştirmeler varsa, bana söyle :)

golf versiyonu:

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

biraz ungolfed versiyonu:

#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: Ben biraz kısaltmak için bir yol buldum ve küçük bir hata düzeltildi


Küçük bir gelişme: döngüleri (örn. for(j=0;j<10;j++)) Daha kısa bir sürümle ( for(j=10;--j;)) değiştirebilirsiniz.
kirbyfan64sos

Tamamen haklısın, bunu "düzeltti" ve birkaç küçük şey daha, teşekkürler.
Metaforce

0

Toplu İşlem - 396 Bayt

Bunun teknik olarak önemli olup olmadığını bilmiyorum - aslında sağlığın 0'dan büyük olduğu takımın rastgele bir üyesini seçmediğinden . Sadece rastgele bir üye seçer ve sağlık çıkarma işlemi 0'dan küçük bir sayı üretirse sayı 0 olur.

@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!-

Gereksinim, değerin basılı durumda hiçbir zaman 0'ın altında gösterilmemesidir. Gösterdiğim örnekte de aynı şeyi yaptım.
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

Oktav, 182177157145 bayt

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

Karakter çekiminin sıfırın üstünde olup olmadığını kontrol etmeyi bıraktım - bu sadece her dönüşte durumu göstermek zorunda kalsaydık önemli olurdu - burada RNG'den rastgele bir sayıyı rastgele atlıyoruz ve daha rasgele hale getiriyoruz.

Ayrıca,

t=max(0,t)

daha kısa ile

t.*=t>0


[not - yeni satır olmadan 'C + R-' yazdırıyor - 145 baytlık sürümde düzeltildi]

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

Değiştim repmat(50,5,2)için repmat(5)- Şimdi yerine 5x2 ait 5x5 matrisi var bu yüzden (ek 3 sütun algoritması etkilemez). Çıktıyı sıkıştırmanın bir yolunu da buldum.

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

Temel olarak, ilk sütunun polisler ve ikinci sütunun soyguncular olduğu 5x2'lik bir matris oluşturuyoruz:

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

sumBaşlangıçta bu yüzden bir argüman uygulanan fonksiyon, sütunlarla bir miktar yapar:

250    250

Bunlardan biri sıfıra ulaştığında prod(sum(t)), döngüyü kırarak sıfır olarak değerlendirilir. Sonra kimin sütun toplamını sıfıra kontrol ettiğini kimin kazandığını inceleyebiliriz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.