ล่ามคะแนนดนตรี


11

ด้วยคะแนนดนตรี ascii คุณจะต้องสามารถส่งออกบันทึกและความยาวที่สอดคล้องกัน คะแนนจะมีอยู่ระหว่าง 5 ถึง 15 โน้ตรวมอยู่ด้วยและถูกถอดความบนเสา ขั้นบันไดประกอบด้วยเส้นแนวนอนห้าเส้นซึ่งประกอบด้วยอักขระ - (ลบ) คั่นด้วยเส้นของช่องว่าง บรรทัดล่างสุดของไม้เท้านั้นเทียบเท่ากับโน้ต 'E' เส้นของช่องว่างเหนือเส้นด้านล่างจะระบุ 'F' และเป็นระยะห่างที่สูงกว่าที่ 'E' อยู่ด้านล่าง ดำเนินการต่อไปดังนี้ โปรดทราบว่าโน้ตจะสูงถึง 'G' ก่อนเริ่มอีกครั้งที่ 'A' ดูด้านล่าง:

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

โปรดทราบว่าตัวอักษรไม่รวมอยู่ในอินพุต บันทึกย่อดังกล่าวจะถูกวางทับที่ด้านบนของไม้เท้าโดยใช้อักขระ ao (ตัวพิมพ์เล็ก ooh) เพื่อระบุ 'หัวกระดาษโน้ต' หัวบันทึกนี้แสดงความถี่ของบันทึกย่อและดังนั้นการแสดงตามตัวอักษรของมันดังกล่าวข้างต้น ตัวอย่างเช่นโน้ตที่วางไว้ในคะแนนด้านล่างแสดงถึง 'A':

----

----

----
o   
----

----

โน้ตเช่น 'A' ด้านบนเรียกว่า 'โน้ตทั้งหมด' และจะเล่นในจังหวะเดียว ระยะเวลาอื่น ๆ สามารถระบุได้โดยรวม 'ก้าน' ที่เพิ่มขึ้นจากบันทึกและระหว่างศูนย์และสาม 'ธง' ก้านประกอบด้วยสาม อักขระ (ไพพ์หรือแถบแนวตั้ง) ซ้อนกันเหนือหัวบันทึกย่อทันที ก้านที่ไม่มีธงถือว่าเป็น 'quarter-note' และเล่นเพื่อตีสี่ ธงคืออักขระ \ (แบ็กสแลช) และส่งทางด้านขวามือของก้าน แต่ละก้านจะแบ่งครึ่งเวลาที่เล่นโน้ต ความยาวของโน้ตแต่ละโน้ตจะเป็นหนึ่งในสิ่งต่อไปนี้: โน้ตทั้งหมด, โน๊ตไตรมาส, โน้ตที่แปด, โน้ตที่สิบหกหรือโน้ตสามสิบสองวินาที นี่คือลักษณะของโน้ตแต่ละประเภทที่จะค้นหา:

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

----|---|\--|\--|\--
    |   |   |\  |\
----|---|---|---|\--
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
  • บันทึกจะอยู่ในช่วงดังต่อไปนี้: 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
มันเป็นเรื่องธรรมดาที่จะนับช่องว่าง แต่จะไม่นับบรรทัดใหม่ที่มีเพียงเพื่อให้รายการภายใต้ความกว้างที่เหมาะสม userscript ของ Georgeทำสิ่งนี้กับบางภาษา (รวมถึง c)
dmckee --- ผู้ดูแลอดีตลูกแมว

2
@Neil ดีตอนนี้สิ่งที่ฉันรู้สึกอยากจะส่งเป็นโปรแกรมช่องว่าง
JB

@ Neil ใช่แล้วคุณได้รับ smartasses ที่เขียนโซลูชัน verbose จริง ๆ พวกเขาบรรจุลงในช่องว่างของสตริงและกอล์ฟถอดรหัสและ exec: codegolf.stackexchange.com/questions/3203/meta-golf-challenge/
บูธโดย

คำตอบ:


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 อักขระ

ฉันคิดว่าอีกวิธีหนึ่งที่จะหลีกเลี่ยงคำยาวเหมือนsplitและmapและปล่อยให้พื้นที่ทำมากขึ้นของการทำงาน แต่สำเร็จรูปและเครื่องหมายวรรคตอนแก้แค้นของพวกเขาและฉันเท่านั้นที่จะได้รับมันลงไปไอกรน 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)}

มีมีช่องว่าง inbetween บาร์จนกว่าจะสิ้นสุดของคะแนน แต่ผมไม่ได้พูดถึงมันเพื่อให้โปรแกรมควรจะทำงานโดยไม่คำนึงถึง หากบรรทัดที่มีช่องว่างว่างสิ้นสุดลงอย่างกระทันหันหมายความว่าไม่มีข้อมูลป้อนเข้าที่จะต้องพิจารณาอีกต่อไปสำหรับบรรทัดนั้น มันก็เพียงแค่มีการไม่ผิดพลาด .. :)
นีล

2

J - 108 ตัวอักษร

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

Ungolfed:

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 golf, 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 วันและฉันพบว่าสิ่งที่ชอบimport sys, sys.stdin.read, sys.stdout.writeมีการขยายตัว


หากคุณยังใหม่กับการเล่นกอล์ฟใน Python คุณอาจพบว่าคำถามสำหรับเคล็ดลับ gofling python นี้มีประโยชน์
Gareth
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.