我的4音符音乐盒可以播放那首歌吗?


51

我有一个曲柄操作的音乐盒,可以播放四个音符。当我转动曲柄时,它会根据曲柄的位置和转动的方向拔出四根弦之一。当曲柄向北旋转时,此框(其字符串从1到4编号)如下所示:

1  |  2
   |
   O   

4     3

从那里,我可以顺时针旋转曲柄以拔出#2弦,然后将曲柄指向东:

1     2

   O---   

4     3

或者,我也可以从北方逆时针旋转曲柄以播放#1弦,并以指向西的曲柄结尾:

1     2

---O   

4     3

然后,该框可以在任何给定时间播放两个音符之一:顺时针方向可用的下一个音符或逆时针方向的下一个音符。

挑战

您面临的挑战是编写一个程序或函数,该程序或函数接受非空的音符值字符串(即数字14),并确定是否有可能在音乐盒上播放该音符序列。产生真实或错误的结果以指示输入的可播放性或不可播放性。

一些注意事项:

  • 输入不对初始开始位置做任何假设。输入214(从东开始并严格按逆时针方向移动)和234(从北开始并严格按顺时针方向移动)输入均有效。

  • 每次发出音符后,曲柄可在任一方向上自由移动。33333通过在一个字符串上来回移动,可能会产生一系列相同的音符(例如)。该系列赛1221441完全可以玩(从西开始,顺时针移动两步,然后逆时针移动三步,然后顺时针移动两步)。

样品

一些true情况:

1
1234
1221
3333
143332
22234
2234
22214
1221441
41233

一些false情况:

13     (note 3 is never available after note 1)
1224   (after `122`, the crank must be north, so 4 is not playable)
121    (after `12` the crank is east; 1 is not playable)
12221  (as above, after `1222` the crank is east)
43221  

输入可以是包含引号的字符串吗?
Luis Mendo

@LuisMendo当然,我会允许的-我对您的算法感兴趣,而不是让您跳入篮球来获取输入。无论如何,社区之间存在非正式共识,那就是一般都可以:带或不带“”的字符串输入?
apsillers

1
我不知道 感谢您的链接!
路易斯·门多

1
@AJMansfield不,解决方案应允许任意多个循环。当然,如果某些输入导致您的代码超出语言解释器或计算机内存的限制,那很好(因为它仅受您实际拥有的内存或解释器允许的内存量限制),但是您的解决方案不应施加额外的限制曲柄移动多少或多少次。
apsillers

1
这项挑战赢得了2016年PPCG最佳产品的“ 看起来并不那么简单”类别。不幸的是,我们无法给予挑战以奖励,但是Zgarb为纪念您写了一个挑战。恭喜你!
马丁·恩德

Answers:


9

Pyth,30 27字节

f!-aVJ.u%-ysYN8zTtJ,1 7cR2T

这是想法:

 1.5  1  0.5

  2       0

 2.5  3  3.5

曲柄始终处于半整数位置c。在每一步中,我们n通过设置将其反映在整数位置注释上c = 2*n-c。如果n有效,c则以±1 mod 8进行更改。如果n无效,c则以±3 mod 8进行更改。我们累计减少输入以收集的所有值c,然后查看所有注释是否有效。我们针对的每个起始值执行此操作c,因为它比仅检查与第一个音符相邻的值短。

格式:

f
  ! -
      aV J .u
              % -
                  y s Y
                  N
                8
              z
              T
         t J
      ,
        1 
        7
  cR2 T

测试套件


18

CJam,34 31字节

8,q{~2*f{_@-_zF8b&,@@+8,=*}0-}/

在手机上进行了此操作,因此稍后我将不得不做出解释。如果是真的,输出是非空的。

在线试用 | 测试套件

说明

新的代码稍微改变了布局:

2    3    4

1    .    5

0/8  7    6

偶数对应于字符串位置,奇数对应于曲柄位置。

这是发生了什么:

8,           Create the range [0 1 .. 7] of possible starting positions
             We can leave the string positions [0 2 4 6] in since it doesn't matter
