Phiên dịch nhạc


11

Cho một số điểm âm nhạc ascii, bạn phải có thể xuất ghi chú và độ dài tương ứng của nó. Điểm số sẽ bao gồm từ 5 đến 15 ghi chú, và được phiên âm trên một dàn. Một stave được tạo thành từ năm dòng nằm ngang bao gồm - (trừ) các ký tự được phân tách bằng các dòng khoảng trắng. Dòng dưới cùng trong stave tương đương với ghi chú 'E'. Dòng không gian ngay phía trên dòng dưới cùng biểu thị 'F' và có độ cao cao hơn 'E' bên dưới nó. Điều này tiếp tục như dưới đây. Lưu ý rằng các ghi chú chỉ tăng lên 'G' trước khi bắt đầu lại tại 'A'. Xem bên dưới:

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

Lưu ý rằng các chữ cái không được bao gồm trong đầu vào. Các ghi chú được đặt chồng lên trên đỉnh của stave bằng ký tự ao (chữ thường ooh) để biểu thị 'đầu ghi chú'. Đầu ghi chú này cho biết tần suất của ghi chú, và do đó biểu diễn chữ cái của nó như trên. Ví dụ: một ghi chú được đặt trên điểm số như dưới đây biểu thị 'A':

----

----

----
o   
----

----

Một ghi chú, như 'A' ở trên, được gọi là 'toàn bộ ghi chú' và sẽ được phát cho một nhịp. Các thời lượng khác có thể được biểu thị bằng cách bao gồm một 'gốc' tăng từ ghi chú và giữa 0 và 3 'cờ'. Một thân cây được tạo thành từ ba | các ký tự (ống hoặc thanh dọc) xếp chồng lên nhau ngay trên đầu ghi chú. Một thân cây không có cờ được coi là 'một phần tư' và chơi cho một phần tư nhịp. Cờ là các ký tự \ (dấu gạch chéo ngược) và tay ở phía bên phải của thân cây. Mỗi thân cây giảm một nửa thời gian ghi chú được chơi. Độ dài của mỗi ghi chú sẽ là một trong những điều sau đây: toàn bộ ghi chú, ghi chú quý, ghi chú thứ tám, ghi chú thứ mười sáu hoặc ghi chú ba mươi giây. Đây là cách mỗi loại ghi chú sẽ tìm kiếm A:

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

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

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

Đặt nhiều hơn một ghi chú với nhau cho bạn một điểm số. Mỗi ghi chú có thể được coi là rộng bốn ký tự, với một ghi chú nằm trong cột đầu tiên của mỗi khối bốn ký tự. Ví dụ :

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

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

Ví dụ trên chứa các ghi chú sau, theo thứ tự: một phần tư ghi chú 'G', một ghi chú ba mươi giây 'D', một ghi chú thứ tám 'C', toàn bộ ghi chú 'D' và một ghi chú thứ mười sáu 'B'. Mỗi ghi chú trong đầu ra của bạn phải ở dạng chữ / độ dài, trong đó chữ cái là AG và độ dài là phần nhỏ của độ dài của ghi chú khi so sánh với toàn bộ ghi chú. Như một ngoại lệ, không nên in độ dài và / ký tự nếu ghi chú là toàn bộ ghi chú. Mỗi ghi chú trong đầu ra của bạn nên được phân tách bằng một khoảng trắng. Do đó, đối với điểm số trên, mã của bạn nên xuất ra như sau:

G/4 D/32 C/8 D B/16
  • Các ghi chú sẽ nằm trong phạm vi sau: EFGABCDE F. Lưu ý rằng chỉ cần in chữ cái, quãng tám được bỏ qua.
  • Lưu ý rằng số lượng dòng đầu vào thay đổi từ 9 đến 12, vì các ghi chú có thời gian quý hoặc ít hơn trên dòng D hoặc cao hơn sẽ yêu cầu nhiều dòng hơn để hiển thị hoàn toàn.
  • Không có nửa ghi chú trong trường hợp này.

Mã ngắn nhất sẽ thắng (khoảng trắng không được tính).

Chỉnh sửa: Đã sửa lỗi khoảng cách trong một đầu vào.

Một số mẫu đầu vào:

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

Đầu ra: B / 8 C / 8 D / 8 E / 32 F / 32 G / 32 D


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

