乐谱翻译


11

给定ascii乐谱,您必须能够输出音符及其相应的长度。乐谱将包含5到15个音符(含在内),并记录在五线谱上。冷却壁由五条水平线组成,水平线由-个(减号)字符组成,并由空格隔开。五线谱的底线等效于音符“ E”。紧靠底线上方的空格线表示“ F”,并且其底线的间距高于其下方的“ E”。这继续如下。请注意,在重新从“ A”开始之前,音符只会升至“ G”。见下文:

F ----------
E           
D ----------
C           
B ----------
A           
G ----------
F           
E ----------

请注意,输入中不包含字母。音符使用ao(小写字母ooh)字符叠加在五线谱的顶部,以指示“音符头”。该音符头指示音符的频率,因此如上所述,按字母顺序表示。例如,在乐谱上的音符如下所示表示“ A”:

----

----

----
o   
----

----

像上面的“ A”一样,音符被称为“整个音符”,并且将被演奏一整拍。其他持续时间可以通过从音符中升起的“茎”指示,并且介于零和三个“标志”之间。茎由三部分组成| (竖线或竖线)字符堆叠在音符头上方。没有标志的茎被认为是“四分音符”,并且每节拍演奏四分之一。标志是\(反斜杠)字符,并位于茎的右侧。每个词干将音符演奏的时间减半。每个音符的长度为以下之一:整音符,四分音符,八分音符,十六分音符或三十秒音符。每种类型的便笺如何查找A:

--------------------

----|---|\--|\--|\--
    |   |   |\  |\
----|---|---|---|\--
o   o   o   o   o
--------------------

--------------------

将多个音符放在一起可以得到一个分数。每个注释可以被认为是四个字符宽,每个四个字符块的第一列中都有一个注释。例如 :

    |\             
----|\--|\----------
    |\  |       |\  
----o---|---o---|\--
|       o       |   
|---------------o---
|                   
o-------------------

--------------------

上面的示例按顺序包含以下音符:四分音符“ G”,三十秒音符“ D”,八分音符“ C”,整音符“ D”和十六分音符“ B”。输出中的每个注释应采用字母/长度格式,其中字母为AG,长度为与整个注释相比,注释长度的一部分。作为例外,如果注释是整个注释,则不应打印长度和/字符。输出中的每个音符应以单个空格分隔。因此,对于以上得分,您的代码应输出以下内容:

G/4 D/32 C/8 D B/16
  • 注释将在以下范围内:EFGABCDEF。请注意,只有字母需要打印,八度会被忽略。
  • 请注意,输入行数从9到12不等,因为D行或更高行上四分之一或更少时间的音符将需要更多行才能完全显示。
  • 在这种情况下,没有半音符。

最短的代码获胜(空格不计算在内)。

编辑:修复了一个输入中间距的错误。

一些样本输入:

        |\                    
----|\--|-------------------
|\  |   |                   
|---|---o---------------o---
|   o               |\      
o---------------|\--|\------
            |\  |\  |\      
------------|\--|\--o-------
            |\  o           
------------o---------------

输出:B / 8 C / 8 D / 8 E / 32 F / 32 G / 32 D


----------------o-------------------
                                o   
------------o-----------------------
                            o       
--------o---------------------------
                        o           
----o-------------------------------
                    o               
o-----------------------------------

输出:EGBDFFACE


            |\                  
            |\                  
            |\                  
------------o-------|-----------
|               o   |   |\      
|---|\--------------|---|\------
|   |               o   |\      
o---|---|\--------------o---|\--
    o   |\                  |\  
--------|\------------------|---
        o                   o   
--------------------------------

输出:B / 4 A / 8 F / 32 F / 32 EC / 4 B / 32 F / 16


为什么空白不计数?
JB,

@J:这样人们就不会倾向于只提交一行没有空格的程序。
尼尔,

1
通常对空格进行计数,不对仅用于将条目保持在合理宽度内的换行进行计数George的用户脚本使用某些语言(包括c)进行此操作。
dmckee ---前主持人小猫,

2
@Neil好吧,我现在想提交的只是一个Whitespace程序。
JB

@Neil,是的,但是然后您得到了聪明的人,他们编写了非常冗长的解决方案,将它们打包到一串空格中,然后打高尔夫球并执行解码:codegolf.stackexchange.com/questions/3203/meta-golf-challenge/…
2011年

Answers:


6

Javascript,284,279,278,225,221,220个字符(包括必要的空格)

一线(测试小提琴):