q{ ... }/    For each character in the input...
  ~2*          Evaluate as integer and double, mapping "1234" -> [2 4 6 8]
  f{ ... }     Map over our possible current crank positions with the string
               position as an extra parameter
    _@-          Calculate (string - crank), giving some number in [-7 ... 7]
    _z           Duplicate and absolute value
    F8b          Push 15 base 8, or [1 7]
    &,           Setwise intersection and get length. If (string - crank) was in
                 [-7 -1 1 7] then the move was valid and this evaluates to 1, otherwise 0
    @@+          Calculate ((string - crank) + string)
    8,=          Take modulo 8, giving the new crank position. x%y in Java matches the
                 sign of x, so we need to do ,= (range + index) to get a number in [0 .. 7]
    *            Multiply the new crank position by our previous 0 or 1
  0-           Remove all 0s, which correspond to invalid positions

然后将自动在最后打印纸叠。任何可能的结束位置将在输出中,例如,对于输入1,输出为31,这意味着曲柄可以朝左或朝上结束。

如果只有CJam的过滤器带有额外的参数...


编辑:暂时回滚,但我确信这29字节有效:

8,q{~2*f{_@-_7b1#@@+8,=|}W-}/

37
每当有人用诸如cjam之类的困难语言回答并说“在手机上做到这一点”时,我都会在里面死掉
Dennis van Gils 2016年

2
他可能是想说文字是通过电话输出的,但这是在脑海中完成的。
尼尔森

7

Haskell,93 88 87字节

any(all(\(a,b:c)->1>mod(a!!1-b)4).(zip=<<tail)).mapM((\a->[[a,a+1],[a+1,a]]).read.pure)

这将得出一个匿名函数,该函数接受一个字符串并返回一个布尔值。测试套件在这里。

说明

这个想法是,如下图所示,右边的lambda将一个数字映射a[[a,a+1],[a+1,a]],这两个可能的“动作”使该数字发生曲柄:

  1 (2) 2

(1/5)  (3)

  4 (4) 3

在主要的匿名函数中,我们首先执行mapM((...).read.pure),该函数将每个字符转换为整数,将上述lambda应用于该整数,然后选择两个移动之一,并返回所有结果移动序列的列表。然后,我们检查这些序列中的任何一个是否具有以下特性:每次移动的第二个数字等于下一个模4的第一个数字,这意味着这是一个物理上可能的序列。为此,我们zip分别移动序列及其tail,检查对的条件all,然后查看any序列的计算结果是否为True



6

视网膜127109字节

^((1|2)|(2|3)|(3|4)|(4|1))((?<2-5>1)|(?<5-2>1)|(?<3-2>2)|(?<2-3>2)|(?<4-3>3)|(?<3-4>3)|(?<5-4>4)|(?<4-5>4))*$

相应地打印01

在线尝试!(这是一个经过稍微修改的版本,它在输入中标记了所有匹配项,而不是打印01。)

我尝试提出一种优雅的算法,但最初的几次尝试都无法绕开回溯...并且实现回溯很烦人...所以我使用了一种为我做回溯的语言,我只需要编码有效的解决方案。不幸的是,编码是相当冗长和相当多余的...我敢肯定,这可以缩短。

当我尝试弄清楚某些东西时,如果有人想弄清楚它是如何工作的,下面是一个更具可读性的版本:

^
(
    (?<a>1|2)
  | (?<b>2|3)
  | (?<c>3|4)
  | (?<d>4|1)
)
(
    (?<a-d>1) | (?<d-a>1)
  | (?<b-a>2) | (?<a-b>2)
  | (?<c-b>3) | (?<b-c>3)
  | (?<d-c>4) | (?<c-d>4)
)*
$

这是一个提示:

1  a  2

d  O  b

4  c  3

6

MATL57 55字节

1t_hjnZ^!t1tL3$)2_/wvG1)UGnl2$Ov+Ys.5tv3X53$Y+4X\G!U=Aa

这将使用当前版本(10.2.1),它比此挑战要早。

编辑(2017年1月17日):由于语言的更改,v需要替换为&vtL3$)Y)(此外,还可以进行其他一些改进)。以下链接包括这两个修改

