Müzikal Skor Tercüman


11

Bir ascii müzikal puanı verildiğinde, notu ve karşılık gelen uzunluğunu çıkarabilmelisiniz. Skor 5 ile 15 arasında not içerecek ve bir çıtaya yazılacaktır. Bir çıta, boşluk satırları ile ayrılmış - (eksi) karakterden oluşan beş yatay çizgiden oluşur. Çıtanın alt çizgisi 'E' notasına eşdeğerdir. Alt çizginin hemen üzerindeki boşluk çizgisi bir 'F' işaretini gösterir ve altındaki 'E' işaretinden daha yüksek bir perdeye sahiptir. Bu aşağıdaki gibi devam eder. Notların 'A'da tekrar başlamadan önce yalnızca' G'ye kadar yükseldiğini unutmayın. Aşağıya bakınız:

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

Harflerin girişe dahil olmadığını unutmayın. Notlar, 'not başlığını' belirtmek için ao (küçük harfli ooh) karakter kullanılarak çıtanın üstüne yerleştirilir. Bu nota başı notanın sıklığını ve dolayısıyla yukarıdaki gibi alfabetik temsilini gösterir. Örneğin, aşağıdaki gibi nota yerleştirilen bir not bir 'A'yı gösterir:

----

----

----
o   
----

----

Bir nota, yukarıdaki 'A' gibi, 'tam nota' denir ve bir tam vuruş için çalınır. Diğer süreler, nottan yükselen bir 'gövde' ve sıfır ile üç 'bayrak' arasında belirtilerek belirtilebilir. Bir kök üç taneden oluşur | (dikey çizgi veya dikey çubuk) karakterleri not başlığının hemen üstüne yerleştirilir. Bayraksız bir kök 'çeyrek nota' olarak kabul edilir ve çeyrek vuruş için oynar. Bayraklar \ (ters eğik çizgi) karakteridir ve gövdenin sağ tarafındaki eldir. Her bir kök notanın çalındığı süreyi yarıya indirir. Her notanın uzunluğu aşağıdakilerden biri olacaktır: tam nota, çeyrek nota, sekizinci nota, on altıncı nota veya otuz saniyelik nota. Her not türü A'yı şu şekilde arayacaktır:

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

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

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

Birden fazla notu bir araya getirmek size bir puan verir. Her not dört karakter genişliğinde, her dört karakter bloğunun ilk sütununda bir not olarak düşünülebilir. Örneğin :

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

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

Yukarıdaki örnek sırasıyla şu notları içerir: çeyrek nota 'G', otuz ikinci nota 'D', sekizinci nota 'C', bütün nota 'D' ve on altıncı nota 'B' notaları. Çıktınızdaki her nota harf / uzunluk biçiminde olmalıdır, burada harf AG'dir ve uzunluk notun tümüyle karşılaştırıldığında notun uzunluğudur. İstisna olarak, notun tamamı not ise uzunluk ve / karakteri yazdırılmamalıdır. Çıktınızdaki her not tek bir boşlukla ayrılmalıdır. Bu nedenle, yukarıdaki puan için kodunuz aşağıdakileri çıkarmalıdır:

G/4 D/32 C/8 D B/16
  • Notlar aşağıdaki aralıkta olacaktır: EFGABCDE F. Sadece harfin yazdırılması gerektiğini, oktavın dikkate alınmadığını unutmayın.
  • Giriş satırlarının sayısının 9 ile 12 arasında değiştiğine dikkat edin, çünkü D satırında veya daha yüksekte çeyrek zamanı veya daha az olan notların tamamen gösterilmesi için daha fazla satır gerekir.
  • Bu durumda yarım nota yoktur.

En kısa kod kazanır (boşluk sayılmaz).

Düzenleme: Bir girişteki boşluk hatası düzeltildi.

Bazı örnek girişler:

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

Çıkış: B / 8 C / 8 D / 8 E / 32 F / 32 G / 32 D


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

Çıktı: EGBDFFACE


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

Çıktı: B / 4 A / 8 F / 32 F / 32 EC / 4 B / 32 F / 16


Boşluk neden sayılmaz?
JB

@J: İnsanlar bir satır uzunluğunda, boşluksuz programlar sunma eğiliminde olmayacaklar.
Neil

1
Geleneksel olduğunu saymak boşluk bunlarla sayılmaz makul genişliği altında girişini tutmanın tek orada yeni hatlar. George'un kullanıcı metni bunu bazı dillerle (c dahil) yapar.
dmckee --- eski moderatör kedi yavrusu

2
@Neil peki şimdi göndermeye meyilli olduğum tek şey bir Whitespace programı.
JB

@Neil, evet, ama sonra gerçekten ayrıntılı çözümler yazan, bunları bir boşluk alanına paketleyen ve bir kod çözme ve yürütme golfü yapan smartasses elde edersiniz
boothby

Yanıtlar:


6

Javascript, 284.279.278.225.221 , 220 Karakter (gerekli boşluk dahil)

Tek astar ( test kemanı ):

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

Okunabilir ( test kemanı ):

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
Gereksiz ;leri kaldırarak ve bazı numaralar yaparak, bunu daha da kısaltabilirsiniz. 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 karakter)
JiminP

4

Perl, 103 karakter

(Gerekli boşluk karakterlerini sayarsanız 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

Sunum için boşluk ile:

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

Tüm satırların aynı uzunluğa sahip olduğunu varsayıyorum (sorunun gözden geçirilmiş versiyonuna göre).

Açıklamaları olan yeniden düzenlenmiş sürüm:

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

(eski, daha uzun çözüm, çünkü biraz daha uzun olsa bile ilginç olabilir)

Perl, 147126 karakter

( 149 Gerekli boşluk sayarsanız 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

Sunum için boşluk ile:

$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

Dili çok fazla kötüye kullanmamak için yeniden düzenlenmiştir:

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

Tüm satırların aynı uzunlukta olduğunu varsayıyorum. Daha kısa satırlara izin vermek istiyorsanız $_.=1x$c,, programın başına 9 karakterlik bir maliyetle belirgin bir düzeltme eklemektir .

Ben gibi uzun kelimeleri önlemek için başka bir yaklaşım düşünce splitve mapboşluk daha işin yapalım ve ancak demirbaş ve noktalama onların intikamını aldı ve sadece (gerekli boşluk ile 144) bir boğmaca 130 için aşağı alabilirsiniz.

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

Bitmemiş çizgilerle başa çıkmak için yama, bu sefer biraz garip (ne, tuhaf tutamayacağını düşündün mü?). 139 karakter, 155 boşluk ile.

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

Ölçeği (2.9), 352 313 291 294 290 277 274 273 karakter

Bir işlev gerekliyse:

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

Tam bir program gerekiyorsa:

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

Orada olan programın bakılmaksızın çalışması gerekir o yüzden söz etmedi gerçi puanı sonuna kadar barlarda İnbetween boşluk. Boşluğu olan satır aniden bitiyorsa, bu satır için dikkate alınacak başka girdi olmadığı anlamına gelir. Sadece çökmemelidir .. :)
Neil

2

J - 108 karakter

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 karakter.

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

Ben 2 gün Python ile kod golf başlamak ettik ve ben gibi şeyler bulduk import sys, sys.stdin.read, sys.stdout.writegeniş vardır.


Python'da golf yapmak için yeniyseniz, bu python gofling ipuçları sorusunu faydalı bulabilirsiniz.
Gareth
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.