警官と強盗


11

誰もがConwayのGame of Lifeを常に実装したいと考えています。つまらない!代わりに警官と強盗をしましょう!

警官と強盗の2つのチームがあります。各チームには、それぞれ50のヘルスを持つ5人のメンバーがいます。プログラムは継続的にループします。各反復で、次のことが発生します。

  • チームごとに、最初の文字(C警官、R強盗)、スペース、スペースで区切られたメンバーのHPのリスト、および改行を印刷します。これがチームのステータスです。両方が完了したら、別の改行を印刷します。たとえば、最初のラウンドのように見えるものは次のとおりです。

    C 50 50 50 50 50
    R 50 50 50 50 50
    
  • 1〜10の乱数(1と10の両方を含む)を選択します。番号を呼び出しますN。N偶数であれば、強盗はこのラウンドを失います。奇数の場合、警官は負けます。

  • HPが0より大きい負けたチームのメンバーをランダムに選び、NHP を差し引く。メンバーのHPはステータスで0を下回ってはなりません。

  • ループを再開します。

1つのチームのすべてのメンバーがHPをすべて失うと、ゲームは終了します。その後、警官が勝った場合、次のように出力されます:

C+
R-

そして強盗が勝った場合:

R+
C-

これはコードゴルフであるため、最短のキャラクターが勝ちます。

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

軽度の皮肉:このサイトの3176以上の質問のうち、タグ付けされてgame-of-lifeいるのは11個までです。
— -Sanchises

3
@sanchises Extended irony:と14がタグ付けされていcops-and-robbersます!
— Runer112

@sanchises私は主にプログラミング全般について言及していました(例えば、「助けて!私はConwayのGame of Lifeを実装しようとしています!」)...しかし、それはまだかなり皮肉です。
— kirbyfan64sos

kirbyfan64sos @私は(、があったことを行って)知っているが、これはまさに、人々が行くサイトの一種である後、彼らはラオス政府を実装して欲しいましたより多くの、おそらく私は> <>でこれをやってみるよ、とにかく... 、それができるかどうか見てみましょう。
— -Sanchises

CnRタグを再度削除しました。ここでは、このタグには非常に具体的な意味があり、特定のタスクで実際に競合する(必ずしもばらばらではない)2つのパーティが存在する課題について説明します(そのタグに関する他の課題について見てみましょう)。
— マーティンエンダー

回答:


3

CJam、86バイト

私はパーティーに少し遅れましたが、CJamの贈り物を持っています!...ちょっと待って、どこに行くの?

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

オンラインでお試しください。

説明

質問は簡単なプロセスをエミュレートするように求めているため、これは比較的簡単な答えです。おそらく、私が行った興味深い選択の1つは、同じリストにインターリーブされた両方のチームの健全性を保持することでした。これは、2つの個別のリストに変換するのに3バイトかかります。これは、ヘルスの表示とチームが負けたかどうかの確認の両方に必要です。ただし、これは、初期化で保存された2バイトと、はるかに単純な損傷処理ロジックによって補われています。

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

また、なぜrep(which(x>0),2)単に反対which(x>0)ですか?
— MickyT

1)最後の文字ではなく、EOL文字を数えています。2)sum(R*C)とsum(R)*sum(C)同じものではありません。たとえば、C = c(0,0,0,10,10)およびR = c(10、10、10、0、0)の場合は終了しません。その場合、を割り当てて保存しS=sumます。3)問題sampleは、最初の引数が単一の数値である場合、たとえばsample(5, 1)次のようになることsample(1:5, 1)です。常に返すの5ではなく、1to から任意の数値を返すということ5です。だから、sample(rep(x, 2), 1)いつもの間で番号を選ぶための私のトリックであるx場合でも場合にはlength(x)あるが1。
— flodel

申し訳ありませんが私の悪い...明らかにコーヒーが足りません。rep()トリックの説明をありがとう。理由があるに違いないと思った、それを見ることができなかった
— -MickyT

2