function a(c){b='',d=c.split('\n');for(e=0;d[0][e++];){f=0;for(i=0;g=d[i++];){h=g[e-1];if(h=='o')b+=(b?' ':'')+String.fromCharCode((d.length+4-i)%7+65);if(h=='|')f=f||4;if(g[e]&&g[e]=='\\')f*=2;}if(f)b+='/'+f;}return b;}

可读(测试小提琴):

function getNotes(input){
    out='',lines=input.split('\n');

    for(col=0;lines[0][col++];){
        time=0;
        for(i=0;line=lines[i++];){
            char=line[col-1];
            if(char=='o')out+=(out?' ':'')+String.fromCharCode((lines.length+4-i)%7+65);
            if(char=='|')time=time||4;
            if(line[col]&&line[col]=='\\')time*=2;
        }
        if(time)out+='/'+time;
    }
    return out;
}

1
通过删除不必要的;s并执行一些技巧,您可以使其更短。function a(c){b='',d=c.split('\n');for(e=0;d[0][e++];){for(i=f=0;g=d[i++];){h=g[e-1];if(h=='o')b+=(b?' ':'')+String.fromCharCode((d.length+4-i)%7+65);if(h=='|')f=f||4;f*=1+(g[e]=='\\');}if(f)b+='/'+f}return b}(209个字符)
JiminP

4

Perl,103个字符

(如果计算必要的空白字符,则为108)

