Terra Mystica: พลังการปั่นจักรยาน


28

boardgame Terra Mysticaมีกลไกที่น่าสนใจมากสำหรับหนึ่งในทรัพยากรหลักพลัง แทนที่จะได้รับและใช้พลังงานจากธนาคารผู้เล่นแต่ละคนจะเริ่มเกมด้วยพลัง 12 หน่วยซึ่งกระจายอยู่ทั่ว "โบลลิ่ง" สามอันซึ่งมีชื่อว่า I, II และ III การดึงดูดและการใช้จ่ายพลังงานนั้นเพียงแค่เปลี่ยนพลังงานระหว่างชามเหล่านี้:

  • ในการใช้หน่วยพลังให้ย้ายจากชาม III ไปยังชาม I (หากคุณมีหน่วยในชาม III)
  • เมื่อคุณได้รับหน่วยพลังถ้ามีหน่วยในชามฉันย้ายไปยังชามที่สอง หากไม่มีหน่วยในชาม I แต่มีหน่วยในชาม II ให้ย้ายไปยังชาม III หากทุกหน่วยอยู่ในชาม III แล้วจะไม่มีอะไรเกิดขึ้น
  • เมื่อคุณได้รับหรือใช้จ่ายหลายหน่วยพร้อมกันพวกเขาจะประมวลผลทีละหน่วย

นี่คือตัวอย่าง พูดว่าผู้เล่นเริ่มต้นด้วยการกระจายพลังงานต่อไปนี้ (ตามลำดับI | II | III):

5 | 7 | 0

พลังของพวกเขาเปลี่ยนไปดังนี้หากพวกเขาได้รับและใช้พลังงานสองสามครั้ง:

               5 |  7 |  0
Gain  3  ==>   2 | 10 |  0
Gain  6  ==>   0 |  8 |  4   (move 2 power from I to II, 
                              then the remaining 4 from II to III)
Gain  7  ==>   0 |  1 | 11
Spend 4  ==>   4 |  1 |  7
Gain  1  ==>   3 |  2 |  7
Spend 7  ==>  10 |  2 |  0
Gain 12  ==>   0 | 10 |  2   (move 10 power from I to II,
                              then the remaining 2 from II to III)
Gain 12  ==>   0 |  0 | 12   (the two excess units go to waste)

งานของคุณคือการคำนวณผลลัพธ์ของเหตุการณ์ที่ได้รับหรือการใช้จ่าย

ความท้าทาย

คุณได้รับจำนวนเต็มสี่จำนวนเป็นอินพุต ครั้งแรกที่สามI, II, IIIแทนปริมาณของพลังงานในแต่ละแห่งที่สามชาม พวกเขาจะไม่เป็นลบและจะรวมเป็น 12 จำนวนที่สี่Pคือจำนวนพลังงานที่ได้รับหรือใช้ไปและจะอยู่ในช่วงรวม[-III, 24](ดังนั้นคุณอาจคิดว่าผู้เล่นจะไม่พยายามใช้พลังงานมากขึ้น เกินกว่าที่พวกเขาจะสามารถทำได้ แต่พวกเขาอาจจะได้รับพลังมากกว่าที่พวกเขาต้องการที่จะย้ายพลังทั้งหมดเข้าไปในชาม III)

คุณอาจใช้ตัวเลขเหล่านี้ตามลำดับที่สอดคล้องกันเป็นอาร์กิวเมนต์แยกเป็นรายการจำนวนเต็มหรือเป็นสตริงที่มีจำนวนเต็มเหล่านี้ นอกจากนี้คุณยังสามารถใช้Pเป็นหนึ่งในข้อโต้แย้งเช่นI, II, IIIเป็นอาร์กิวเมนต์รายการแยกต่างหาก

