楽譜通訳


11

ASCII楽譜が与えられた場合、ノートとそれに対応する長さを出力できる必要があります。スコアには5〜15音が含まれ、譜表に書き写されます。ステーブは、スペースの行で区切られた-(マイナス)文字で構成される5本の水平線で構成されます。ステーブの一番下の行は、音符「E」に相当します。一番下の行のすぐ上のスペースの行は「F」を示し、その下の「E」よりも高いピッチです。これは以下のように続きます。メモは、「A」で再び開始する前に「G」までしか表示されないことに注意してください。下記参照:

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

文字は入力に含まれないことに注意してください。音符はステーブの上にao(小文字ooh)文字を使用して重ねられ、「音符の頭」を示します。この音符の頭は音符の頻度を示しているため、上記のようにアルファベット順で表示されます。たとえば、次のようにスコアに付けられた音符は「A」を示します。

----

----

----
o   
----

----

上記の「A」のような音符は「全音符」と呼ばれ、1ビート全体で演奏されます。他の持続時間は、音符から上昇する「ステム」と、0〜3個の「フラグ」を含めることで示すことができます。ステムは3つで構成されています| (パイプ、または垂直バー)音符の頭のすぐ上にスタックされた文字。フラグのないステムは「クォーターノート」と見なされ、1/4ビートで演奏されます。フラグは\(バックスラッシュ)文字であり、ステムの右側にあります。各ステムは、ノートが演奏される時間を半分にします。各音符の長さは、音符全体、4分音符、8分音符、16分音符、または32秒音符のいずれかです。これは、各タイプのメモがどのようにAを探すかです。

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

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

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

複数のノートをまとめると、スコアが得られます。各ノートは4文字幅と見なすことができ、各4文字ブロックの最初の列にノートがあります。例えば ​​:

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

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

上記の例には、次の音符が順番に含まれています。4分音符「G」、32秒音符「D」、8分音符「C」、全体音符「D」、16分音符「B」。出力の各ノートはレター/長さの形式にする必要があります。レターはAG、長さはノート全体と比較したときのノートの長さの割合です。例外として、音符が音符全体である場合、長さと/文字は印刷されません。出力内の各ノートは、単一のスペースで区切る必要があります。したがって、上記のスコアの場合、コードは次を出力する必要があります。

G/4 D/32 C/8 D B/16
  • メモは次の範囲になります。EFGABCDEF。文字のみを印刷する必要があり、オクターブは無視されることに注意してください。
  • 入力Dの行数が9から12に変化することに注意してください。これは、行D以上の4分の1以下の音符を完全に表示するにはより多くの行が必要になるためです。
  • この場合、半音符はありません。

最短のコードが優先されます(空白はカウントされません)。

編集: 1つの入力の間隔のエラーを修正しました。

いくつかのサンプル入力:

        |\                    
----|\--|-------------------
|\  |   |                   
|---|---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行も空けずに提出する気にならないように。
ニール

1
空白を数えることは慣習的ですが、エントリを適切な幅に保つためだけに存在する改行は数えませんGeorgeのユーザースクリプトは、いくつかの言語(cを含む)でこれを行います。
dmckee ---元モデレーター子猫

2
@Neilは今のところ、提出したいと思うのはホワイトスペースプログラムだけです。
JB

回答:


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、147 126文字

(必要な空白を数える場合は149 131)

$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スペースがより多くの仕事の任せとが、定型および句読点は彼らの復讐を取って、私は(必要な空白で144)百日咳130にそれを得ることができます。

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)}

スコアの最後までバーの間に空白スペースがあります、言及しなかったので、プログラムは関係なく動作します。空白のある行が突然終了する場合、それはその行についてとにかく考慮する入力がもうないことを意味します。単にクラッシュしないようにする必要があります。.:)
ニール

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

パイソンゴルフ、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],

私は2日間のPythonでコードゴルフを開始していると私は物事が好きなことを見つけimport syssys.stdin.readsys.stdout.write広大です。


あなたがPythonでゴルフをするのが初めてなら、このpython gofling tipsの質問が役に立つかもしれません。
ガレス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.