解决Dominion中的加倍和三倍动作


14

灵感

这个问题的灵感来自于流行的甲板建筑纸牌游戏《Dominion》中的《王座室》和《王宫》。

金銮殿 英皇阁

作为回合的一部分,人们扮演一系列动作。这两个特定动作导致下一个播放的动作重复两次或三次*。其他“一般”动作会导致特定的游戏效果,但是我们对细节不感兴趣,只需用字母标记它们即可。

有趣的情况是,当一个王室或国王法院影响另一个王室的王室时,使自身的加倍或三倍效果增加了一倍或三倍。长久的宝座室,国王宫廷和繁复的动作链会混淆甚至是经验丰富的Dominion玩家。

您的目标是编写使用尽可能少的字节正确解析这些链的代码。在解释这些链如何在Dominion规则中解析之前,我将描述程序要求。

*从技术上讲,您选择受影响的行动是解决“王室”或“国王法院”的一部分,但这种观点对于解决这一挑战是比较干净的。

课程要求

写一个 程序命名函数。它应该接受所播放的动作链(STDIN或函数输入),并输出或打印因加倍和三倍效果而产生的动作链。最少的字节数获胜。

输入值

一个字符串,表示播放的动作序列。一般的操作是用大写字母来表示A通过Z。特殊加倍动作王座室由人物表示2,三重动作“国王法院”由表示3

字符(动作)的数量在1到30之间(含1和30)。如果需要,可以在换行符后面输入输入。

输入示例: WA23G3GA

输出量

大写字母组成的字符串AZ。这应该是解决双重和三重影响所产生的一般动作的顺序,顺序是它们发生的顺序。

如果需要,可以将输出结尾换行。否则不应有其他字符。

输出示例:WAGGGGGGAAA

Dominion中的两倍和三倍如何工作

在这里,我将详细说明根据自治领规则2,王室室和国王法院的链条如何3工作。

播放后2,下一个要解决的动作将发生两次。因此,如果您先玩2,然后玩A,您会A发生两次。

2A -> AA

同样,

A2BC -> ABBC
3DE -> DDDE
3N2BC3XY2 -> NNNBBCXXXY

请注意,在最后一个示例中,决赛2没有任何内容可以加倍,因此没有任何效果。

当倍增或三倍效果本身变为两倍或三倍时,会发生有趣的事情。例如,

22AB -> AABB

首先,您玩2。然后,您播放另一个2,是前一个的两倍2。结果,接下来的两个动作加倍。首先,A解决两个副本。然后,B解决副本。

请注意,A它不是四倍的:在第一个2行为的第A一个副本之后,下一个副本对下一个未解决的行为()起作用B。没有B,我们将拥有

22A -> AA

其中的第二个副本2正在等待下一个操作加倍,但没有任何操作来。

最后,让我们看一个复杂的例子。

223BCDE -> BBBCCCDDE

和以前一样,第一个2导致第二个2被加倍。因此,接下来的两个动作将加倍。第一个副本2将下一个动作加倍3,在解决下一个副本之前必须彻底解决这个问题2。第一副本的3三倍B,第二副本的三倍C。现在,仍在等待的第二个副本2将下一个仍未解决的操作()加倍D。在此之后,不再保留任何倍增或三倍的效果,而最终的动作E只发生了。

测试用例

这些以给出(input,output)

(FY, FY)
(A2BC, ABBC)
(3DE, DDDE)
(3N2BC3XY2, NNNBBCXXXY)
(WA23G3GA, WAGGGGGGAAA)
(32, )
(33RST, RRRSSSTTT)
(2A32B2CDEFG, AABBCCDDEEFG)
(A2A323AB2CD2D2E3ABC, AAAAAABBBCCDDDDEEAAABBBC)
(P22LL3Q2Q22T, PLLLLQQQQQTT)
(322322ABCDEFGHIJKLMN, AABBCCDDEEEFFGGHHIJKLMN)

Answers:


5

