Terra Mystica: Kekuatan Bersepeda


28

Boardgame Terra Mystica memiliki beberapa mekanisme yang sangat menarik untuk salah satu sumber daya utama, daya. Alih-alih mendapatkan dan mengeluarkan unit daya dari bank, setiap pemain memulai permainan dengan tepat 12 unit daya yang didistribusikan di tiga "mangkuk", yang diberi label I, II dan III. Mendapatkan dan membelanjakan daya kemudian dengan mudah menggeser kekuatan di antara mangkuk-mangkuk ini:

  • Untuk menghabiskan satu unit daya, pindahkan dari mangkuk III ke mangkuk I (asalkan Anda memiliki unit di mangkuk III).
  • Saat Anda mendapatkan unit daya, jika ada unit di mangkuk I, pindahkan ke mangkuk II. Jika tidak ada unit di mangkuk I, tetapi ada unit di mangkuk II, pindahkan ke mangkuk III. Jika semua unit sudah ada di mangkuk III, tidak ada yang terjadi.
  • Ketika Anda mendapatkan atau menghabiskan beberapa unit sekaligus, mereka diproses satu unit sekaligus.

Berikut ini sebuah contoh. Katakanlah, seorang pemain mulai dengan distribusi daya berikut (diberikan secara berurutan I | II | III):

5 | 7 | 0

Kekuatan mereka berubah sebagai berikut jika mereka mendapatkan dan menghabiskan kekuasaan beberapa kali:

               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)

Tugas Anda adalah untuk menghitung hasil dari salah satu acara perolehan atau pengeluaran tersebut.

Tantangan

Anda diberi empat bilangan bulat sebagai input. Tiga pertama, I, II, III, mewakili jumlah daya di masing-masing tiga mangkuk. Mereka akan menjadi non-negatif, dan mereka akan berjumlah 12. Angka keempat P,, adalah jumlah daya yang diperoleh atau dihabiskan, dan akan berada dalam kisaran inklusif [-III, 24](sehingga Anda dapat mengasumsikan bahwa pemain tidak akan pernah mencoba menghabiskan lebih banyak daya daripada saat ini, tetapi mereka mungkin mendapatkan kekuatan lebih dari yang mereka butuhkan untuk memindahkan semua kekuatan ke mangkuk III).

Anda dapat mengambil angka-angka ini dalam urutan yang konsisten, sebagai argumen terpisah, sebagai daftar bilangan bulat, atau sebagai string yang berisi bilangan bulat ini. Anda juga dapat mengambil Psebagai salah satu argumen, seperti I, II, IIIsebagai daftar argumen yang terpisah.

Anda harus keluaran tiga bilangan bulat I', II', III'yang mewakili jumlah daya di setiap mangkuk setelah P unit diperoleh atau dihabiskan, mengikuti aturan yang dijelaskan di atas.

Anda dapat menulis program atau fungsi dan menggunakan salah satu metode standar kami untuk menerima input dan memberikan output.

Anda dapat menggunakan bahasa pemrograman apa pun , tetapi perhatikan bahwa celah ini dilarang secara default.

Ini adalah , sehingga jawaban terpendek yang valid - diukur dalam byte - menang.

Uji Kasus

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
Saya merekomendasikan untuk menghapus kata ganti spesifik gender dan menggantinya dengan kata ganti netral-gender (atau merestrukturisasi kalimat): gamer tidak harus laki-laki.
Greg Martin

1
@Regregart tentu saja. Apakah saya menangkap mereka semua?
Martin Ender

2
Terlihat seperti itu; terima kasih sudah memikirkannya! Juga, apakah Terra Mystica sehebat yang saya dengar?
Greg Martin

4
@GregMartin ya. :)
Martin Ender

5
Tidak ada daya terbakar dari mangkuk 2? Ini terasa sangat tidak lengkap.
selanjutnya

Jawaban:


6

Mathematica, 52 byte

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

