악보 통역사


11

아스키 악보가 주어지면 음표와 해당 길이를 출력 할 수 있어야합니다. 악보는 5 ~ 15 개의 음을 포함하며 악보에 기록됩니다. 스 태브는 공백으로 구분 된-(마이너스) 문자로 구성된 5 개의 수평선으로 구성됩니다. 스 태브의 결론은 'E'음과 같습니다. 하단 라인 바로 위의 스페이스 라인은 'F'를 나타내며 그 아래의 'E'보다 높은 피치입니다. 이것은 아래와 같이 계속됩니다. 'A'에서 다시 시작하기 전에 음표는 'G'로만 올라갑니다. 아래를보십시오 :

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

문자는 입력에 포함되지 않습니다. 노트는 '노트 헤드'를 나타 내기 위해 ao (소문자 ooh) 문자를 사용하여 스 태브 위에 겹쳐집니다. 이 노트 헤드는 노트의 빈도를 나타내므로 위와 같이 알파벳 순서로 표시됩니다. 예를 들어, 아래와 같이 점수에 표시된 메모는 'A'를 나타냅니다.

----

----

----
o   
----

----

위의 'A'와 같은 음표를 '전체 음표'라고하며 하나의 전체 비트에 대해 연주됩니다. 다른 지속 시간은 음표에서 상승하는 '줄기'와 0에서 3 사이의 '플래그'를 포함하여 표시 할 수 있습니다. 줄기는 세 가지로 구성되어 있습니다 | (파이프 또는 세로 막대) 문자가 노트 헤드 바로 위에 쌓입니다. 깃발이없는 줄기는 '4 분 음표'로 간주되며 4 분의 1 비트로 재생됩니다. 플래그는 \ (백 슬래시) 문자이며 줄기의 오른쪽에 손입니다. 각 스템은 음표 연주 시간의 절반입니다. 각 음표의 길이는 전체 음표, 1/4 음표, 8 분 음표, 16 분 음표 또는 32 분 음표 중 하나입니다. 이것은 각 유형의 메모가 A를 찾는 방법입니다.

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

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

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

하나 이상의 메모를 작성하면 점수를 얻을 수 있습니다. 각 메모는 너비가 4자인 것으로 간주 될 수 있으며, 메모는 각 4 자 블록의 첫 번째 열에 있습니다. 예를 들면 다음과 같습니다.

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

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

위의 예에는 1/4 음표 'G', 30 초 음표 'D', 8 분 음표 'C', 전체 음표 'D'및 16 분 음표 'B'가 순서대로 포함되어 있습니다. 출력의 각 노트는 문자 / 길이 형식이어야합니다. 여기서 문자는 AG이고 길이는 전체 노트와 비교할 때 노트 길이의 일부입니다. 단, 메모가 전체 메모 인 경우 길이 및 / 문자를 인쇄하면 안됩니다. 출력의 각 음표는 단일 공백으로 분리해야합니다. 따라서 위의 점수에 대해 코드는 다음을 출력해야합니다.

G/4 D/32 C/8 D B/16
  • 음표의 범위는 EFGABCDE F입니다. 글자 만 인쇄하면 옥타브는 무시됩니다.
  • 입력 라인 수는 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 : 사람들은 공백없이 한 줄로 프로그램을 제출하는 경향이 없습니다.
Neil

1
공백 을 계산하는 것이 일반적 이지만 항목을 적당한 너비로 유지하기 위해 존재하는 줄 바꾸기 는 계산 하지 않는 것이 일반적 입니다. George의 사용자 스크립트 는 일부 언어 (c 포함)로이 작업을 수행합니다.
dmckee --- 전 운영자 고양이

2
@Neil 글쎄 지금 제출하려는 경향은 공백 프로그램입니다.
JB

@Neil, 그렇습니다.하지만 정말 장황한 솔루션을 작성하고 공백 문자열로 묶어 디코드 및 실행을 수행하는 현명한 사람들이 있습니다
boothby

답변:


6

자바 스크립트, 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
불필요한을 제거 ;하고 몇 가지 트릭을 수행하면 더 짧게 만들 수 있습니다. 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

펄, 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 " ";
    }
}

(오래된, 더 긴 솔루션, 조금 더 길어도 재미있을 수 있기 때문에 유지됨)

펄, 147126

( 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자를 추가하여 추가 해야합니다.

내가 좋아하는 긴 단어를 방지하기 위해 다른 방법을 생각 split하고 map공간이 더 많은 작업을 할 수 있도록하고 있지만, 보일러 및 문장 부호는 복수를했다, 그리고 난 단지 (필요한 공백과 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)}

있는 프로그램에 관계없이 작동합니다 그래서 그것을 언급하지 않았지만 점수가 끝날 때까지 바 inbetween 빈 공간. 공백이있는 줄이 갑자기 끝나는 경우 해당 줄에 대해 더 이상 입력 할 사항이 없음을 의미합니다. 단순히 충돌하지 않아도됩니다 .. :)

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 sys했으며 sys.stdin.read, 같은 것들이 sys.stdout.write광대 하다는 것을 알았습니다 .


파이썬에서 골프를 처음 접한다면이 파이썬 고플 링 팁 질문이 유용 할 것입니다.
Gareth
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.