¡Hagamos música!

11

A mucha gente le gusta tocar música por diversión y entretenimiento. Desafortunadamente, la música es bastante difícil a veces. ¡Por eso estás aquí!

Tarea

Es su trabajo hacer que la lectura de música sea mucho más fácil para aquellos que luchan con ella. Debe escribir un programa o función que tome como entrada un pentagrama musical y que muestre los nombres de las notas escritas en ese pentagrama.

Personal, clave y notas

Un pentagrama musical , o pentagrama, son cinco líneas horizontales, entre las cuales hay cuatro espacios. Cada línea o espacio representa una nota diferente (tono), dependiendo de la clave.
Hay unas pocas claves musicales diferentes para elegir, pero solo trataremos con una por ahora: la clave de sol . En la clave de sol, las notas se representan en el pentagrama de la siguiente manera:

Líneas
F ----------
D ----------
B ----------
G ----------
E ----------
Espacios  
   ----------  
mi
   ----------  
C
   ----------  
UNA
   ----------  
F
   ----------

Formateo de la entrada

La entrada se dará como una sola cadena, de la siguiente manera:

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

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

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

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

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

Las cinco líneas y los cuatro espacios del pentagrama están formados por nueve filas de caracteres. Las líneas del pentagrama se construyen con caracteres -(guión) y espacios con (espacio). Cada fila está separada de la siguiente por un único carácter de nueva línea, por ejemplo: las
-----\n \n-----\n \n-----\n \n-----\n \n-----\n
filas tienen una longitud arbitraria (en una cantidad razonable que puede manejar su lenguaje de programación), y cada fila tiene exactamente la misma longitud en caracteres que las demás. También tenga en cuenta que las filas siempre serán de una longitud que sea divisible por tres (para ajustarse al patrón de una nota seguida de dos columnas sin una nota).

Las notas se colocan en este personal reemplazando el apropiado -o el carácter con o. Las notas también se pueden subir (agudo) o bajar (plano) en tono con un semitono (aproximadamente la mitad de la diferencia de frecuencia entre una nota y sus notas adyacentes). Esto estará representado por los caracteres #y b, respectivamente, en lugar de o. Cada nota estará separada de la siguiente por exactamente dos -caracteres, y la primera nota siempre aparecerá en la primera "columna" de -y (espacio) caracteres.

Al generar nombres de notas, su programa siempre debe usar las letras en mayúscula ( A B C D E F G) correspondientes a la nota dada en el pentagrama. Para las notas agudas ( #) y planas ( b), su programa necesita agregar #y b, respectivamente, a la letra correspondiente a la nota. Para una nota natural que no sea nítida o plana, se debe agregar un (espacio) en su lugar.

Ejemplo

Entrada:

--------------------- o--
                  o     
--------------- o --------
            o           
---------si--------------
      o                 
--- o --------------------
o                       
------------------------

* tenga en cuenta que todo el "espacio vacío" en este ejemplo es en realidad (carácter de espacio).
En este caso (una escala F mayor simple), su programa debería generar esto:

FGA Bb CDEF

Tenga en cuenta que el espacio entre los caracteres de la salida debe ser exactamente como se muestra arriba, para que se ajuste correctamente con las notas en el pentagrama. Entre todos los nombres de las notas hay dos caracteres (espacio), excepto entre Bby C. El baquí reemplaza uno de los caracteres (espacio).

Otro ejemplo de
entrada:

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

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

Un ejemplo más para la buena suerte.
Entrada:

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

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

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

Salida:
E E E C E G G

Reglas

  • Las notas solo se darán en el rango de personal de cinco líneas de E plano hasta F sostenido (a excepción de los desafíos, ver más abajo)
  • Cualquier nota puede ser nítida o plana, no solo las que se ven comúnmente en la música (por ejemplo, a pesar de que B # en realidad solo se reproduce como C en realidad, B # aún puede aparecer en la entrada)
  • Puede suponer que habrá exactamente una nota por 3 columnas (por lo que no habrá acordes ni nada de eso, y tampoco descansos)
  • Puede suponer que la última nota irá seguida de dos columnas sin notas.
  • Puede suponer que incluso la última línea del pentagrama irá seguida de un único carácter de nueva línea.
  • La entrada debe tomarse de STDIN (o equivalente de idioma) o como parámetro de función
  • La salida debe ser STDOUT (o equivalente de idioma) o como resultado de retorno si su programa es una función
  • Se permiten lagunas estándar e incorporadas. La música se trata de experimentar y jugar. Siga adelante y diviértase con su idioma (aunque reconozca que explotar una laguna puede no producir el programa más interesante)
  • Este es el , por lo que el programa más corto en bytes gana

Desafíos de bonificación

  • -10% si su programa también puede procesar con éxito el espacio por encima de la línea superior del personal (G, G #, Gb).
  • -10% si su programa también puede procesar con éxito el espacio debajo de la línea inferior del personal (D, D #, Db)
  • En estos casos, su programa tomaría como entrada una fila adicional al inicio y al final; estas filas deben tratarse exactamente igual que las otras nueve filas
MC ΔT
fuente
Sí, me doy cuenta de que uno es bastante similar a mi pregunta. Sin embargo, esa solo obtuvo una respuesta. Esperaba hacer algo más simple para involucrar más idiomas. Y en realidad, creo que el desafío implica lo contrario, convertir notas en un pentagrama.
MC ΔT

Respuestas:

3

CJam ( 40 37 * 0.8 = 29.6 puntos)

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

Demostración en línea

Gracias de hecho por señalar algunas variables predefinidas que había olvidado.

Peter Taylor
fuente
¡Muy aseado! Puede reducir algunos bytes utilizando S para los caracteres de espacio. Además, reemplaza 13 con 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}

Sin golf en el programa de prueba

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
fuente
1

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

Explicación

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
)

Prueba

Recuerde agregar una línea sobre el pentagrama que tenga la longitud exacta de las otras líneas porque esta solución incluye analizar las líneas sobre y debajo del pentagrama.

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>

usuario81655
fuente