首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >打印一首乐曲内部间隔的大小。

打印一首乐曲内部间隔的大小。
EN

Code Golf用户
提问于 2012-04-06 21:14:48
回答 3查看 489关注 0票数 10

背景

在西方音乐中,每个音乐音符都有一个指定的名字。在每个八度范围内,有12个独特的音符按以下顺序排列:"C、C#/Db D# D#/Eb E F#/Gb G# G#/Ab #/Bb B C",其中最后的C是第一个八度以上的一个八度。

为了区分不同八度音阶的音符之间的差异,在音符名称的末尾附加一个数字(针对这个限制在一个数字上的挑战)。因此,C5是高于C4一个八度的音符。Bb6高于B5。

一个重要的事实是,B5和C6是彼此相邻的音符,而C0和B9是最低音和最高音符。

在任意两个音符之间,有一个距离,即它们之间的半音数。Bb4比B4低一个半个,这本身就是比C5低一个半个。一个八度有12个半音,所以Bb4与A#3的距离是12,因为它是一个八度以上的音阶(注意一个音符最多可以有两个名字)。

挑战

您的挑战是编写尽可能最短的程序,该程序可以从STDIN获取一个音乐音符列表,并打印到STDOUT的间隔更改列表。

输入将是一个空格分隔的音乐音符列表。每个音符将包括一个大写字母and,一个可选的b或#符号,以及一个单数数字。您将不必处理E#/Fb或B#/Cb。示例输入:

代码语言:javascript
复制
C4 D4 E4 F4 G4 A4 B4 C5 C4

输出将是一个空格分隔的整数列表,表示每个连续音符之间的距离,总是以+或-作为前缀,以显示该音符相对于前面的音符是上升还是下降。输出的数字总是比输入的音符少一个。上面输入的输出示例:

代码语言:javascript
复制
+2 +2 +1 +2 +2 +2 +1 -12

一些更多的示例输入:

代码语言:javascript
复制
E5 D#5 E5 B4 E5 F#5 E5 B4
C0 B0 Bb1 A2 G#3 G4 F#5 F6
G4 Ab4 Gb4 A4 F4 A#4

及其相应的产出:

代码语言:javascript
复制
-1 +1 -5 +5 +2 -2 -5
+11 +11 +11 +11 +11 +11 +11
+1 -2 +3 -4 +5

规则和限制

  1. 胜利者由源代码中的字符数决定。
  2. 您的程序应该只包含可打印的ASCII字符。
  3. 您不允许使用任何与音乐或声音相关的内置功能。
  4. 除此之外,还适用标准的高尔夫规则。
EN

回答 3

Code Golf用户

发布于 2012-04-07 09:19:59

GolfScript,61

代码语言:javascript
复制
" "/{)12*\{"bC#D EF G A B"?(+}/}%(\{.@-.`\0>{"+"\+}*\}/;]" "*
票数 6
EN

Code Golf用户

发布于 2012-04-09 10:56:57

C,123个字符

基于左撇子的解决方案,并作了一些改进。

代码语言:javascript
复制
main(c,b,d)
    char*b;
{
    while(d=c,~scanf("%s",b)?c=-~*b*1.6,c%=12,c+=b[~b[1]&16?c+=1-b[1]/40,2:1]*12:0)
        d>1&&printf("%+d ",c-d);
}

一些我认为值得提及的技巧:

  1. argv[0] (这里称为b)是指向程序名称的指针,但在这里用作划痕缓冲区。我们只需要4个字节(例如C#2\0),所以我们就足够了。

  1. c是参数的数量,所以它以1开头(当运行时没有参数)。我们用它来防止第一轮印刷。

可能的问题-- c+=b[..c+=..]是一种--很奇怪。我不认为这是未定义的行为,因为?:是一个序列点,但也许我错了。

票数 3
EN

Code Golf用户

发布于 2012-04-09 17:52:12

因子,303个字符

代码语言:javascript
复制
USING: combinators formatting io kernel math regexp sequences ;
f contents R/ [#-b]+/ all-matching-slices
[ 0 swap [ {
{ [ dup 48 < ] [ drop 1 ] }
{ [ dup 65 < ] [ 48 - 12 * ] }
{ [ dup 98 < ] [ "C-D-EF-G-A-B" index ] }
[ drop -1 ]
} cond + ] each
swap [ over [ - "%+d " printf ] dip ] when* ] each drop

带着评论,

代码语言:javascript
复制
! combinators => cond
! formatting => printf
! io => contents
! kernel => swap dup drop over dip when*
! math => < - * +
! regexp => R/ all-matching-slices
! sequences => each
USING: combinators formatting io kernel math regexp sequences ;

f       ! Push false, no previous note value.

! Find notes (as string slices) in standard input. The golfed regexp
! R/ [#-b]+/ matches all notes and no whitespace.
contents R/ [#-b]+/ all-matching-slices

! For each string slice:
[
    0       ! Push 0, initial note value.
    swap    ! Move note slice to top of stack, above note value.

    ! For each Unicode codepoint in note:
    [
        ! Convert the Unicode codepoint to its value in semitones.
        ! For golf, [ 48 ] is shorter than [ CHAR: A ].
        {
            ! Sharp # {35} has 1 semitone.
            { [ dup 48 < ] [ drop 1 ] }
            ! 0-9 {48-57} has 0 to 9 octaves (1 octave = 12 semitones).
            { [ dup 65 < ] [ 48 - 12 * ] }
            ! A-G {65-71} has 0 to 11 semitones.
            { [ dup 98 < ] [ "C-D-EF-G-A-B" index ] }
            ! Flat b {98} has -1 semitone.
            [ drop -1 ]
        } cond

        +       ! Add semitones to cumulative note value.
    ] each

    swap    ! Move previous note value to top of stack.
    ! When there is a previous note value:
    [
        ! Keep current note on stack.
        over [
            ! Compute and print interval.
            - "%+d " printf
        ] dip
    ] when*
    ! Current note replaces previous note at top of stack.
] each

drop    ! Drop previous note, so stack is empty.

对于此脚本,“空格分隔列表”可以在元素之间有一个或多个空格,在开头或结尾有0或多个空格。这个脚本确实在输出结束时打印一个额外的空间,但它也在输入结束时接受额外的空格(或换行符)。

如果我采用一个更严格的定义,即“空格分隔列表”在元素之间只有一个空格,在开始或结束时有0个空格,那么我可以将contents R/ [#-b]+/ all-matching-slices缩短为contents " " split (使用splitting而不是regexp)。但是,我需要添加更多的代码来防止输出结束时的额外空间。

如果我使用不推荐的单词dupd,我可以将over [ - "%+d " printf ] dip缩短为dupd - "%+d " printf,保存8个字符。我不使用反对词,因为它们“打算很快被移除”。

票数 1
EN
页面原文内容由Code Golf提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codegolf.stackexchange.com/questions/5410

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档