Lass uns Musik machen!

11

Viele Leute spielen gerne Musik zum Spaß und zur Unterhaltung. Leider ist Musik manchmal ziemlich schwierig. Deshalb bist du hier!

Aufgabe

Es ist Ihre Aufgabe, das Lesen von Musik für diejenigen, die damit zu kämpfen haben, viel einfacher zu machen. Sie müssen ein Programm oder eine Funktion schreiben, die einen musikalischen Stab als Eingabe verwendet und die Namen der auf diesem Stab geschriebenen Noten ausgibt.

Stab, Notenschlüssel und Notizen

Ein musikalischer Stab oder Stab besteht aus fünf horizontalen Linien, zwischen denen sich vier Leerzeichen befinden. Jede Linie oder jedes Leerzeichen repräsentiert je nach Notenschlüssel eine andere Note (Tonhöhe).
Es gibt ein paar verschiedene Musikschlüssel zur Auswahl, aber wir werden uns vorerst nur mit einem befassen: dem Violinschlüssel . Auf dem Violinschlüssel sind die Noten im Stab wie folgt dargestellt:

Linien
F ----------
D ----------
B ----------
G ----------
E ----------
Räume  
   ----------  
E.
   ----------  
C.
   ----------  
EIN
   ----------  
F.
   ----------

Formatierung der Eingabe

Die Eingabe erfolgt wie folgt als einzelne Zeichenfolge:

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

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

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

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

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

Die fünf Zeilen und vier Leerzeichen des Personals bestehen aus neun Zeichenreihen. Die Zeilen des Personals bestehen aus -(Bindestrich-) Zeichen und Leerzeichen mit (Leerzeichen). Jede Zeile ist durch ein einzelnes Zeilenumbruchzeichen von der nächsten getrennt, z. B.:
-----\n \n-----\n \n-----\n \n-----\n \n-----\n
Die Zeilen haben eine beliebige Länge (bis zu einem angemessenen Betrag, der von Ihrer Programmiersprache verarbeitet werden kann), und jede Zeile hat in Zeichen genau die gleiche Länge wie die anderen. Beachten Sie auch, dass die Zeilen immer eine Länge haben, die durch drei teilbar ist (passend zum Muster einer Note, gefolgt von zwei Spalten ohne Note).

Notizen werden auf diesen Stab gelegt, indem das entsprechende -oder Zeichen durch ersetzt wird o. Noten können auch um einen Halbton angehoben (scharf) oder abgesenkt (flach) werden (etwa die Hälfte der Frequenzdifferenz zwischen einer Note und den angrenzenden Noten). Dies wird durch die Zeichen dargestellt werden #und bjeweils anstelle der o. Jede Note wird durch genau zwei -Zeichen von der nächsten getrennt , und die erste Note erscheint immer in der ersten "Spalte" von -und (Leerzeichen).

