大二分法


15

给定一个和弦列表,将其标记为“大”或“小”。

输入值

输入将是和弦列表,每行一个,由3个音符隔开。每个便笺将由大写的便笺名称(A- G)和可选的偶然的(#b)组成。和弦可以以任何反转(即音符可以以任何顺序)。

输出量

如果和弦是大和弦,则输出“ Major”。如果和弦较小,则输出“ Minor”。如果和弦既不是大和小,则输出空白行。

输入值

C E G
F Ab C
C Eb Gb
E G B
Db F Ab
Bb G D
D A Gb

输出量

Major
Minor

Minor
Major
Minor
Major

测试脚本

就像我过去的一些问题一样,我再次选择了一些最初由JoeyVentero创建的测试脚本,以针对该问题提供一些测试用例:

用法: ./test [your program and its arguments]

奖赏

我可以验证符合规格,通过测试并且显然已经尝试过打高尔夫球的每条条目都会收到我的赞誉(因此,请在回答中提供使用说明)。最短的解决方案将在2012年10月13日结束之前被接受。

一点理论

对于那些没有音乐理论知识的人来说,这里有足够的信息供您竞争。

一个大和弦由三个音符组成,这三个音符由特定的半音模式分开。如果我们认为和弦的根(底音)为0,则大和弦为0-4-7模式,小和弦为0-3-7模式。有些音符是半音分开的,有些音符是音调分开的事实,使事情变得更加尴尬。来自Ab- 的半音的传播G#如下:

G#/Ab A A#/Bb B/Cb B#/C C#/Db D D#/Eb E/Fb E#/F F#/Gb G G#/Ab
  0   1   2    3     4    5   6   7    8     9    10  11  12

G#/Ab表示G#与相同的音符Ab。从中我们可以看到,和弦Ab C Eb是大和弦,那Ab Cb Eb是次要的。

为了使问题进一步复杂化,该和弦Eb Cb Ab被认为与和相同Ab Cb Eb,依此类推。这些变奏中的每一个仍然是次要的和弦。Cb Eb AbCb Ab Eb


2
我认为您的bash测试人员需要交换输入和预期的答案。
flodel

@flodel是的,您是对的。抱歉,我现在已更正它。我需要检查Powershell测试脚本是否也没有同样的问题。
Gareth 2012年

Answers:


3

GolfScript,83个字符

n%{' '%{1\{'A#BC D EF G'?+}/.}%$(+2/{~- 12%}%.(+.(+]$0=.$]10,7>?'MMaijnoorr

'>2%}%

这是一个快速的第一个解决方案。我相信这可以继续打下去。修复了flodel在注释中指出的错误之后,通过了bash测试套件。

编辑1:以较短的方式保存了5个字符,以识别规范化的大和弦和弦模式。

编辑2:受grc解决方案的启发,使用更紧凑的输出编码节省了2个字符。(谢谢!)作为副作用,代码现在在输出之后打印了一个额外的空白行,但是测试工具似乎接受了这一点,所以我认为可以。:)

运作方式如下:

  • 外循环n%{ }%n*仅将输入分成几行,在每行的大括号内运行代码,并将结果与​​换行符连接在一起。

  • ' '%将每一行拆分为一个注释数组。对于每个音符,1\{'A#BC D EF G'?+}/然后通过在字符串中搜索每个音符并将其'A#BC D EF G'位置加起来,将该音符转换为半音数字(位置在字符串中找不到的任何字符(特别是包括b)将为-1 )。(我肯定我已经看过以前使用过这个技巧。)最后,.重复每个数字,以便在循环结束时,例如,输入F Ab C已变成[9 9 0 0 4 4]

  • 然后$,我们将注释与排序,将第一个注释移至的末尾(+,然后将数组与拆分成对2/,这样现在看起来像[[9 0] [0 4] [4 9]]。然后{~- 12%}%将每对音符映射到其差模12,将示例数组转换为[9 8 7]

  • 接下来,.(+复制数组并将其元素向左旋转一个位置。我们执行两次,然后将副本收集到一个数组中],这样我们的示例现在看起来像[[9 8 7] [8 7 9] [7 9 8]]

  • 然后,我们使用对该数组进行排序,$并使用来获取第一个元素(在这种情况下[7 9 8]0=。然后,我们对该数组进行复制(.),对其进行排序($),将未排序和未排序的数组都收集到另一个数组(])中,并搜索该数组的第一个匹配项[7 8 9](写为10,7>保存两个字符) ) 在里面。

  • 这给我们或者0(如果未排序的数组是[7 8 9],因此和弦为大),1(如果未排序的数组是的排列[7 8 9],则鉴于其第一个元素必须为最小,只能为[7 9 8],使和弦成为次要)或-1(如果已排序数组也不相等[7 8 9])。

  • 然后,该数字用作字符串的起始索引"MMaijnoorr\n\n"(其中\ns作为代码中的实际换行符给出),我们从中获取该字符,然后每隔一秒将其作为输出。如果索引为-1,则从字符串的最后一个字符开始,这只是换行。


很好的解释。我在使用GolfScript时遇到了同样的困难-我可以一次调用它来进行测试,echo "G# B# Eb" | ruby golfscript.rb ilmari.gs但是如何在上面运行测试脚本呢?我尝试过,./test ruby golfscript.rb ilmari.gs但没有任何东西。(我已经给您+1了,因为它显然可以工作,但我很好奇)
Gareth 2012年

1
@Gareth:看来这是bash测试脚本中的错误-它不能正确处理多个参数。为了解决这个问题,更换args="$@"args=("$@")got=$("$cmd" "$args")got=$("$cmd" "${args[@]}")。(或只是使golfscript.rb可执行文件并以方式运行./test ./golfscript.rb chords.gs。)
Ilmari Karonen

4

Python,160

f='A#BC D EF G3453543'.find
try:
 while 1:x,y,z=sorted(map(lambda x:f(x[0])+f(x[1:])+1,raw_input().split()));print'MMianjoorrr'[f(`y-x`+`z-y`)/14:-1:2]
except:0
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.