在线尝试!

说明

这基于我最喜欢的两种代码高尔夫工具:蛮力卷积

该代码定义了路径,接着曲柄在坐标中0.51.5等。每个数字说明音符间的曲轴的位置。该代码首先构建一个路径数组,其中包含所有可能的路径,这些路径以输入字符串的第一个音符开头。每个路径都是此数组中的一列。这是蛮力部分。

从该路径数组中获得一个音符数组,其中每一列都是可弹奏的音符的可实现序列。例如,从位置0.5移到1.5会产生音符1。这包括取位置之间的平均值,然后应用模4运算。沿每一列的移动平均值是通过2D 卷积完成的

最后,程序检查note数组的任何列是否与输入一致。

1t_h        % row array [1, -1]
j           % input string
nZ^!        % Cartesian power of [1, -1] raised to N, where "N" is length of string
t           % duplicate
1tL3$)      % extract first row
2_/         % divide by -2
wv          % attach that modified row to the top of Cartesian power array
G1)U        % first character of input string converted to number, "x"
Gnl2$O      % column array of N-1 zeros, where N is length of input
v           % concat vertically into column array [x;0;0...;0]
+           % add with singleton expansion
Ys          % cumulative sum along each column. Each column if this array is a path
.5tv        % column array [.5;.5]
3X5         % predefined string 'same' (for convolution)
3$Y+        % 2D convolution of path array with [.5;.5]
4X\         % modified modulo operation. This gives note array with values 1,2,3,4
G!U         % column array of input string characters converted to numbers
=Aa         % true if any column of the note array equals this

5

佩斯,43

Km-R2sMdc`M%R4-VJjQTtJ`0|Fm!s-VKdCm_B^_1dlK

测试套件

这可能很容易打高尔夫球,也不是打高尔夫球的最佳算法(我希望列举所有路径会更短?)...无论如何,如果您发现算法有任何错误,请告诉我,我认为它应该可以,但是我以前错了!

我将使用的示例输入来说明我的算法1221。此程序首先将数字映射到其后继者,如下所示:[[1,2],[2,2],[2,1]]。然后它得到他们之间的分歧MOD 4(Pyth获取的右参数的标配结果%,所以这始终是正的)[3,0,1]。然后将结果分割开0并从中2减去:[[1],[-1]]

设置完成后,我们将创建一个列表[-1,1,-1...]及其取反[1,-1,...],它们的长度与之前得到的数组的长度相同。然后,对于这些列表中的每一个,在列表的元素和在先前步骤中生成的列表之间执行按设定的减法。然后,如果任何一个结果仅包含空列表,则输出true。


您将“结果拆分为0”是什么意思?特别是,你会得到12212211221441
尼尔

1
@Neil 1221221是错误的,1221441总体上是真实的,但是如果我理解您想要算法那一步之后的结果吗?如果这是它给人的情况:从[3, 0, 1, 3, 0, 1][[3], [1, 3], [1]][3, 0, 1, 1, 0, 3][[3], [1, 1], [3]]。让我知道是否您需要其他说明:)
FryAmTheEggman

我想我比以前更困惑,所以请您完成以下两个示例以说明如何获得(正确)结果?
尼尔

1
@Neil当然,没问题:)从那里,我们做减法得到:[[1], [-1, 1], [-1]][[1], [-1, -1], [1]]从这里,你可以看到,第一个没有列出之间交替-11,而其他清单呢,得到最终的结果。该算法有点笨拙,但是基本上是将方向更改映射到0,方向映射为+/-1,然后检查是否未发生跳动且方向是否有意义。
FryAmTheEggman

哦,所以我缺少的一点是,每个拆分列表必须包含相同的值,并且这些值必须交替。谢谢!
尼尔

4

Matlab,279180字节

o=eye(4);a=input('')-'0';M=[o,o(:,[4,1:3]);o(:,[2:4,1:4,1])];x=2;for p=[a(1),mod(a(1),4)+1];for k=a;i=find(M*[o(:,k);o(:,p)]>1);if i;p=mod(i-1,4)+1;else;x=x-1;break;end;end;end;x>0