APL(ダイアログ)(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
∇

説明:

  • S←2 5⍴50:最初は、S各値が50である5行2列の行列に設定します。行列の一番上の行は警官を表し、2番目の行は強盗を表します。
  • J←∨/S>0:行列の各行についてJ、HPのいずれかがゼロより大きいかどうかを格納します。
  • →6/⍨~∧/J:両方のチームに生きているメンバーがいない場合、6行目にジャンプします(終了)
  • ⎕←3↑'CR',0⌈S:マトリックスの各値について、最大値と0を出力し、最初の行に「C」を追加し、2番目に「R」を追加し、3番目の(空の)行を追加します。
  • N←?10:間隔[1,10]で乱数を取得し、に保存しNます。
  • L←1+~2⊤N:番号が奇​​数の場合と偶数の場合に設定しますL(負けたチーム)。12
  • M←(0<S[L... ;])/⍳5:そのチームの生きているメンバーのインデックスを取得し、保存しますM
  • M[?⍴M... ]:からランダムな値を選択しますM
  • S[L;M... ]-←N:N選択したチームメンバーの値から減算します
  • →2:2行目にジャンプ(生きているメンバーのテスト)
  • ⎕←'CR',⍪'+-'⌽⍨J⍳0:最終ステータスを出力し+、勝ったチームの-前と負けたチームの前に配置します。

サンプル出力


1

ルビー、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バイト

おそらくさらにゴルフをすることができます...

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バイト

私はゴルフを始めたばかりで、この挑戦​​はそれを試すのに十分簡単でしょうが。だからここに私が思いついたものがあります。

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

説明付き:

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

私はPHPのユーザーではありませんが、!= 0ゼロに等しいチェックをnot演算子(!array_sum($r))で削除および置換することにより、いくつかの文字を削減できると思います。
— kirbyfan64sos

動作しない@ kirbyfan64sos
— ティモ

ああ。ほとんどの言語でそうなります。
— kirbyfan64sos

1

C、390の 384 371バイト

私の最初のゴルフ、可能な改善があれば、教えてください:)

ゴルフバージョン:

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

やや手付かずのバージョン:

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

編集:私はそれを少し短くする方法を見つけ、小さなバグを修正しました


小さな改善:ループ(例えばfor(j=0;j<10;j++))をより短いバージョン(for(j=10;--j;))に置き換えることができます。
— kirbyfan64sos

あなたは完全に正しい、これといくつかの小さな他のことを「修正」、ありがとう。
— メタフォース

0

バッチ-396バイト

これが技術的に重要であるかどうかはわかりません-それは実際には健康が0より大きいチームのランダムなメンバーを選択しないからです。ランダムなメンバーを選択するだけで、ヘルス減算によって0未満の数値が生成されると、その数値は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!-

要件は、印刷ステータスで値が0未満にならないことです。示した例でも同じことをしました。
— 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

オクターブ、182177158145バイト

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

キャラクターシュートが0を超えているかどうかを確認することをあきらめました-これは、各ターンで状態を表示することを強制された場合にのみ重要です-ここでは、RNGから1つの乱数をランダムにスキップして、よりランダムにします。

また、交換

t=max(0,t)

より短い

t.*=t>0


[注-改行なしで 'C + R-'を出力しています-145バイトバージョンで修正されています]

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

デゴルフド:

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

- に変更repmat(50,5,2)したrepmat(5)ので、5x2の代わりに5x5マトリックスになりました(追加の3列はアルゴリズムに影響しません)。出力を圧縮する方法も見つけました。

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

デゴルフド:

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

基本的に、5列のマトリックスを作成します。最初の列は警官で、2番目の列は強盗です。

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

sum1つの引数が適用されたときの関数は列ごとの合計を作成するため、最初は次のようになります。

250    250

それらのいずれかがゼロに達するとprod(sum(t))、ループを中断してゼロと評価されます。次に、列の合計がゼロになるチェックを誰が勝ち取ったかを調べることができます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.