คุณควรเอาท์พุทสามจำนวนเต็มI', II', III'ซึ่งเป็นตัวแทนของปริมาณของพลังงานในแต่ละชามหลังจาก Pหน่วยที่ได้รับหรือการใช้จ่ายตามกฎที่อธิบายข้างต้น

คุณสามารถเขียนโปรแกรมหรือฟังก์ชั่นและใช้วิธีการมาตรฐานของเราในการรับอินพุตและให้เอาต์พุต

คุณอาจใช้ภาษาการเขียนโปรแกรมใด ๆแต่โปรดทราบว่าช่องโหว่เหล่านี้เป็นสิ่งต้องห้ามตามค่าเริ่มต้น

นี่คือดังนั้นคำตอบที่สั้นที่สุดที่ถูกต้อง - วัดเป็นไบต์ - ชนะ

กรณีทดสอบ

I II III P => I' II' III'
5 7 0 3    => 2 10 0
2 10 0 6   => 0 8 4
0 8 4 7    => 0 1 11
0 1 11 -4  => 4 1 7
4 1 7 0    => 4 1 7
4 1 7 1    => 3 2 7
3 2 7 -7   => 10 2 0
10 2 0 12  => 0 10 2
0 10 2 12  => 0 0 12

1
ฉันขอแนะนำให้ลบคำสรรพนามเฉพาะเพศและแทนที่ด้วยสรรพนามเพศที่เป็นกลาง (หรือปรับโครงสร้างประโยค): ผู้เล่นไม่จำเป็นต้องเป็นเพศชาย
Greg Martin

1
@ GregMartin แน่นอน ฉันจับพวกมันทั้งหมดเหรอ?
Martin Ender

2
ดูเหมือนว่ามัน; ขอบคุณที่คิดเกี่ยวกับมัน! นอกจากนี้ Terra Mystica ยังยอดเยี่ยมเหมือนที่ฉันเคยได้ยินหรือไม่?
Greg Martin

4
@ GregMartin ใช่ :)
Martin Ender

5
ไม่มีไฟไหม้จากชาม 2? นี่แค่รู้สึกไม่สมบูรณ์
เพิ่มเติม

คำตอบ:


6

Mathematica, 52 ไบต์