相当懒惰的解决方案,但我能想到的最短。我创建了一个特殊的矩阵:在对拔除器的状态和要拔除的最后一个字符串进行编码时,它将返回一个向量,该向量对拔除器的新位置进行编码,以及是否可以进行先前的拔除。现在,我们从两个可能的开始位置循环播放所有音符,看看其中之一是否产生可播放的旋律。可以打更多的高尔夫球。

扩展并说明了来源:

o=eye(4);
a=input('')-'0';

% encoding of plucker/notes
%      1
%   1     2
%4           2
%   4     3
%      3
%

M=[...
%12 3 4 1 2 3 4 <
1,0,0,0,0,1,0,0; %1  k = current note
0,1,0,0,0,0,1,0; %2  
0,0,1,0,0,0,0,1; %3  
0,0,0,1,1,0,0,0; %4  
0,0,0,1,0,0,0,1; %1  p = current position of plucker
1,0,0,0,1,0,0,0; %2
0,1,0,0,0,1,0,0; %3
0,0,1,0,0,0,1,0];%4
% the vector we multiply with this matrix has following structure,
% the k-th and the p+4 th entries are 1, the rest 0
% when we multiply this vecotr with this matrix, we get a vector with an
% entry of value 2 IF this is a valid move ( mod(positionOfThe2 -1,4)+1 is
% the position of the plucker now)
% or only entries less than 2 it is impossible
x=2;  %number of "chances" to get it right
for p=[a(1),mod(a(1),4)+1] %check both starting values;
    for k=a;                %loop throu the notes
        size(M);

        c = M * [o(:,k);o(:,p)];
        i=find(c>1);               %did we find a 2?
        if i;
           p=mod(i-1,4)+1;         %if yes, valid move
        else;
            x=x-1;                 %if no, invalid, 
            break;
        end 
    end
end
x=x>0 %if we failed more than once, it is not possible

4

ES6,104个 100字节

s=>!/13|24|31|42|3[24]{2}1|4[13]{2}2|1[24]{2}3|2[13]{2}4|(.).\1/.test(s.replace(/(.)(\1\1)+/g,"$1"))

编辑:由于@DigitalTrauma,节省了4个字节。

由于我以前的方法有缺陷,因此这是一个完整的重写。

首先,根据运行中是否有奇数或偶数,将所有数字减为1或2。然后,我查找所有非法组合:

  • 13|24|31|42 (对面)
  • 3[24]{2}1因为32213441是非法的
  • 同样的4xx21xx3并且2xx4其中x要么是所缺失的数字
  • (.).\1因为类似121的东西是非法的(111已经减少到1以前)

如果没有非法的配对或“三元组”,则整个字符串都是合法的(通过归纳证明作为练习是多余的,因为这是深夜)。

我试图3[24]{2}1|1[24]{2}3使用否定的前瞻性断言来简化,但事实证明它要更长一些。


f("1122") => true@DigitalTrauma
Conor O'Brien

@CᴏɴᴏʀO'Bʀɪᴇɴ我认为这没错。另一方面,我意识到f("1221221")输出错误的答案,因此我必须重新考虑。
尼尔

包含一个测试套件总是很不错,“ 43221”失败了:jsbin.com/vafitotequ/1/edit?js,console
Pavlo

@Pavlo哎呀,我打过高尔夫球[24][24](2|4)\1但是我没有进行充分的测试。对于那个很抱歉。
尼尔

你能高尔夫球[24][24][24]{2}
Digital Trauma

2

JavaScript(ES6),80个字节

s=>[r=0,1,2,3].map(i=>[...s].map(n=>n-1-i%4?n%4-i%4?v=0:i+=3:i++,v=1)|v?r=1:0)|r

说明

i%4 是当前的曲柄位置:

    1 (i%4 == 1) 2   

(i%4 == 0) (i%4 == 2)

    4 (i%4 == 3) 3   

缩进和注释

