Stwórzmy muzykę!

11

Wiele osób lubi odtwarzać muzykę dla zabawy i rozrywki. Niestety czasami muzyka jest dość trudna. Właśnie dlatego tu jesteś!

Zadanie

Twoim zadaniem jest sprawienie, by czytanie muzyki stało się łatwiejsze dla osób, które się z tym zmagają. Musisz napisać program lub funkcję, która pobiera wejściową pięciolinię muzyczną i wyświetla nazwy nut zapisanych na tej pięciolinii.

Personel, klucz wiolinowy i notatki

Kij muzyczny lub pięciolinia to pięć poziomych linii, pomiędzy którymi są cztery przestrzenie. Każda linia lub spacja reprezentuje inną nutę (wysokość), w zależności od klucza.
Do wyboru jest kilka różnych muzycznych kluczy, ale na razie zajmiemy się tylko jednym: kluczem wiolinowym . Na kluczu wiolinowym nuty są przedstawione na pięciolinii w następujący sposób:

Linie
F ----------
D ----------
B ----------
G ----------
E ----------
Przestrzenie  
   ----------  
mi
   ----------  
do
   ----------  
ZA
   ----------  
fa
   ----------

Formatowanie wejścia

Dane wejściowe będą podawane jako pojedynczy ciąg, jak następuje:

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

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

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

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

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

Pięć wierszy i cztery pola pięciolinii zbudowane są z dziewięciu rzędów znaków. Linie pięciolinii są zbudowane z -(łączników) znaków, a spacje z (spacją). Każdy wiersz jest oddzielony od następnego pojedynczym znakiem nowej linii, np .:
-----\n \n-----\n \n-----\n \n-----\n \n-----\n
Wiersze mają dowolną długość (do rozsądnej ilości, którą może obsłużyć język programowania), a każdy wiersz ma dokładnie taką samą długość w znakach jak inne. Zauważ też, że rzędy zawsze będą miały długość podzielną przez trzy (aby dopasować wzór jednej nuty, po której następują dwie kolumny bez nuty).

Notatki są umieszczane na tym kiju, zastępując odpowiednią postać -lub postać o. Nuty mogą być również podnoszone (ostre) lub obniżane (płaskie) o pół tonu (około połowy różnicy częstotliwości między nutą a sąsiednimi nutami). Będzie to reprezentowane odpowiednio przez postacie #i bzamiast o. Każda uwaga zostanie oddzielona od następnej dokładnie dwóch -znaków, a pierwsza uwaga będzie zawsze występować na pierwszym „kolumny” z -i (spacja) znaków.