GolfScript(29 26字节)

](1/{\1+(3&@*.23-\1$-@+}/;

在线演示

解剖

这稍微滥用了GolfScript的松散类型。重复执行后续操作的次数堆栈从一个数组开始,后来变成一个字符串-但1+附加一个1并(3&弹出第一个值,然后将其正确地置于范围内03而与类型更改无关。

](         # Push an empty array under the input string to serve as rep stack
1/{        # Loop over the input string as a series of 1-char strings
           #   Stack is ... reps ch
           #   where the ... covers zero or more strings which will be output
  \        #   Bring the rep stack to the top
  1+(      #   Push a `1` on the bottom of it to avoid underflow and then pop
  3&       #   Coerce to correct range, because if rep stack is a string then
           #   we just got an ASCII value
  @*       #   Apply repetition to the 1-char string: it's now an n-char string
  .23-     #   Duplicate it and remove chars '2' and '3': this becomes output
  \1$-     #   Get the original copy and remove the output string's chars
           #   So the stack is now ... reps output non-output
           #   where non-output is either an empty string or a string of '2's
           #   or '3's
  @+       #   Push non-output onto the repetition stack
}/         # Loop
;          # Pop whatever's left of the repetition stack

我喜欢您将压1入堆栈的技巧,将未乘的动作与乘的相同。您能否解释一下有关如何处理各种堆栈的更多信息?特别是,“将rep栈带到顶部”怎么办?
xnor

@xnor,这是内建参考。\交换堆栈中的前两个项目。
彼得·泰勒

谢谢,我不明白每个堆栈元素都是其自己的堆栈。我在想象单个串联的堆栈。
xnor 2014年

@xnor,不是每个堆栈项都是自己的堆栈;这是因为重复堆栈存储为数组或字符串(仍然是数组,但是某些内置函数对其进行了不同处理)。调试演示,该演示在主循环结束之前打印GS堆栈的内容。
彼得·泰勒

4

Javascript- 162152字节

缩小:

F=I=>{L=c=>S.length;p=c=>L()?S.shift():d=>{};S=[(x=>/\d/.test(x)?(c,b)=>{for(c=p(),b=x;b--;)c();}:c=>s+=x)(m)for(m of I)];for(s='';L();)p()();return s;}

展开:

F = I => {
    L = c => S.length;
    p = c => L() ? S.shift() : d => {};
    S = [ (x => /\d/.test( x ) ?
        (c,b) => {
            for( c = p(), b = x; b--; )
                c();
        } : c =>
            s += x
        )(m) for( m of I ) ];

    for( s = ''; L(); )
        p()();

    return s;
}

我猜想基于堆栈的高尔夫语言会在这方面失败,因为它基本上是函数堆栈中的一种练习。:P

样本输出

F('3N2BC3XY2')
"NNNBBCXXXY"

F('WA23G3GA')
"WAGGGGGGAAA"

F('A2A323AB2CD2D2E3ABC')
"AAAAAABBBCCDDDDEEAAABBBC"

F('322322ABCDEFGHIJKLMN')
"AABBCCDDEEEFFGGHHIJKLMN"

F('FY')
"FY"

F('')
""

1
您对卡作为功能的解释有多精确,我感到惊讶。我期望有一个堆栈,但不是函数的文字调用堆栈!虽然没有多次调用函数的简洁方法?更好的是,可以无数次地2/3一起处理案件吗?
xnor

@xnor:我认为这很聪明。;)至于您的建议,您的直觉是正确的。我将这两种情况结合起来节省了10个字节。理想情况下是18,但我偶然发现了我认为是Firefox中的错误的信息。我应该能够x直接进行操作,而无需先将其复制到b范围为内部lambda 的变量中,但是Firefox无法正确评估循环条件。具体来说,x变为负数并且浏览器挂起。尝试替换, b = x; b--;; x--;并运行输入A2A323AB2CD2D2E3ABC。如果有人读过这篇文章可以找出原因,...
COTO 2014年

...我很想知道。也许我缺少有关应该如何使用闭包的信息。
COTO 2014年

3

C,115111字节

使用标准输入/输出。

通过使用memset堆栈并使堆栈朝另一个方向保存,从而节省了4 。

char*i,X[222],*s=X+99;main(){for(gets(i=X);*i;i++)*i<55?s=memset(s-*s,*i-49,*s+1):putchar(*i)**s?--*s,--i:++s;}

不打高尔夫球

#include <stdio.h>
#include <stdlib.h>
char I[99], S[99], *i = I, *s = S+66;
int n;
int main()
{
    gets(I);
    for(;*i;)
    {
        if(*i < '5') {
            n = *s;
            s[0] = s[1] = s[2] = *i - '1';
            s += n;
            i++;
        } else {
            putchar(*i);
            if(*s)
                --*s;
            else
                --s, ++i;
        }
    }
    return 0;
}

0

巨蟒(84)

S='1'*99
R=''
for c in input():q=int(S[0])*c;S=q*(c<'A')+S[1:];R+=q*(c>'3')
print(R)

S是乘数的堆栈(如果在前,则为顶)。已使用足够的进行了初始化,1以处理未乘的动作。

根据当前操作c是否通用,我们将其相乘结果添加到输出R或乘数堆栈中S

一切都表示为字符串而不是字符列表。由于字符串是不可变的,因此很遗憾,我们无法pop在它们上使用或分配元素。

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.