s=>
  [r=0,1,2,3].map(i=> // i = crank position, test for i starting at 0 to 3, r = result
    [...s].map(n=>    // for each note n
      n-1-i%4?        // if n is not at the position after i
        n%4-i%4?      // if n is not at the position before i
          v=0         // set the result of this test to invalid
        :i+=3         // else i-- (+3 used because i%4 would break for negative values)
      :i++,           // else i++
      v=1             // v = result of test, initialise to 1 (valid)
    )
    |v?r=1:0          // if the test returned true, set the result to true
  )
  |r                  // return the result

测试

var solution = s=>[r=0,1,2,3].map(i=>[...s].map(n=>n-1-i%4?n%4-i%4?v=0:i+=3:i++,v=1)|v?r=1:0)|r
<input type="text" value="1221441" oninput="result.textContent=solution(this.value)" />
<pre id="result"></pre>


做得很好。您能解释一下|这种情况下的工作原理吗?
巴甫洛

1
@pavlo谢谢。这是一种较短的书写方式(x.map(...),v)。之所以有效,是因为map返回的数组强制转换为0and 0|v == v
user81655 '02

2

的Lua146 142 108 162 159 149 144 135 132 118 113字节

z,q,s=0,0,io.read()for i in s:gmatch'.'do t=i-z if 2==math.abs(t)or t==q then return''end q=-t z=i end return 2>1

给定介于1和4之间的数字字符串,则返回true或false。(不处理任何数据或超出范围的数字。

只需跟踪最后一个动作是什么,然后检查该动作是否是最后一个动作的反转(即,IE,121或12221),或者距离移动是否超过可能。

编辑1

保存了6个字节。我忘了if (int) then如果int不为零,则返回true。

从而:

if t~=0 then

更改为:

if t then

还通过重组节省了几个字节。

编辑2

我正在慢慢弄清楚。我一直在这里阅读文档:http : //www.lua.org/pil/其中最有用的高尔夫页面之一是http://www.lua.org/pil/3.3.html

特别地,这非常有帮助:

像控制结构一样,所有逻辑运算符都将false和nil视为false,将其他任何事物视为true。

对我来说,这意味着我可以继续删除我对q的声明(声明最初设置为0),因为在设置它之前它将被视为“ false”。所以我通过这个节省了更多的字节。

值得一提的另一件事,尽管我不使用它,但是如果您想在Lua中交换值,则可以简单地进行操作 a,b=b,a而无需使用临时变量。

编辑3

因此,通过一些巧妙的重构以及一个新功能,我的字节数又减少了9个。

接收输入的最佳模式

如果您需要读入一个数字列表并一次对其进行操作,则可以使用:

for x in string:gmatch('.') do
    print(x) --This is our number
end

与使用string:sub的替代方案进行比较时,您可以看到golf(或一般用途)的值:

for x=1,string:len() do
    print(string:sub(x,x)) --This is our number
end

重组函数或字符串

第二件事,如果您在一行上有多个声明,并且其中一个值是一个函数,或者您遇到了将数字与此类函数的结果进行比较的条件:

x,y,z=io.read(),0,0 print('test')

if math.abs(x)==2 then

通过对其进行重组,使右括号成为条件或声明中的最后一个字符,您可以像这样剪切出一个字符:

y,z,x=0,0,io.read()print('test') --Notice no space

if 2==math.abs(x)then --If we put the '2' first in the conditional statement, we can now remove a space character

等于“ True”或“ False”而不是“ True”或“ False”的返回条件

我发现了一种半有趣的方式来进一步减少字节数。如果需要返回true或false,则可以返回一个语句,该语句等于true或false,其自身的字符少于“ true”或“ false”。

例如,比较:

return true
return false

至:

return 2>1
return 1>2

121应该输出false。
lirtosiast

啊没关系。我懂了。即将修复
Skyl3r

如果您尚未在Lua打高尔夫球技巧中添加一些Lua技巧,则可能会感兴趣。
apsillers

2

MATL,49个字节(非竞争1

1.答案(ab)使用的是对较新版本的MATL进行较不严格的索引编制,并且在发布此挑战时将不起作用。

dt~aX`tt~f1)q:)w3MQJh)_ht~a]tT-3hX|n2=wT_3hX|n2=+

在线尝试!

我在2016年PPCG最佳展会上看到了这一挑战,并发现这可以使用我最喜欢的运算符

d

或者,diff在MATLAB / Octave中(我将在解释中自由使用MATLAB / Octave术语,因为它对于人类来说更容易阅读)。该命令计算矢量或字符数组中元素逐元素的差。

对于此问题,差异表现出有趣的模式。注意

方向的改变必须意味着音符被演奏两次

对于差异模式(忽略 1-4过渡),这意味着

登录更改之间diff(input)必须有奇数个零。相反,不允许偶数个零后改变符号。


我通过为每个数组找到第一个零来实现这一点。我修剪掉零,然后将其后的所有元素乘以-1。对于最终结果,这意味着所有元素必须具有相同的符号。当然,有小问题,-3等于+1,和2一般不允许被。我通过使用来获取结果的集合联合[1 -3]并检查其大小是否为2(即,没有不允许的元素通过联合“进入”集合)来解决此问题。重复[-1 3],并检查其中一个(或两个,对于1长度输入)是否为true。

d                                % Difference of input
 t~a                             % Check if any element equals 0
    X`                     t~a]  % Start while loop, ending in the same check
       t~                           % Get a new vector, logical negated to find zeroes.
          f1)                       % Find the position of the first zero. 
      t         q:)                 % Decrement by 1, to index all elements before that zero.
                   w3MQJh)          % Push the result of 'find', but increment to get all elements after.
                         _h         % Multiply the second half by -1, and concatenate horizontally.

  T-3hX|n2=                      % Check if set union with [1 -3] is size 2
 t        wT_3hX|n2=             % Check if set union with [-1 3] is size 2
                    +            % Logical OR. 