Kiedy wypisujesz nazwy nut, twój program powinien zawsze używać wielkich liter ( A B C D E F G) odpowiadających nucie podanej na pięciolinii. W przypadku nut ostrych ( #) i płaskich ( b) program musi dołączyć odpowiednio literę odpowiadającą nucie #i bodpowiednio literę. Aby nuta naturalna nie była ostra ani płaska, zamiast niej należy dołączyć (spację).

Przykład

Wejście:

--------------------- o--
                  o     
--------------- o --------
            o           
---------b--------------
      o                 
--- o --------------------
o                       
------------------------

* Uwaga: cała „pusta przestrzeń” w tym przykładzie jest w rzeczywistości (znak spacji).
W takim przypadku (prosta skala F-dur) program powinien wypisać to:

FGA Bb CDEF

Zwróć uwagę, że odstępy między znakami wyjścia powinny być dokładnie takie, jak pokazano powyżej, aby poprawnie pasowały do ​​nut na pięciolinii. Pomiędzy wszystkimi nazwami nut znajdują się dwa znaki (spacja), z wyjątkiem między Bbi C. bTutaj zastępuje jeden z (spacja) znaków.

Kolejny przykład Dane
wejściowe:

------------------------
                     o  
------------------ # -----
               #        
------------ o -----------
         o              
------ # -----------------
   #                    
o -----------------------

Wynik:
E F# G# A B C# D# E

Jeszcze jeden przykład szczęścia Powodzenia
:

---------------------
oooo           
---------------------
         o              
---------------------

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

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

Wynik:
E E E C E G G

Zasady

  • Nuty zostaną podane tylko w pięcioliniowym zakresie pięciolinii od E do Fis (z wyjątkiem wyzwań, patrz poniżej)
  • Każda nuta może być ostra lub płaska, nie tylko te często spotykane w muzyce (np. Pomimo tego, że B # faktycznie jest grany jako C w rzeczywistości, B # może nadal występować na wejściu)
  • Możesz założyć, że będzie dokładnie jedna nuta na 3 kolumny (więc nie będzie żadnych akordów lub czegoś podobnego, a także żadnych pauz)
  • Możesz założyć, że po ostatniej nucie następują dwie kolumny bez nut
  • Możesz założyć, że po ostatnim wierszu pięcioliniowym pojawi się pojedynczy znak nowej linii
  • Dane wejściowe należy pobierać z STDIN (lub odpowiednika językowego) lub jako parametr funkcji
  • Dane wyjściowe powinny być do STDOUT (lub odpowiednika językowego) lub jako wynik zwrotny, jeśli twój program jest funkcją
  • Standardowe luki i wbudowane są dozwolone! Muzyka polega na eksperymentowaniu i zabawie. Śmiało i baw się dobrze ze swoim językiem (choć pamiętaj, że wykorzystanie luki może nie dać najciekawszego programu)
  • To jest , więc wygrywa najkrótszy program w bajtach

Wyzwania premiowe

  • -10%, jeśli Twój program może również z powodzeniem przetworzyć przestrzeń powyżej górnej linii pięciolinii (G, G #, Gb).
  • -10%, jeśli twój program może również z powodzeniem przetworzyć przestrzeń poniżej dolnej linii personelu (D, D #, Db)
  • W takich przypadkach program pobierałby jako wiersz dodatkowy wiersz na początku i na końcu; wiersze te należy traktować dokładnie tak samo jak pozostałe dziewięć wierszy
MC ΔT
źródło
Tak, zdaję sobie sprawę, że jedno jest dość podobne do mojego pytania. Jednak ten otrzymał tylko jedną odpowiedź. Miałem nadzieję uprościć coś, aby zaangażować więcej języków. I tak naprawdę uważam, że wyzwanie polega na odwróceniu, przekształcaniu nut w pięciolinię.
MC ΔT

Odpowiedzi:

3

CJam ( 40 37 * 0,8 = 29,6 punktów)

qN/z3%{_{iD%6>}#_~'H,65>=@@=+'oSerS}%

Demo online

Dzięki rzeczywiście dla wskazując kilka predefiniowanych zmiennych, które Zapomniałam o.

Peter Taylor
źródło
Bardzo schludny! Możesz ogolić kilka bajtów, używając S do znaków spacji. Dodatkowo zamieniasz 13 na D.
MC ΔT
1

Rubinowy, 106 bajtów * 0,8 = 84,8

->s{a=' '*l=s.index('
')+1
s.size.times{|i|s[i].ord&34>33&&(a[i%l,2]='GFEDCBA'[i/l%7]+s[i].tr(?o,' '))}
a}

Niegolfowany w programie testowym

f=->s{a=' '*l=s.index('
')+1                                 #l = length of first row, initialize string a to l spaces
  s.size.times{|i|                   #for each character in s
  s[i].ord&34>33&&                   #if ASCII code for ob#
   (a[i%l,2]=                        #change 2 bytes in a to the following string
   'GFEDCBA'[i/l%7]+s[i].tr(?o,' '))}#note letter, and copy of symbol ob# (transcribe to space if o)
a}                                   #return a



t='                        
---------------------o--
                  o     
---------------o--------
            o           
---------b--------------
      o                 
---o--------------------
o                       
------------------------

'

u='                        
------------------------
                     o  
------------------#-----
               #        
------------o-----------
         o              
------#-----------------
   #                    
o-----------------------

'

v='                     
---------------------
o  o  o     o        
---------------------
         o           
---------------------

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

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

'

puts f[t]
puts f[u]
puts f[v]
Level River St
źródło
1

JavaScript (ES6), 144 bajty - 20% = 115,2

f=s=>(n=[],l=s.indexOf(`
`)+1,[...s].map((v,i)=>(x=i%l,h=v.match(/[ob#]/),n[x]=h?"GFEDCBAGFED"[i/l|0]:n[x]||" ",h&&v!="o"?n[x+1]=v:0)),n.join``)

Wyjaśnienie

f=s=>(
  n=[],                      // n = array of note letters
  l=s.indexOf(`
`)+1,                        // l = line length
  [...s].map((v,i)=>(        // iterate through each character
    x=i%l,                   // x = position within current line
    h=v.match(/[ob#]/),      // h = character is note
    n[x]=                    // set current note letter to:
      h?"GFEDCBAGFED"[i/l|0] //     if it is a note, the letter
      :n[x]||" ",            //     if not, the current value or space if null
    h&&v!="o"?n[x+1]=v:0     // put the sharp/flat symbol at the next position
  )),
  n.join``                   // return the note letters as a string
)

Test

Pamiętaj, aby dodać linię powyżej pięciolinii, która jest dokładną długością innych linii, ponieważ to rozwiązanie obejmuje analizowanie linii powyżej i poniżej pięciolinii.

f=s=>(n=[],l=s.indexOf(`
`)+1,[...s].map((v,i)=>(x=i%l,h=v.match(/[ob#]/),n[x]=h?"GFEDCBAGFED"[i/l|0]:n[x]||" ",h&&v!="o"?n[x+1]=v:0)),n.join``)
<textarea id="input" style="float:left;width:200px;height:175px">                        
---------------------o--
                  o     
---------------o--------
            o           
---------b--------------
      o                 
---o--------------------
o                       
------------------------
                        </textarea>
<div style="float:left">
  <button onclick="results.innerHTML=f(input.value)">Test</button>
  <pre id="results"></pre>
</div>

użytkownik 81655
źródło