Bei der Ausgabe von Notennamen sollte Ihr Programm immer die Großbuchstaben ( A B C D E F G) verwenden, die der Notiz auf dem Stab entsprechen. Für scharfe ( #) und Wohnung ( b) Notizen, Ihr Programm anzuhängen #und bjeweils mit dem Buchstaben auf die Note entspricht. Für eine natürliche Note, die nicht scharf oder flach ist, sollte stattdessen ein (Leerzeichen) angehängt werden.

Beispiel

Eingang:

---------------------Ö--
                  Ö     
---------------Ö--------
            Ö           
--------- b --------------
      Ö                 
---Ö--------------------
Ö                       
------------------------

* Beachten Sie, dass der gesamte "leere Raum" in diesem Beispiel tatsächlich (Leerzeichen) ist.
In diesem Fall (eine einfache F-Dur-Tonleiter) sollte Ihr Programm Folgendes ausgeben:

FGA Bb CDEF

Beachten Sie, dass der Abstand zwischen den Zeichen der Ausgabe genau wie oben gezeigt sein sollte, damit er korrekt zu den Notizen auf dem Stab passt. Zwischen allen Notennamen befinden sich zwei (Leerzeichen), außer zwischen Bbund C. Das bhier ersetzt eines der (Leerzeichen-) Zeichen.

Ein weiteres Beispiel
Eingabe:

------------------------
                     Ö  
------------------ # -----
               #        
------------Ö-----------
         Ö              
------ # -----------------
   #                    
Ö-----------------------

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

Ein weiteres Beispiel für viel Glück
Input:

---------------------
oooo           
---------------------
         Ö              
---------------------

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

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

Ausgabe:
E E E C E G G

Regeln

  • Notizen werden immer nur im fünfzeiligen Personalbereich von Es bis Fis gegeben (mit Ausnahme der Herausforderungen, siehe unten).
  • Jede Note kann scharf oder flach sein, nicht nur die in der Musik üblichen (z. B. obwohl B # in der Realität nur als C gespielt wird, kann B # immer noch in der Eingabe vorkommen).
  • Sie können davon ausgehen, dass es genau eine Note pro 3 Spalten gibt (es gibt also keine Akkorde oder ähnliches und auch keine Pausen).
  • Sie können davon ausgehen, dass auf die letzte Notiz zwei Spalten ohne Notizen folgen
  • Sie können davon ausgehen, dass auf die letzte Zeile des Personals ein einzelnes Zeilenumbruchzeichen folgt
  • Die Eingabe sollte über STDIN (oder ein Sprachäquivalent) oder als Funktionsparameter erfolgen
  • Die Ausgabe sollte in STDOUT (oder einem Sprachäquivalent) oder als Rückgabeergebnis erfolgen, wenn Ihr Programm eine Funktion ist
  • Standardlücken und Einbauten sind erlaubt! Bei Musik geht es darum zu experimentieren und herumzuspielen. Machen Sie weiter und haben Sie Spaß mit Ihrer Sprache (obwohl Sie erkennen, dass das Ausnutzen einer Lücke möglicherweise nicht das interessanteste Programm hervorbringt)
  • Dies ist , also gewinnt das kürzeste Programm in Bytes

Bonusherausforderungen

  • -10%, wenn Ihr Programm auch den Platz über der obersten Zeile des Personals (G, G #, Gb) erfolgreich verarbeiten kann.
  • -10%, wenn Ihr Programm auch den Platz unter dem Endergebnis des Personals erfolgreich verarbeiten kann (D, D #, Db)
  • In diesen Fällen würde Ihr Programm am Anfang und am Ende eine zusätzliche Zeile als Eingabe verwenden. Diese Zeilen sollten genauso behandelt werden wie die anderen neun Zeilen
MC ΔT
quelle
Ja, mir ist klar, dass eine meiner Frage ziemlich ähnlich ist. Dieser bekam jedoch nur eine Antwort. Ich hatte gehofft, etwas einfacher zu machen, um mehr Sprachen einzubeziehen. Und tatsächlich glaube ich, dass die Herausforderung das Gegenteil beinhaltet, Notizen in einen Stab umzuwandeln.
MC ΔT

Antworten:

3

CJam ( 40 37 * 0,8 = 29,6 Punkte)

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

Online-Demo

Dank der Tat für den Hinweis auf einige vordefinierte Variablen , die ich vergessen hatte.

Peter Taylor
quelle
Sehr gepflegt! Sie können einige Bytes sparen, indem Sie S für Leerzeichen verwenden. Zusätzlich ersetzen Sie 13 durch D.
MC ΔT
1

Ruby, 106 Bytes * 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}

Ungolfed im Testprogramm

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.
quelle
1

JavaScript (ES6), 144 Byte - 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``)

Erläuterung

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
)

Prüfung

Denken Sie daran, eine Zeile über dem Stab einzufügen, die genau der Länge der anderen Zeilen entspricht, da diese Lösung das Parsen der Zeilen über und unter dem Stab umfasst.

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>

user81655
quelle