@LuisMendo谢谢。我真的需要继续阅读M,上次尝试时,它的工作原理与预期的不同,因此我暂时忽略了它。说这一定是正确的,3M因为这样我就得到了not ),not :but 的输入qw因为这不是正常函数,所以跳过)?
桑奇斯(Sanchises)'17年

对,就是这样。w被跳过,因为它不是正常功能。没有输入的普通功能也将被跳过
Luis Mendo

2

的Python(3.5)160 151 150个字节

递归解决方案

def f(s):g=lambda s,c:s==''or g(s[1:],(c[:4]*2)[(s[0]==c[0])*2+1:])if s==''or s[0]in c[:2]else 0;return any([g(s,"1234123"[i:])for i in range(4)])

没有lambda的非高尔夫

def f(s):
    def g(s,c):
        if s=='' or s[0] in c[:2] :
            return s=='' or g(s[1:],(c[:4]*2)[(s[0]==c[0])*2+1:])
        else:
            return False
    return any([g(s,"1234123"[i:]) for i in range(4)])

我旋转所有盒子而不是曲柄。曲柄位置在c字符串的第一个字符和第二个字符之间。我需要测试所有曲柄的开始位置。

技巧用来旋转琴弦

在python(s[i:]+s[:i])中旋转字符串的常用方法也需要重复索引和字符串。在这种情况下,我复制字符串并裁剪第一个字符。

(c*2)                        # duplicate the string
     [(s[0]==c[0])*2+1       # test that return 1 if firsts characters match 3 instead 
                      :]     
                        [:4] # crop again to have a 4 characters string

测试用例

[f(i) for i in ["1", "1234", "1221", "3333", "143332", "22234", "2234", "22214", "1221441", "41233", "13", "1224", "121", "12221", "43221"]]
[True, True, True, True, True, True, True, True, True, True, False, False, False, False, False]

1
您可以在删除空格3"[i:]) for
暴民埃里克(Erik the Outgolfer)'17年

@EriktheOutgolfer,谢谢,我删除了它。
Erwan


1

JavaScript(ES2015), 110 95

p=(s,d)=>(h=s[0],t=s.slice(1),g=t[0],!g||(d?g==h?p(t,-d):g%4==(h-d)%4&&p(t,d):p(s,1)||p(s,-1)))