Đầu ra: EGBDFFACE


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

Đầu ra: B / 4 A / 8 F / 32 F / 32 EC / 4 B / 32 F / 16


Tại sao không tính khoảng trắng?
JB

@J: Vì vậy, mọi người sẽ không cảm thấy có xu hướng gửi các chương trình dài một dòng mà không có khoảng trắng.
Neil

1
Thông thường là tính khoảng trắng nhưng không tính các dòng mới chỉ có ở đó để giữ mục nhập dưới một chiều rộng hợp lý. Usercript của George thực hiện điều này với một số ngôn ngữ (bao gồm cả c).
dmckee --- ex-moderator mèo con

2
@ Bây giờ tất cả những gì tôi cảm thấy có xu hướng gửi là một chương trình Whitespace.
JB

@Neil, yeah, nhưng sau đó bạn có được những người thông minh viết ra các giải pháp thực sự dài dòng, đóng gói chúng thành một chuỗi khoảng trắng và chơi golf một giải mã-và-exec: codegolf.stackexchange.com/questions/3203/meta-golf-challenge/
gian hàng

Câu trả lời:


6

Javascript, 284.279.278.225.221 , 220 Ký tự (bao gồm cả khoảng trắng cần thiết)

Một lớp lót ( thử nghiệm ):

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

Có thể đọc được ( bài kiểm tra ):

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
Bằng cách loại bỏ ;s không cần thiết và thực hiện một số thủ thuật, bạn có thể làm cho việc này thậm chí còn ngắn hơn. 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 ký tự)
JiminP

4

Perl, 103 ký tự

(108 nếu bạn đếm các ký tự khoảng trắng cần thiết)

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

Với khoảng trắng để trình bày:

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

Lưu ý rằng tôi giả sử rằng tất cả các dòng có cùng độ dài (theo phiên bản sửa đổi của câu hỏi).

Sắp xếp lại phiên bản với lời giải thích:

#!/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 " ";
    }
}

(giải pháp cũ, dài hơn, được giữ vì nó có thể thú vị ngay cả khi nó dài hơn một chút)

Perl, 147 126 ký tự

( 149 131 nếu bạn tính khoảng trắng cần thiết)

$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

Với khoảng trắng để trình bày:

$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

Sắp xếp lại một chút để không lạm dụng ngôn ngữ quá nhiều:

#!/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
    }
}

Lưu ý rằng tôi giả sử rằng tất cả các dòng có cùng độ dài. Nếu bạn muốn cho phép các dòng ngắn hơn, một sửa chữa rõ ràng là thêm $_.=1x$c,vào lúc bắt đầu chương trình, với chi phí 9 ký tự.

Tôi đã nghĩ đến một cách tiếp cận khác để tránh những từ dài như splitmapđể cho không gian làm được nhiều việc hơn, nhưng cái nồi hơi và dấu câu đã trả thù họ, và tôi chỉ có thể đưa nó xuống một con số 130 (144 với khoảng trắng cần thiết).

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

Bản vá để đối phó với các dòng chưa hoàn thành là một chút kỳ lạ lần này (cái gì, bạn nghĩ rằng nó không thể có được weirder?). 139 ký tự, 155 với khoảng trắng cần thiết.

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

Scala (2.9), 352 313 291 294 290 277 274 273 ký tự

Nếu một chức năng là tất cả những gì cần thiết:

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

Nếu một chương trình đầy đủ là bắt buộc:

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

những khoảng trống nằm giữa các thanh cho đến khi hết điểm, mặc dù tôi không đề cập đến nó nên chương trình sẽ hoạt động bất kể. Nếu dòng có khoảng trắng kết thúc đột ngột, điều đó có nghĩa là không còn đầu vào nào để xem xét cho dòng đó nữa. Nó chỉ đơn giản là không bị sập .. :)
Neil

2

J - 108 ký tự

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

Ung dung:

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

Golf Python, 207 ký tự.

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],

Tôi đã bắt đầu mã chơi golf với Python trong 2 ngày và tôi thấy rằng những điều thích import sys, sys.stdin.read, sys.stdout.writeđang mở rộng.


Nếu bạn chưa quen với việc chơi gôn trong Python, bạn có thể thấy câu hỏi mẹo vặt về con trăn này hữu ích.
Gareth
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.