Terra Mystica:单车动力


28

棋盘游戏Terra Mystica具有一些非常有趣的机制,其中一种主要资源就是力量。每个玩家不用从银行获得和消耗权力单位,而是以恰好12个权力单位开始游戏,这些权力分配在三个“碗”中,分别标记为I,II和III。获得和消费能力然后简单地在这些碗之间转移权力:

  • 要消耗一个单位的功率,请将其从III碗移到I碗(前提是您在III碗中有一个单位)。
  • 当获得一个单位的功率时,如果碗I中有一个单位,请将其移至碗II中。如果碗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)

您的任务是计算一个此类收益或支出事件的结果。

挑战

您将获得四个整数作为输入。前三,IIIIII,表示在三个碗的功率量。它们将为非负数,总和为12。第四个数字,P是获得或消耗的力量数量,并且将在包含在内的范围内[-III, 24](因此您可以假设玩家永远不会尝试花费更多的力量比他们目前能获得的要多,但是他们获得的功率可能超过了将所有功率移入III号碗所需的功率。

您可以按照任何一致的顺序将这些数字用作单独的参数,整数列表或包含这些整数的字符串。您也可以P作为一个参数,如IIIIII作为一个单独的列表参数。

你应该输出三个整数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
我建议删除针对性别的代词,并用中性的代词(或重组句子)代替:游戏玩家不必是男性。
格雷格·马丁

1
@GregMartin当然。我都抓住了吗?
马丁·恩德

2
看起来像;谢谢您的考虑!另外,Terra Mystica是否像我所听到的那样出色?
格雷格·马丁

4
@GregMartin是的。:)
Martin Ender'3

5
2号碗没有功率燃烧吗?感觉还不完整。
moreON

Answers:


6

Mathematica,52个字节

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

这是一个未命名的函数,它将列表{I, II, III, P}作为输入并返回一个列表{I', II', III'}

封闭形式的解决方案。感觉还不是最理想的...


以为我可以缩短,但{##,12-+##}&[#-#4~Min~#,Max[#2+#-Abs[#4~Max~0-#],0]]&要长一个字节。我喜欢12-+##
格雷格·马丁

1
@GregMartin我尝试过同样的事情:)
Martin Ender

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

Python 2,104字节

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

在线尝试

取消高尔夫:

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个字节

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-z使用标识a+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öda100 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]}

取消高尔夫:

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

@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`,

一元输入。第一行包含三个逗号分隔的碗中的电量,第二行包含循环的电量。

测试套件 -将所有输入都放在一行上,并从十进制转换为一进制,反之亦然,以方便使用。

说明

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

由于Batch的运算符不小于运算符,因此我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)}

abc分别是碗I,II和III中的起始标记数。然后,对于增加幂的情况,将创建一个列表,其中包含a三元组(-1, 1, 0)a + b副本,然后是三元组的副本(0, -1, 1),然后是的无限副本0d此列表的第一个元素(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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.