Polizei und Räuber

11

Jeder möchte immer Conways Spiel des Lebens implementieren. Das ist langweilig! Lassen Sie uns stattdessen Polizisten und Räuber machen!

Sie haben zwei Teams: die Bullen und die Räuber. Jedes Team hat 5 Mitglieder mit jeweils 50 Gesundheit. Das Programm wird kontinuierlich wiederholt. Bei jeder Iteration wird Folgendes ausgeführt:

  • Drucken Sie für jedes Team den ersten Buchstaben ( Cfür die Polizei, Rfür die Räuber), ein Leerzeichen, eine durch Leerzeichen getrennte Liste der HP der Mitglieder und eine neue Zeile. Dies ist der Status der Teams. Nachdem beide erledigt sind, drucken Sie eine weitere Zeile. So könnte es beispielsweise in der ersten Runde aussehen:

    C 50 50 50 50 50
    R 50 50 50 50 50
    
  • Wählen Sie eine Zufallszahl von 1 bis 10 (einschließlich 1 und 10). Wir rufen die Nummer an N. Wenn Nes gerade ist, verlieren die Räuber diese Runde; Wenn es seltsam ist, verlieren die Bullen.

  • Wählen Sie ein zufälliges Mitglied des verlierenden Teams aus, dessen HP größer als 0 sind, und ziehen Sie die NHP ab. Die HP der Mitglieder sollten im Status niemals unter 0 fallen.

  • Starten Sie die Schleife neu.

Das Spiel endet, wenn alle Mitglieder eines Teams alle HP verlieren. Dann wird Folgendes gedruckt, wenn die Polizei gewinnt:

C+
R-

und wenn die Räuber gewinnen:

R+
C-

Dies ist Code Golf, also gewinnt die kürzeste Anzahl von Charakteren.

Hier ist eine Beispielimplementierung 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+'
kirbyfan64sos
quelle
Kleinere Ironie: Von den über 3176 Fragen auf dieser Website sind nicht mehr als 11 markiert game-of-life.
Sanchises
3
@sanchises Erweiterte Ironie: und 14 sind markiert cops-and-robbers!
Runer112
@sanchises Ich bezog mich hauptsächlich auf die Programmierung im Allgemeinen (z. B. "Hilf mir! Ich versuche, Conways Spiel des Lebens zu implementieren!") ... aber das ist immer noch ziemlich ironisch.
kirbyfan64sos
@ kirbyfan64sos Ich weiß (war dort, habe das getan), aber dies ist genau die Art von Site, auf die Leute gehen, nachdem sie GoL implementiert haben und mehr wollen ... Wie auch immer, vielleicht werde ich es in> <> versuchen Mal sehen, ob ich das kann.
Sanchises
Ich habe das CnR-Tag wieder entfernt. Hier hat dieses Tag eine sehr spezifische Bedeutung und beschreibt Herausforderungen, bei denen tatsächlich zwei (nicht unbedingt disjunkte) Parteien bei bestimmten Aufgaben gegeneinander antreten (sehen Sie sich die anderen Herausforderungen mit diesem Tag an).
Martin Ender

Antworten:

3

CJam, 86 Bytes

Ich bin etwas spät zur Party, aber ich bringe das Geschenk von CJam! ... Hey warte, wohin gehst du?

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

Probieren Sie es online aus.

Erläuterung

Da die Fragen einen einfachen Prozess nachahmen sollen, ist dies eine relativ einfache Antwort. Vielleicht war eine interessante Entscheidung, die ich getroffen habe, die Gesundheit beider Teams in derselben Liste zu verankern. Die Konvertierung in zwei separate Listen kostet 3 Byte. Dies wird sowohl für die Anzeige des Zustands als auch für die Überprüfung, ob ein Team verloren hat, benötigt. Aber (ich denke) dies wird durch die 2 Bytes ausgeglichen, die bei der Initialisierung eingespart wurden, und durch eine viel einfachere Logik, die Schaden verursacht.

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
quelle
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
quelle
Auch warum die rep(which(x>0),2)im Gegensatz zu nur which(x>0)?
MickyT
1) Ich zähle die EOL-Zeichen, aber nicht die letzten. 2) sum(R*C)und sum(R)*sum(C)sind nicht dasselbe. Zum Beispiel möchten Sie nicht beenden, wenn C = c (0,0,0,10,10) und R = c (10, 10, 10, 0, 0). In diesem Fall speichere ich durch Zuweisen S=sum. 3) Das Problem dabei sampleist, dass wenn das erste Argument eine einzelne Zahl ist, z. B. sample(5, 1)dasselbe wie folgt sample(1:5, 1): Anstatt immer zurückzukehren 5, wird eine beliebige Zahl von 1bis zurückgegeben 5. So sample(rep(x, 2), 1)ist mein Trick, immer eine Zahl unter zu wählen, xselbst wenn es so length(x)ist 1.
Flodel
Tut mir leid, mein schlechtes ... Offensichtlich nicht genug Kaffee. Vielen Dank für die Erklärung zum Trick rep (). Ich dachte, es muss einen Grund geben, konnte es einfach nicht sehen
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
∇