{x=#-#4~Min~#,y=Max[#2+#-Abs[#4~Max~0-#],0],12-x-y}&

นี้เป็นฟังก์ชั่นที่ใช้ชื่อรายการ{I, II, III, P}เป็น input {I', II', III'}และส่งกลับรายการ

วิธีแก้ปัญหาแบบปิด มันยังไม่รู้สึกที่ดีที่สุดจริงๆ ...


คิดว่าฉันสามารถทำให้สั้นลง แต่{##,12-+##}&[#-#4~Min~#,Max[#2+#-Abs[#4~Max~0-#],0]]&มีความยาวมากกว่าหนึ่งไบต์ ผมชอบ12-+##แม้ว่า
Greg Martin

1
@GregMartin ฉันพยายามในสิ่งเดียวกัน :)
มาร์ตินเอนเดอร์

6

C, 97 94 ไบต์

f(i,j,k,n){for(;n;n-=n/abs(n))n<0?k?++i+--k:0:i?++j+--i:j?++k+--j:0;printf("%d %d %d",i,j,k);}

ในรูปแบบที่ไม่ดี:

f(i, j, k, n) {
    while (n) {
        if (n < 0) {
            if (k) {
                ++i; --k;
            }
            ++n;
        } else {
            if (i) {
                ++j; --i;
            }
            else if (j) {
                ++k; --j;
            }
            --n;
        }
    }
    printf("%d %d %d", i, j, k);
}


5

Haskell, 58 ไบต์

f(a,b,c)d|m<-min a d,z<-min(c+d-max 0 m)12=(a-m,b+c+m-z,z)

ค่ากลางmหมายถึงปริมาณพลังงานที่ได้จาก (หรือหากเป็นลบ) ชามแรกจะzแสดงปริมาณของพลังงานในชามที่สามหลังจากการกระทำ สุดท้ายจะเพิ่มประสิทธิภาพไบต์หนึ่งนาทีการเปลี่ยนแปลงการแสดงออกเก่าชามที่สองจากการใช้บัตรประจำตัว12-a+m-za+b+c=12

ประเภทผลลัพธ์ตามธรรมชาติคือสามเท่าสำหรับโบลิ่งดังนั้นอินพุตยังใช้โบลิ่งเป็นสามเท่าและการเปลี่ยนแปลงพลังงานเป็นอาร์กิวเมนต์ที่สอง สิ่งนี้จะช่วยให้สามารถจัดการกับกรณีทดสอบทั้งหมดด้วยแอปพลิเคชันเดียวscanl:

*Main> scanl f (5,7,0) [3,6,7,-4,0,1,-7,12,12]
[(5,7,0),(2,10,0),(0,8,4),(0,1,11),(4,1,7),(4,1,7),(3,2,7),(10,2,0),(0,10,2),(0,0,12)]

5

Röda , 100 94 ไบต์

f a,b,c,p{{c+=p;a-=p}if[p<0]else{{a--;b++;p--}while[p*a>0];{b--;c++;p--}while[p*b>0]};[a,b,c]}

Ungolfed:

f a,b,c,p {
    if [ p < 0 ] do
        c += p
        a -= p
    else
        { a-=1; b+=1; p-=1 } while [ p > 0 and a > 0 ]
        { b-=1; c+=1; p-=1 } while [ p > 0 and b > 0 ]
    done
    return a, b, c
}

Rödaไม่มีตัวดำเนินการ++และ--ตัวดำเนินการหรือไม่
Kritixi Lithos

@KritixiLithos ขอบคุณ! ใช่แล้ว.
fergusq


3

GNU sed , 66 ไบต์

รวม +1 สำหรับ -r

/-/!{:
s/1,(.* )1/,1\1/
t}
s/(.*)(1+) -\2/\2\1/
s/(,,1{12}).*/\1/

ใช้เอกนารี (ดูฉันทามตินี้ )

ลองออนไลน์!

/-/!{                  # If there is not a '-'
  :                    # start loop
  s/1,(.* )1/,1\1/     # move a 1 from before a ',' to after the ',' for every 1 after the space
                       # sed reads left to right, so this takes everything from the first bowl before starting on the second
  t                    # loop if something changed
}                      # end if
s/(.*)(1+) -\2/\2\1/   # take all of the 1s from after a '-' and move them to the begining.
                       # at the same time, remove that many 1s from the 3rd bowl
s/(,,1{12}).*/\1/      # remove everything after 12 1s in the third bowl

3

เรติน่า ,  46  41 39 38 ไบต์

ขอบคุณ Martin Ender สำหรับคำแนะนำที่เป็นประโยชน์มากมาย!

+`1,(.*¶)1
,1$1
(.*)(1+)¶-\2$
$2$1
G`,

ใช้อินพุตเป็น unary บรรทัดแรกมีปริมาณพลังงานในชามทั้งสามคั่นด้วยเครื่องหมายจุลภาคบรรทัดที่สองคือปริมาณพลังงานที่จะหมุนเวียน

ชุดทดสอบ - รับอินพุตทั้งหมดในบรรทัดเดียวและแปลงจากทศนิยมเป็นเอกและในทางกลับกันเพื่อความสะดวกในการใช้งาน

คำอธิบาย

+`1,(.*¶)1
,1$1

กรณีที่เป็นบวก: เราลบผู้นำ1จากบรรทัดที่สองซ้ำ ๆและย้าย a 1จากชามที่ไม่ว่างเปล่าแรกไปยังชามต่อไปนี้ตราบใดที่การดำเนินการนี้เป็นไปได้ กำลังอยู่ในชามที่สาม) sวิธีการปรับปรุงsingle-lineช่วยให้.เพื่อให้ตรงกับยังขึ้นบรรทัดใหม่

(.*)(1+)¶-\2$
$2$1

กรณีเชิงลบ: ทำทั้งหมดในขั้นตอนเดียวย้ายปริมาณพลังงานที่ระบุโดยอินพุตสุดท้ายจากสามไปยังชามแรก นี่จะเป็นการลบบรรทัดที่มีปริมาณพลังงานลบที่จะย้าย

G`,

เก็บ (grep) เฉพาะบรรทัดที่มีเครื่องหมายจุลภาค สิ่งนี้จะกำจัดส่วนที่เหลือในที่สุดของบรรทัดแรก



2

แบตช์ 87 ไบต์

@set/a"i=%4-%1,j=%4*(-%4>>5)-%2-2*i*(-i>>5),i*=i>>5,j*=j>>5,k=12-i-j
@echo %i% %j% %k%

ใช้สูตรต่อไปนี้:

I' = min(I - P, 0)
II' = min(II + min(P, 0) - 2 * min(P - I, 0), 0)
III' = 12 - I' - II'

ตั้งแต่รุ่นที่ไม่ได้น้อยกว่าผู้ประกอบการที่ผมคำนวณโดยใช้i = min(-i, 0)i*=i>>5


2

Perl 6 , 99 ไบต์

->\a,\b,\c,\d{d>0??[»+»] (a,b,c),|(|((-1,1,0)xx a),|((0,-1,1)xx a+b),|(0 xx*))[^d]!!(a- d,b,c+d)}

อนุญาตa, bและcเป็นจำนวนโทเค็นเริ่มต้นในชาม I, II และ III ตามลำดับ จากนั้นสำหรับกรณีเพิ่มพลังงานรายการจะถูกสร้างขึ้นซึ่งมีaสำเนาของ triplet(-1, 1, 0)ตามa + bสำเนาของแฝดตามสำเนาอนันต์ของ(0, -1, 1) องค์ประกอบ0แรกdของรายการนี้dปริมาณพลังงานที่จะเพิ่มจะถูกรวมเข้ากับการกระจายพลังงานเริ่มต้น

สำหรับการลบกำลัง (เชิงลบd) จะใช้รูปแบบปิดแบบง่าย:(a - d, b, c + d)ซึ่งเป็นรูปแบบปิดง่ายใช้:


2

tinylisp , 134 ไบต์

(d f(q((x y z p)(i p(i(l p 0)(f(s x p)y(a z p)0)(i x(f(s x 1)(a y 1)z(s p 1))(i y(f x(s y 1)(a z 1)(s p 1))(f x y z 0))))(c x(c y(c z(

กำหนดฟังก์ชั่นfที่รับสี่อาร์กิวเมนต์สามโบลว์ ( x y z) และปริมาณของพลังงานที่ทำธุรกรรม ( p) และส่งกลับรายการของสามโบลว์หลังจากธุรกรรม นี่เป็นเวอร์ชั่นที่เว้นระยะอย่างถูกต้องกับกรณีทดสอบทั้งหมด: ลองออนไลน์!

(d f                         Define f to be
 (q(                          a quoted two-item list (which acts as a function):
  (x y z p)                    Arglist: the three bowls x y z and power p
  (i p                         If p is nonzero
   (i (l p 0)                   then if p is negative (spending power)
    (f(s x p)y(a z p)0)          then take -p from z, add -p to x, and recurse with p=0
    (i x                         else (gaining power), if x is nonzero
     (f(s x 1)(a y 1)z(s p 1))    then take 1 from x, add to y, decrement p and recurse
     (i y                         else if y is nonzero
      (f x(s y 1)(a z 1)(s p 1))   then take 1 from y, add to z, decrement p and recurse
      (f x y z 0))))               else no moves possible; recurse with p=0
   (c x(c y(c z())))))))        else (p=0), cons x y z into a list and return it
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.