Neil保存了15个字节!原始版本已发布:

p = (s, d) => {
  h = s[0]
  t = s.substr(1)

  if (!t[0]) return true
  if (!d) return p(s, 1) || p(s, -1)
  if (t[0] == h) return p(t, d*-1)
  if (t[0] == (h-d > 4 ? 1 : h-d || 4)) return p(t, d)

  return false
}

测试:https//jsbin.com/cuqicajuko/1/edit?js,console


1
为您节省了17个字节:(s,d)=>(h=s[0],t=s.slice(1),g=t[0],!g||(d?g==h?p(t,-d):g%4==(h-d)%4&&p(t,d):p(s,1)||p(s,-1)))
尼尔

虽然还不如@ user81655的答案那么短。
尼尔

1

图灵机代码,395字节

0 1 _ r a
0 2 _ r b
0 3 _ r c
0 4 _ r d
a 1 _ r a
a 2 _ r E
a 3 _ r h
a 4 _ r S
b 1 _ r W
b 2 _ r b
b 3 _ r S
b 4 _ r h
c 1 _ r h
c 2 _ r N
c 3 _ r c
c 4 _ r W
d 1 _ r N
d 2 _ r h
d 3 _ r E
d 4 _ r d
N 1 _ r W
N 2 _ r E
N _ _ r r
N * _ r h
E 2 _ r N
E 3 _ r S
E _ _ r r
E * _ r h
S 3 _ r E
S 4 _ r W
S _ _ r r
S * _ r h
W 4 _ r S
W 1 _ r N
W _ _ r r
W * _ r h
h _ 0 r halt
h * _ r h
r _ 1 r halt

在线尝试!

这基本上是一种基于状态的方法:

  • 初始状态为0。
  • abc,和d是“犹豫不决的状态”,只有发生在开始
  • NES,和W是“决定状态”,显然站立N正高,EAST,SOUTH和WEST。

1

Thue,203个字节

我想不起来怎么打高尔夫球。

0::=:::
>11::=>1
>22::=>2
>33::=>3
>44::=>4
>12::=b
>21::=d
>14::=c
>41::=a
>23::=c
>32::=a
>34::=d
>43::=b
a1::=d
a2::=b
b2::=a
b3::=c
c3::=b
c4::=d
d4::=c
d1::=a
a<::=~n
b<::=~e
c<::=~s
d<::=~w
::=
>0<

如果音符序列可行,将输出结束方向,否则输出将为空。


1

Prolog(SWI),117字节

a(N,P):-P=N;N=1,P=4,!;P is N-1.
m([A,B|C],[X,Y|Z]):-a(A,X),a(B,X),a(B,Y),X\=Y,m([B|C],[Y|Z]).
m([_],_).
p(N):-m(N,_).

定义一个谓词p,该谓词在可播放的输入(作为整数列表)上成功,而在不可播放的输入上失败。在线尝试!

说明

a定义音符N和曲柄位置之间的邻接关系P。我们将位置p定义在音符pp + 1之间。因此,位置与音符Niff 相邻

  • 它等于NP=N); 要么
  • 音符为1,位置为4(N=1,P=4);要么
  • 以上情况不正确(!),位置等于N-1P is N-1)。

m获取一个音符列表,并尝试生成将播放这些音符的位置列表。A是刚刚演奏的音符,B是即将演奏的音符;X是当前曲柄位置,Y是下一个曲柄位置。如果有效,此举是有效的

  • 刚演奏的音符与当前曲柄位置(a(A,X))相邻;
  • 要播放的音符也与当前曲柄位置(a(B,X))相邻;
  • 即将播放的音符与下一个曲柄位置(a(B,Y))相邻;和
  • 两个曲柄位置不相等(X\=Y)。

如果所有这些都成立,请递归。如果我们成功找到任何一个音符(m([_],_)),便可以播放音符序列。

对于这个问题,我们只关心是否存在一系列移动,因此我们定义p调用m并丢弃生成的曲柄位置列表。

参见非公开版本并在此处验证所有测试用例。

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.