Перекладач музичної партитури


11

З огляду на музичну партитуру ascii, ви повинні мати можливість вивести ноту та відповідну її довжину. Оцінка буде містити від 5 до 15 записок включно і записана на ній. Кладка складається з п'яти горизонтальних ліній, що складаються з - (мінус) символів, розділених рядками пробілів. Нижній рядок на кожусі еквівалентний примітці "E". Рядок пробілів безпосередньо над нижньою лінією вказує на 'F' і має більш високий крок, ніж 'E' під ним. Це продовжується як нижче. Зауважте, що нотатки піднімаються лише до "G", перш ніж починати знову з "A". Дивись нижче:

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

Зауважте, що букви не включені до вводу. Нотатки накладаються на верхню частину стулки, використовуючи символ ao (нижній регістр оо), щоб позначити "голову ноти". Цей заголовок нота вказує на частоту нотатки, а отже, алфавітне зображення її як вище. Наприклад, примітка, поміщена на рахунок, як показано нижче, позначає "A":

----

----

----
o   
----

----

Нота, як і "А" вище, називається "ціла нота" і відтворюватиметься за один цілий ритм. Інші тривалості можна вказати, включивши "стебло", що піднімається від ноти, і між нулем і трьома "прапорами". Стебло складається з трьох | (труба або вертикальна смуга), що розміщуються безпосередньо над головою нотатки. Стебло без прапорців вважається «чверть нотою» і грає за чверть удару. Прапори - це \ (зворотна косою рисою) символи та рука праворуч від стебла. Кожне стебло вдвічі зменшує час відтворення ноти. Довжина кожної ноти буде однією з таких: ціла нота, чверть нота, восьма нота, шістнадцята нота або тридцять друга нота. Ось як виглядатиме кожен тип ноти:

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

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

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

Якщо скласти більше однієї ноти разом, ви отримуєте бал. Кожна нота може вважатися шириною чотирьох символів, при цьому примітка знаходиться в першому стовпчику кожного блоку з чотирма символами. Наприклад :

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

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

Наведений вище приклад містить такі примітки: Порядок чверть нота "G", тридцять друга примітка "D", восьма примітка "C", ціла примітка "D" і шістнадцята примітка "B". Кожна примітка у вашому висновку повинна бути у форматі літери / довжини, де літера - це АГ, а довжина - частка довжини нотатки порівняно з цілою нотою. Як виняток, довжина та / символ не повинні друкуватися, якщо нота є цілою нотою. Кожна примітка у вашому висновку повинна бути розділена одним пробілом. Тому для вищезазначеного результату ваш код повинен виводити наступне:

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: Так що люди не будуть схильні подавати програми довгим рядком без пробілів.
Ніл

1
Умовно рахувати пробіли, але не рахувати нові рядки, які є лише там, щоб тримати запис під розумною шириною. Користувацький сценарій Джорджа робить це з деякими мовами (включаючи c).
dmckee --- кошеня колишнього модератора

2
@Neil добре зараз, я відчуваю схильність подати програму Whitespace.
JB

@Neil, так, але тоді ви отримуєте розумники, які пишуть дійсно багатослівні рішення, упаковують їх у рядок пробілів і гольф розшифровують і виконуються: 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)}

Між барами є пробіли до кінця партитури, хоча я цього не згадував, тому програма повинна працювати незалежно. Якщо рядок із порожніми пробілами різко закінчується, це означає, що в цьому випадку більше немає для введення для цього рядка. Він просто повинен не врізатися .. :)
Ніл,

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

Я запустити код гри в гольф з Python в протягом 2 днів , і я виявив , що речі , як import sys, sys.stdin.read, sys.stdout.writeвеликі.


Якщо ви не новачок у гольфі в Python, вам може здатися корисним цей підказки щодо гофлінгу python .
Гарет
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.