Erläuterung:

  • S←2 5⍴50: Stellen Sie zu Beginn Seine 5-mal-2-Matrix ein, in der jeder Wert 50 beträgt. Die oberste Zeile der Matrix repräsentiert die Bullen, die zweite Reihe die Räuber.
  • J←∨/S>0: Speichern Sie für jede Zeile der Matrix, Job eine der HP größer als Null ist.
  • →6/⍨~∧/J: Wenn nicht beide Teams lebende Mitglieder haben, springe zu Zeile 6. (Ende)
  • ⎕←3↑'CR',0⌈S: Geben Sie für jeden Wert in der Matrix das Maximum und 0 aus, stellen Sie der ersten Zeile ein 'C' und der zweiten ein 'R' voran und fügen Sie eine dritte (leere) Zeile hinzu.
  • N←?10: Holen Sie sich eine Zufallszahl im Intervall [1,10] und speichern Sie sie in N.
  • L←1+~2⊤N: setze L(das verlierende Team) auf, 1ob die Zahl ungerade und 2ob sie gerade war.
  • M←(0<S[L... ;])/⍳5: Holen Sie sich die Indizes der lebenden Mitglieder dieses Teams und speichern Sie sie inM
  • M[?⍴M... ]: Wählen Sie einen zufälligen Wert ausM
  • S[L;M... ]-←N: Nvom Wert des ausgewählten Teammitglieds abziehen
  • →2: Springe zu Zeile 2 (der Test für lebende Mitglieder)
  • ⎕←'CR',⍪'+-'⌽⍨J⍳0: Geben Sie den endgültigen Status aus und stellen Sie ihn +vor das Gewinnerteam und -vor das Verliererteam.

Beispielausgabe

Marinus
quelle
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
quelle
1

Mathematica, 246 241 Bytes

Könnte wahrscheinlich weiter Golf gespielt werden ...

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

PHP - 416 Bytes

Ich bin neu im Golfen und obwohl diese Herausforderung einfach genug wäre, um sie auszuprobieren. Also hier ist, was ich mir ausgedacht habe.

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

Mit Erklärung:

<? 
$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
quelle
Ich bin kein PHP-Benutzer, aber ich würde vermuten, dass Sie ein paar Zeichen sparen würden, != 0indem Sie die Prüfung auf Null durch den Operator not ( !array_sum($r)) entfernen und ersetzen .
kirbyfan64sos
@ kirbyfan64sos das funktioniert nicht
Timo
Oh. In den meisten Sprachen würde es.
kirbyfan64sos
1

C 390 384 371 Bytes

Mein erster Golf, wenn es irgendwelche möglichen Verbesserungen gibt, sag es mir einfach :)

Golfversion:

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

etwas ungolfed Version:

#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: Ich habe einen Weg gefunden, es ein wenig zu verkürzen und einen kleinen Fehler behoben

Metaforce
quelle
Eine kleine Verbesserung: Sie können Loops (zB for(j=0;j<10;j++)) durch eine kürzere Version ( for(j=10;--j;)) ersetzen .
kirbyfan64sos
Sie haben völlig Recht, "behoben" dies und ein paar kleinere andere Dinge, danke.
Metaforce
0

Stapel - 396 Bytes

Ich weiß nicht, ob dies technisch zählt - da es kein zufälliges Mitglied des Teams auswählt , dessen Gesundheit größer als 0 ist . Es wird nur ein zufälliges Mitglied ausgewählt. Wenn die Gesundheitssubtraktion eine Zahl kleiner als 0 generiert, wird die Zahl zu 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!-
unclemeat
quelle
Voraussetzung ist, dass der Wert im gedruckten Status niemals unter 0 angezeigt wird. In dem Beispiel, das ich gezeigt habe, habe ich dasselbe getan.
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-')
Logik8
quelle
0

Oktave, 182 177 158 145 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,:)

Ich habe es aufgegeben zu überprüfen, ob die Charakteraufnahme über Null liegt - dies wäre nur dann von Bedeutung, wenn wir gezwungen wären, den Status in jeder Runde anzuzeigen - hier überspringen wir nur zufällig eine Zufallszahl aus RNG, um sie zufälliger zu machen.

Auch ersetzt

t=max(0,t)

mit kürzeren

t.*=t>0


[Hinweis - es wird 'C + R-' ohne den Zeilenumbruch gedruckt - es ist in der 145-Byte-Version behoben]

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

Ich habe repmat(50,5,2)zu repmat(5)- also haben wir jetzt eine 5x5-Matrix anstelle von 5x2 (die zusätzlichen 3 Spalten haben keinen Einfluss auf den Algorithmus). Ich habe auch einen Weg gefunden, die Ausgabe zu komprimieren.

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

Grundsätzlich erstellen wir eine 5x2-Matrix, in der die erste Spalte Polizisten und die zweite Spalte Räuber sind:

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

Die sumFunktion, wenn ein Argument angewendet wird, ergibt eine Summe aus Spalten.

250    250

Wenn einer von ihnen Null erreicht, ergibt der prod(sum(t))Wert Null, wodurch die Schleife unterbrochen wird. Dann können wir untersuchen, wer gewonnen hat und wessen Spalte auf Null summiert.

pawel.boczarski
quelle