Ini adalah fungsi tanpa nama yang mengambil daftar {I, II, III, P}sebagai input dan mengembalikan daftar {I', II', III'}.

Solusi bentuk tertutup. Itu belum benar-benar terasa optimal ...


Kupikir aku bisa mempersingkat, tetapi {##,12-+##}&[#-#4~Min~#,Max[#2+#-Abs[#4~Max~0-#],0]]&satu byte lebih lama. Saya suka itu 12-+##.
Greg Martin

1
@GregMartin saya mencoba hal yang sama :)
Martin Ender

6

C, 97 94 byte

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

Dalam bentuk yang tidak diserang:

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

Python 2, 104 byte

def f(i,d,t,g):
 x=min(i,g);i-=x;q=g>0;g-=x
 if q:d+=x;x=min(d,g);g-=x;d-=x;t+=x
 else:t+=x
 print i,d,t

Cobalah online

Tidak Terkumpul:

def f(i,d,t,g):
 if g>0:
    x=min(i,g)
    g-=x
    i-=x
    d+=x    
    x=min(d,g)
    g-=x
    d-=x
    t+=x
 else:
    x=min(i,g)
    g-=x
    i-=x
    t+=x
 print(i,d,t)

5

Haskell, 58 byte

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

Nilai perantara mmenunjukkan jumlah daya yang mengalir dari (atau ke, jika negatif) mangkuk pertama, zmenunjukkan jumlah daya di mangkuk ketiga setelah tindakan. Pengoptimalan satu byte menit terakhir mengubah ekspresi lama untuk mangkuk kedua dari 12-a+m-zmenggunakan identitas a+b+c=12.

Jenis hasil alami adalah triple untuk mangkuk, sehingga input juga mengambil mangkuk sebagai triple dan kekuatan berubah sebagai argumen kedua. Ini memungkinkan untuk menangani semua kasus uji dengan satu aplikasi 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 byte

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

Tidak Terkumpul:

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
}

Bukankah Röda memiliki ++dan --operator?
Kritixi Lithos

@KritixiLithos Terima kasih! Ya itu.
fergusq


3

GNU sed , 66 byte

Termasuk +1 untuk -r

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

Menggunakan unary (lihat konsensus ini ).

Cobalah online!

/-/!{                  # 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

Retina ,  46  41 39 38 byte

Terima kasih kepada Martin Ender untuk beberapa saran berguna!

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

Mengambil input di unary. Baris pertama berisi jumlah daya dalam tiga cawan, dipisahkan koma, baris kedua jumlah daya untuk siklus.

Test suite - Mengambil semua input pada satu baris dan mengonversi dari desimal ke unary dan sebaliknya untuk kenyamanan penggunaan.

Penjelasan

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

Kasus positif: kami berulang kali melepas pelapis 1dari baris kedua, dan memindahkan a 1dari mangkuk pertama yang tidak kosong ke yang berikutnya, selama operasi ini dimungkinkan (yaitu jumlah daya untuk siklus tidak nol dan tidak semua kekuatan ada di mangkuk ketiga). The ssarana pengubah single-line, memungkinkan .untuk mencocokkan juga baris baru.

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

Kasus negatif: dilakukan semua dalam satu langkah, memindahkan jumlah daya yang ditunjukkan oleh input terakhir dari mangkuk ketiga ke mangkuk pertama. Ini juga akan menghapus garis yang mengandung jumlah daya negatif untuk bergerak.

G`,

Simpan (grep) hanya baris yang mengandung koma. Ini akan menyingkirkan sisa-sisa baris pertama.


3

Python 2, 91 byte

Berdasarkan jawaban ini

def f(i,d,t,g):
 x=min(i,g);i-=x
 if g>0:y=min(d+x,g-x);d+=x-y;t+=y
 else:t+=x
 print i,d,t

Cobalah online

Tidak Terkumpul:

def f(i,d,t,g):
 if g>0:
    x=min(i,g)
    y=min(d+x,g-x)
    i-=x
    d+=x-y
    t+=y
 else:
    x=min(i,g)
    i-=x
    t+=x
 print(i,d,t)

Selamat datang di situs ini!
DJMcMayhem

2

Batch, 87 byte

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

Gunakan rumus berikut:

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

Karena Batch tidak memiliki lebih sedikit dari operator, saya menghitung i = min(-i, 0)menggunakan i*=i>>5.


2

Perl 6 , 99 byte

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

Biarkan a,, bdan cjadilah jumlah token awal dalam mangkuk I, II, dan III. Kemudian, untuk kasus daya tambahan, daftar dibuat yang berisi asalinan triplet (-1, 1, 0), diikuti oleh a + bsalinan triplet (0, -1, 1), diikuti oleh salinan infinite dari 0. dElemen pertama dari daftar ini, dmenjadi jumlah daya yang ditambahkan, ditambahkan elementwise ke distribusi daya awal.

Untuk mengurangi daya (negatif d), bentuk tertutup sederhana yang digunakan: (a - d, b, c + d).


2

tinylisp , 134 byte

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

Menentukan fungsi fyang mengambil empat argumen, tiga cawan ( x y z) dan jumlah daya yang ditransaksikan ( p), dan mengembalikan daftar tiga cawan setelah transaksi. Berikut ini adalah versi yang diberi spasi dengan baik pada semua test case: Cobalah online!

(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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.