ตำรวจและโจร


11

ทุกคนต้องการนำเกมแห่งชีวิตของ Conway มาใช้ เบื่อ! มาทำตำรวจและโจรกันเถอะ!

คุณจะมีสองทีม: ตำรวจและโจร แต่ละทีมมีสมาชิก 5 คนโดย 50 คนละคน โปรแกรมจะวนซ้ำอย่างต่อเนื่อง การวนซ้ำแต่ละครั้งจะเกิดสิ่งต่อไปนี้:

  • สำหรับแต่ละทีมให้พิมพ์ตัวอักษรตัวแรก ( 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 ในสถานะ

  • รีสตาร์ทลูป

เกมจะจบลงเมื่อสมาชิกทุกคนในทีมเดียวเสีย 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+ ข้อในไซต์นี้มีการติดแท็กไม่เกิน 11 game-of-lifeรายการ
Sanchises

3
@sanchises Extended irony: และอีก 14 แท็กcops-and-robbers!
Runer112

@sanchises ฉันส่วนใหญ่หมายถึงการเขียนโปรแกรมโดยทั่วไป (เช่น "ช่วยฉัน! ฉันพยายามที่จะใช้เกมแห่งชีวิตของคอนเวย์!") ... แต่นั่นก็น่าขัน
kirbyfan64sos

@ kirbyfan64sos ฉันรู้ว่า (เคยทำมาแล้ว) แต่นี่เป็นเว็บไซต์ประเภทที่ผู้คนไปหลังจากที่พวกเขานำ GoL มาใช้และต้องการมากขึ้น ... อย่างไรก็ตามบางทีฉันอาจจะไปที่นี่ใน> <> มาดูกันว่าฉันทำได้ไหม
Sanchises

ฉันลบแท็ก CnR อีกครั้ง รอบ ๆ ที่นี่แท็กนี้มีความหมายที่เฉพาะเจาะจงมากและอธิบายถึงความท้าทายที่จริง ๆ แล้วมีทั้งสองฝ่าย (ไม่จำเป็นต้องแยกจากกัน) แข่งขันกันในงานบางงาน (ดูรอบ ๆ ความท้าทายอื่น ๆ ด้วยแท็กนั้น)
Martin Ender

คำตอบ:


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^

ลองออนไลน์

คำอธิบาย

เมื่อคำถามถามให้เลียนแบบกระบวนการที่ตรงไปตรงมานี่เป็นคำตอบที่ค่อนข้างตรงไปตรง บางทีทางเลือกหนึ่งที่น่าสนใจที่ฉันทำคือรักษาสุขภาพของทั้งสองทีมไว้ในรายการเดียวกัน ค่าใช้จ่ายนี้ 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ก็จะกลับหมายเลขใด ๆ จากการ1 5ดังนั้นsample(rep(x, 2), 1)เคล็ดลับของฉันคือการเลือกหมายเลขxแม้ในกรณีที่length(x)เป็น1เสมอ
flodel

ขออภัยที่ไม่ดีของฉัน ... เห็นได้ชัดว่ากาแฟไม่เพียงพอ ขอบคุณสำหรับคำอธิบายเกี่ยวกับเคล็ดลับตัวแทน () ฉันคิดว่าต้องมีเหตุผลแค่มองไม่เห็น
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
∇

คำอธิบาย:

  • S←2 5⍴50: ที่จุดเริ่มต้นตั้ง Sเป็นเมทริกซ์ 5 คูณ 2 โดยแต่ละค่าคือ 50 แถวบนสุดของเมทริกซ์แสดงถึงตำรวจแถวที่สองแสดงถึงโจร
  • J←∨/S>0: สำหรับแต่ละแถวของเมทริกซ์ให้เก็บอิน Jว่า HP ใดมีขนาดใหญ่กว่าศูนย์หรือไม่
  • →6/⍨~∧/J: ถ้าไม่ใช่ทั้งสองทีมมีสมาชิกที่มีชีวิตข้ามไปที่บรรทัด 6 (จบ)
  • ⎕←3↑'CR',0⌈S: สำหรับแต่ละค่าในเมทริกซ์ให้เอาท์พุทสูงสุดของมันและ 0, เติม 'C' ลงในแถวแรกและ 'R' ถึงวินาทีและเพิ่มบรรทัดที่สาม (ว่าง)
  • N←?10: รับตัวเลขสุ่มในช่วงเวลา [1,10] และเก็บไว้ใน Nและเก็บไว้ใน
  • L←1+~2⊤N: set L(ทีมที่แพ้) 1หากหมายเลขนั้นเป็นเลขคี่และ2ถ้าเป็นเลขคู่
  • 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 แต่ฉันเดาว่าบางทีคุณอาจตัดบาง chars ด้วยการลบ!= 0และแทนที่เช็คให้เท่ากับศูนย์ด้วยตัวดำเนินการไม่ใช่ ( !array_sum($r))
kirbyfan64sos

@ kirbyfan64sos ที่ใช้งานไม่ได้
ติโม

โอ้ ในภาษาส่วนใหญ่มันจะ
kirbyfan64sos

1

C, 390 384 371 ไบต์

กอล์ฟครั้งแรกของฉันหากมีการปรับปรุงใด ๆ ที่เป็นไปได้เพียงแค่บอกฉัน :)

รุ่น 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);}

รุ่นที่ค่อนข้าง ungolfed:

#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

คุณพูดถูกต้อง "คงที่" สิ่งนี้และสิ่งอื่น ๆ อีกเล็กน้อยขอบคุณ
Metaforce

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

คู่, 182 177 158 145 ไบต์

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

ฉันเลิกตรวจสอบว่าการยิงตัวละครสูงกว่าศูนย์ - นี่จะสำคัญถ้าเราถูกบังคับให้แสดงสถานะในแต่ละเทิร์น - ที่นี่เราแค่สุ่มข้ามหมายเลขสุ่มหนึ่งตัวจาก RNG ทำให้สุ่มขึ้นมา

ยังถูกแทนที่ด้วย

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

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

ฉันเปลี่ยนrepmat(50,5,2)เป็นrepmat(5)- ดังนั้นเราจึงมีเมทริกซ์ 5x5 แทนที่จะเป็น 5x2 ในขณะนี้ (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

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

โดยพื้นฐานแล้วเราสร้างเมทริกซ์ 5x2 โดยที่คอลัมน์แรกเป็นตำรวจและคอลัมน์ที่สองเป็นโจร:

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

sumฟังก์ชั่นเมื่ออาร์กิวเมนต์หนึ่งนำมาใช้ทำให้ผลรวมตามคอลัมน์จึงเป็นครั้งแรก:

250    250

เมื่อหนึ่งในนั้นถึงศูนย์การprod(sum(t))ประเมินจะเป็นศูนย์ทำลายวง จากนั้นเราสามารถตรวจสอบว่าใครชนะในการตรวจสอบว่าคอลัมน์ใดมีผลรวมเป็นศูนย์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.