$i=0,s/\|\\/h /g,map$b[$i++].=$_,/./g for<>;/o/&&print chr 65+(4+length$')%7,/[h|]/&&"/".4*2**y/h//," "for@b

使用空格进行演示:

$i=0,
    s/\|\\/h /g,
    map $b[$i++]. = $_, /./g
  for <>;
/o/ && print chr 65 + (4 + length $') % 7,
             /[h|]/ && "/" . 4*2**y/h//,
             " "
  for @b

请注意,我假设所有行的长度都相同(根据问题的修订版本)。

重新排列版本,并附有说明:

#!/usr/bin/env perl
# First transpose the list of lines into a list of columns.
my @b = ();               # @b[$i] will contain the characters in column $i
while (<>) {              # for each input line, do
    my $i = 0;            # start in column 0
    s/\|\\/h /g;          # replace '\|' by 'h ', to keep track of part notes in the first column
    foreach (/./g) {      # for each character, do
        $b[$i++] .= $_;   # append the character to the transposed matrix
    }
}
# Now process each column.
foreach (@b) {            # for each column, do
    if (/o/) {            # if it contains a note, then
        print chr(65 + (4 + length $') % 7);    # print the note pitch
        if (/[h|]/) {                           # if this is a part note (had |\ or just |)
            print "/", 4*2**y/h//;              # print /n where n = 2^(subdivision)
        }
        print " ";
    }
}

(旧的较长的解决方案,保留下来,因为即使更长一点也可能很有趣)

Perl,147126个字符

149131,如果您计算必要的空白)

$c=0,map{/o/?$h[$c]=E:/\\/?$d[$c-1]*=2:/\|/?$d[$c]||=4:++$h[$c];++$c}/./g for<>;print grep{s~$~/$d[$i++] ~;s~/ ~ ~;y/E-M/EFGA-F/}@h

使用空格进行演示:

$c = 0,
map { /o/ ? $h[$c]=E :
      /\\/ ? $d[$c-1]*=2 :
      /\|/ ? $d[$c]||=4 :
      ++$h[$c];
      ++$c
    } /./g for <>;
print grep {s~$~/$d[$i++] ~; s~/ ~ ~; y/E-M/EFGA-F/} @h

重新整理一下,以免滥用太多语言:

#!/usr/bin/perl
my @h;          # $h[$c] will contain the note in column $c, if any
my @d;          # $d[$c] will contain the note length (e.g. 4), if any
while (<>) {    # for each input line, do
    my $c = 0;  # column number
    foreach (split //) {   # for each character, do
        if (/o/) { $h[$c] = "E"; }      # o => it's a note; if this is the last line, it's E
        elsif (/\\/) { $d[$c-1] *= 2; } # \ => halve the duration of the note in the previous column
        elsif (/\|/) { $d[$c] ||= 4; }  # | => if this is the first | in the column, we have a quarter note
        else { ++$h[$c]; }              # anything else => bump the note by 1
        ++$c;
     }
}
for (my $i = 0; $i < @h; $i++) { # for each column, do
    $_ = $h[$i];                   # look up the potential note (or garbage if there is no note in this column)
    s~$~/$d[$i++] ~;               # append the duration and a space (or "/ " if there is no duration)
    s~/ ~ ~;                       # remove the spurious "/" if there is no duration
    if (y/E-M/EFGA-F/) {           # if it's a note (i.e. if it contains a letter E-M), then
                                   # fix the letter wraparound and then
        print $_;                    # print the note
    }
}

请注意,我假设所有行的长度都相同。如果要允许较短的行,一个明显的解决方法是$_.=1x$c,在程序的开头添加9个字符的费用。

我想到了另一种避免长的单词,例如splitmap,让空格来完成更多工作的方法,但样板和标点符号引起了他们的报复,我只能将其降低到高达130(带有必要空白的144)。

sub p{$-[0]}
%a=qw(o $h[p]=E \ $d[&p-1]*=2 | $d[p]||=4 - ++$h[p]);
y/ /-/,s~.~$a{$&}~gee for<>;
print grep{s~$~/$d[$i++] ~;s~/ ~ ~;y/E-M/EFGA-F/}@h

这次处理未完成线条的补丁有点奇怪(什么,您认为它不会变得奇怪?)。139个字符,其中包含155个必要的空格。

sub p{$-[0]}
%a=qw(o $h[p]=E \ $d[&p-1]*=2 | $d[p]||=4 - ++$h[p]);
$_.=" "x p,y/
 /-/,s~.~$a{$&}~gee for<>;
print grep{s~$~/$d[$i++] ~;s~/ ~ ~;y/E-M/EFGA-F/}@h

2

阶(2.9),352 313 291 294 290个 277 274 273字符

如果只需要一个函数:

def m(s:String){var(x,y,z,l)=(0,1,s.count(_=='\n'),Array.fill(99)(0))
var n=l.clone
for(c<-s){if(c=='\n'){x=0;y+=1}
if(c=='\\')l(x-1)+=1
if(c=='|')l(x)+=1
if(c=='o')n(x)="EFGABCDEF"(z-y)
x+=1}
(n,l).zipped.map((x,y)=>if(x>0)print(x.toChar+(if(y>0)"/"+(4<<y-3)else"")+" "))}

如果需要完整的程序:

object M extends App{def m(s:String){var(x,y,z,l)=(0,1,s.count(_=='\n'),Array.fill(99)(0))
var n=l.clone
for(c<-s){if(c=='\n'){x=0;y+=1}
if(c=='\\')l(x-1)+=1
if(c=='|')l(x)+=1
if(c=='o')n(x)="EFGABCDEF"(z-y)
x+=1}
(n,l).zipped.map((x,y)=>if(x>0)print(x.toChar+(if(y>0)"/"+(4<<y-3)else"")+" "))}
m(io.Source.stdin.mkString)}

空格其间酒吧,直到比分结束,虽然我没有提到它使程序应该无论工作。如果带有空格的行突然结束,则意味着该行不再需要考虑任何输入。它只是必须不必崩溃.. :)
Neil

2

J-108个字符

exit echo}.,>,&.>/_4<@((a.{~32,65+7|4+i.&'o'),(>&0#('/',0":2^]))@((+/@(=&'\'))+2*'|'&e.))@;\|:|.[;._2]stdin''

取消高尔夫:

str =: stdin''
lines =: [;._2] str                          NB. split on the last character, the newline
rotated =: |: |. lines                       NB. lines reversed, then transposed
pitch =: 65 + 7 | 4 + i.&'o'                 NB. ord('A') + ( line.index('o') + 4 ) % 7
has_stem =: '|' & e.                         NB. '|' in line?
backslash_count =: (+/ @ (=&'\') )           NB. sum(char = '\\' for char in line)
denom_exp =: backslash_count + 2 * has_stem
fraction =: (>&0 # ('/', 0": 2 ^ ]))         NB. slash + 2^denom_exp, if denom_exp > 0
suffix =: fraction @ denom_exp
note_string =: (a. {~ 32,pitch) , suffix     NB. map(chr, (ord(' '), pitch)) + suffix
boxed_note_string =: < @ note_string @ ;     NB. box the string so it doesn't get padded
each_note_of_the =: boxed_note_string        NB. compute the note for a block of 4 lines
join_to_one_box =: , &. >
exit echo }. , > join_to_one_box / _4 each_note_of_the \ rotated

2

Python高尔夫球,207个字符。

import sys
a=[x[:-1]+' '*99 for x in sys.stdin]
for x in range(0,99,4):
 b=''.join((y[x:x+4] for y in a))+'o'
 c=2**(b.count('\\')+('|'in b)*2)
 print'FEDCBAGFE '[b.index('o')/4-len(a)+9]+('','/'+`c`)[c>1],

我开始打高尔夫球的代码与Python 2天,我发现一些事情,如import syssys.stdin.readsys.stdout.write是广阔的。


如果您不熟悉 Python打高尔夫球,则可能会发现此python高尔夫技巧提示问题有用。
加雷斯(Gareth)2012年
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.