Traducir pares de números a notas de guitarra

18

Un diagrama de diapasón de guitarra se ve así:

  0  1  2  3  4  5  6  7  8  9 10 11 12   <- Fret number (0 means it's open)
|-E--F--F#-G--G#-A--A#-B--C--C#-D--D#-E
|-B--C--C#-D--D#-E--F--F#-G--G#-A--A#-B 
|-G--G#-A--A#-B--C--C#-D--D#-E--F--F#-G
|-D--D#-E--F--F#-G--G#-A--A#-B--C--C#-D
|-A--A#-B--C--C#-D--D#-E--F--F#-G--G#-A
|-E--F--F#-G--G#-A--A#-B--C--C#-D--D#-E

Como puede ver, la primera cadena (desde arriba) abierta es un E. El primer traste en la primera cadena es un F. El cuarto traste en la tercera cuerda es a B. Tenga en cuenta que la primera nota es el traste cero, no la primera.

Esto se puede escribir con números en el formato string, fret. Las cadenas están numeradas del 1 al 6 de arriba a abajo. Los trastes están numerados del 0 al 12 de izquierda a derecha. El primero Ees por lo tanto 1, 0. Algunos otros ejemplos:

1, 0 --> E
1, 1 --> F
3, 5 --> C
5, 1 --> A# 
6, 6 --> A#

Desafío:

Tome Npares de números ( sy f) y genere una sucesión de notas delimitadas.

  • La entrada puede estar en cualquier formato adecuado. tuplas, matriz 2D, dos listas separadas, una lista entrelazada (string, fret, string, fret ...) etc.
  • El tono de salida debe estar separado, pero el delimitador es opcional (coma, espacio, guión ...). La salida puede ser mayúscula o minúscula.
  • s(para la cadena) estará en el rango [1, 6](puede optar por indexar i 0)
  • f (para traste) estará en el rango [0, 12]

Casos de prueba y ejemplos:

1 4 5 2 1 3   <- String
4 2 6 3 5 1   <- Fret
G# E D# D A G#

6 2 3 1 4 2 3 2 2 2 6 5 2
0 1 2 3 4 5 6 7 8 9 10 11 12
E C A G F# E C# F# G G# D G# B  

3 3 3 3 3 3 3 3 3 3 3 3 3   <- String
0 3 5 0 3 6 5 0 3 5 3 0 0   <- Fret
G A# C G A# C# C G A# C A# G G     

// The same test case, but different input and output format:
(3,0)(3,3)(3,5)(3,3)(3,6)(3,5)(3,0)(3,3)(3,5)(3,3)(3,0)(3,0)    
G,A#,C,G,A#,C#,C,G,A#,C,A#,G,G     

¡Buena suerte y feliz golf!

Stewie Griffin
fuente
No soy un guitarrista (ni siquiera un músico decente, de verdad), pero ¿no hay una omisión significativa aquí, si esperas una salida como melodías reconocibles? Es decir, la duración de la nota: entera, media, cuartos, etc.
jamesqf
1
@jamesqf No, está perfectamente bien siempre que conozcas la canción. Esta es actualmente la canción más popular en ultimate-guitar.com . Echa un vistazo a la introducción.
Stewie Griffin

Respuestas:

4

05AB1E , 48 47 43 40 bytes

Utiliza la codificación CP-1252 .

Tanto las cadenas como los trastes están basados ​​en 0.

v7YT5¾7)y`Šè+•™ÎÚ,Ülu•žh'#A«‡•7V3•3BS£è,

Explicación

v                                # for each pair in input
 7YT5¾7)                         # the list [7,2,10,5,0,7]
 y`                              # flatten the pair [string, fret] and places on stack
 Šè                              # index into the list above using the string
 +                               # add the fret
 •™ÎÚ,Ülu•žh'#A«‡•7V3•3BS£       # list of accords
 è                               # index into the string using the number calculated above
 ,                               # print

Pruébalo en línea!

Guardado 7 bytes gracias a Adnan

Emigna
fuente
1
¡Explotar errores es muy golfoso! .-)
Luis Mendo
"AA#BCC#DD#EFF#GG#"•7V3•3BS£en lugar de "A A# B C C# D D# E F F# G G#"#es unos pocos bytes más corto :).
Adnan
@Adnan: Ooh, buen cambio de base :)
Emigna
También una versión comprimida de la "AA#BCC#DD#EFF#GG#"cadena: •™ÎÚ,Ülu•žh'#A«‡(ya que se permite minúsculas: p).
Adnan
9

JavaScript (ES6), 79 70 bytes

a=>a.map(([s,f])=>"AA#BCC#DD#EFF#GG#".match(/.#?/g)[(s*7+(s>2)+f)%12])

Requiere cadenas basadas en 1. Editar: ahorró 9 bytes calculando directamente la cadena para trasladar la conversión, según la respuesta anterior de @ nimi.

Neil
fuente
@Arnauld Gracias, pero terminé apropiándome de la respuesta de @ nimi.
Neil
Mucho más eficiente de hecho;)
Arnauld
Inteligente. respuesta muy astuta
Rohan Jhunjhunwala
7

Mathematica, 62 bytes (no competitivos)

<<Music`;MusicScale[100(#2+{24,19,15,10,5,0}[[#]])&@@@#,E2,9]&

El {24,19,15,10,5,0}y el E2representan los tonos de cuerda abierta de las seis cuerdas de guitarra (por ejemplo, la cuerda superior está 24 semitonos por encima de la nota E2). No compite porque no imprime los nombres de las notas, ¡ reproduce la secuencia de notas! (solo si tiene Mathematica, desafortunadamente) Por ejemplo,

<<Music`;MusicScale[100(#2+{24,19,15,10,5,0}[[#]])&@@@#,E2,9]&@
 {{4,0},{3,2},{2,3},{1,2},{5,0},{4,2},{3,2},{2,2},
  {5,2},{4,4},{2,0},{2,3},{6,2},{4,4},{3,2},{2,2},
  {6,3},{4,0},{3,0},{2,0},{4,0},{4,4},{3,2},{2,3},
  {6,3},{3,0},{2,0},{2,3},{5,0},{4,2},{3,2},{2,2},{4,0}}

juega los primeros 4 compases del Canon de Pachelbel. (que es casi todo el Canon de Pachelbel que puedo soportar)

Greg Martin
fuente
7

MATL , 48 47 45 bytes

Gracias a @Emigna por una corrección con respecto al formato de entrada.

Guitarra y golf de código ... ¡Tenía que responder a esta!

'$)-27<'i)-'F F# G G# A A# B C C# D D#

El formato de entrada es: una matriz de cadenas (basadas en 1), luego una matriz de trastes (basados ​​en 0).

Pruébalo en línea!

Explicación

Algunas características del lenguaje utilizadas en esta respuesta:

  • Una cadena se convierte automáticamente en una matriz numérica de puntos de código ASCII cuando se le aplica alguna operación aritmética.
  • Las operaciones aritméticas funcionan por elementos , es decir, vectorizadas. Por lo tanto, la resta de una cadena y una matriz numérica del mismo tamaño proporciona una matriz con la resta de las entradas correspondientes.
  • La indexación se basa en 1 y es modular .
  • Una matriz de celdas es como una lista en otros idiomas. Puede contener elementos arbitrarios, posiblemente matrices de diferentes tipos o tamaños. Aquí se utilizará una matriz de celdas para almacenar cadenas de diferentes longitudes (los nombres de las notas).

Código comentado:

'$)-27<'                       % Push this string
i                              % Take first input (array of guitar strings)
)                              % Index into the string. For example, input [1 3] gives
                               % the string '$-' (indexing is 1-based)
-                              % Implicitly take second input (array of guitar frets).
                               % Subtract element-wise. This automatically converts the
                               % previous string into an array of ASCII codes. For
                               % example, second input [1 5] gives a result [-35 -40],
                               % which is [1 5] minus [36 45], where 36 and 45 are the
                               % ASCII codes of '$-' 
'F F# G G# A A# B C C# D D# E' % Push this string
Yb                             % Split at spaces. Gives a cell array of 12 (sub)strings:
                               % {'F', 'F#', 'G', ..., 'E'}
w)                             % Swap and index into the cell array of strings.
                               % Indexing is 1-based and modular. In the example, since
                               % the cell array has 12 elements, the indexing array
                               % [-35 -40] is the same [1 8], and thus it gives a 
                               % (sub-)array formed by the first and eighth cells: 
                               % {'F', 'C'}. This is displayed as the cells' contents,
                               % one per line
Luis Mendo
fuente
1
Sabía que iba a encontrar una respuesta tuya tan pronto como viera la palabra "Guitarra"
Suever
1
@LuisMendo ¡Muy bien! Me gusta el truco del índice ascii-char :)
Emigna
4

Java, 174

String f(int[]s,int[]f){String o="";for(int i=0;i<s.length;++i){int n =(7*s[i]-7+f[i]+(s[i]>2?1:0))%12*2;o+="E F F#G G#A A#B C C#D D#".substring(n,n+2).trim()+" ";}return o;}

Sin golf:

  String f(int[] s, int[] f) {
    String o = "";
    for (int i = 0; i < s.length; ++i) {
      int n = (7 * s[i] - 7 + f[i] + (s[i] > 2 ? 1 : 0)) % 12 * 2;
      o += "E F F#G G#A A#B C C#D D#".substring(n, n + 2).trim() + " ";
    }
    return o;
  }

fuente
3

C, 104 103 bytes

main(s,f){for(;~scanf("%d%d",&s,&f);printf("%.2s\n",
"E F F#G G#A A#B C C#D D#"+(f+7*~-s+(s>2))%12*2));}

Toma los números como string fretpares en stdin y genera la nota después de cada par. P.ej:

1 4
G#
4 2
E 
5 6
D#
2 3
D 
orlp
fuente
3

Ruby, 63 bytes

toma una matriz de matrices de 2 elementos, en el orden [string,fret].

->x{x.map{|i|"BEADGCF"[6-n=((i[0]-3)%5+2+i[1]*7)%12]+?#*(n/7)}}

Explicación

En la afinación estándar, la guitarra es uno de los pocos instrumentos de cuerda (arqueados o con trastes) que tiene intervalos inconsistentes entre sus cuerdas. La mayoría tiene un intervalo constante de 5 semitonos entre todos los pares de cuerdas adyacentes (un "cuarto") o un intervalo consistente de 7 semitonos entre todos los pares de cuerdas adyacentes (un "quinto"). Estos corresponden a relaciones de frecuencia de 3: 4 y 2: 3 respectivamente, y son segundos en importancia solo a la "octava" con relación de frecuencia 1: 2.

La guitarra tiene principalmente intervalos de 5 semitonos. Si tuviera 5 de estos, tendría una diferencia de 25 semitonos entre la 1ra y la 6ta cuerda. En cambio, el intervalo entre la 2da y 3ra cuerda se reduce a 4 semitonos, dando una diferencia de 24 semitonos (2 octavas) que es mejor para tocar acordes.

Esto es inconveniente para el programa, por lo que comenzamos cambiando la entonación de guitarra indexada en 1 por una entonación de bajo de 5 cuerdas indexada en 0, que tiene todos los intervalos de 5 semitonos:

formula (i[0]-3)%5
Before                            After
String      6 5 4 3 2 1           String 4 3 2 1 0
Note        E A D G B E           Note   B E A D G

A continuación, agregamos 2 y damos la afinación de un bajo ficticio de 12 cuerdas, con la entonación de las cuerdas abiertas de la siguiente manera, y todos los intervalos son 5 semitonos (existen "bajos" de 12 cuerdas, pero no estoy seguro de que haya muchos con esto precisamente Afinación.)

String       11 10 9  8  7  6  5  4  3  2  1  0 
Note         A# D# G# C# F# B  E  A  D  G  C  F

Como se puede ver, todos los objetos punzantes se agrupan. Este patrón puede repetirse hasta el infinito. Se le conoce como el "círculo de quintas" y es fundamental para la escala musical occidental (con un poco de ajuste de sintonía del círculo puede ser cerrado debido al hecho de que (3/2)**12y 2**7son números muy similares.

Ahora nos ocupamos del parámetro de traste. A diferencia de muchas otras respuestas aquí, que traducen el parámetro de cadena en varios trastes, yo traduzco el parámetro de traste en varias cadenas. En la tabla anterior se puede ver que sumar 7 al número de cadena nos coloca en una cadena cuyo nombre de nota es un semitono más alto. (Está en una octava completamente diferente, pero eso no importa). Entonces agregamos i[1]*7al número de cadena y tomamos el módulo 12:

n=(i[0]-3)%5+2+i[1]*7)%12

Restamos esto de 6 para obtener un número en el rango de 6 a -5 y buscamos la letra BEADGCF(Ruby permite que los índices negativos vuelvan al final de la matriz). Si n>=7necesitamos agregar un #símbolo para completar la salida .

Programa de prueba

f=->x{x.map{|i|"BEADGCF"[6-n=((i[0]-3)%5+2+i[1]*7)%12]+?#*(n/7)}}

z=[[6, 2, 3, 1, 4, 2, 3, 2, 2, 2, 6,5,2],[0, 1, 2, 3, 4 ,5 ,6 ,7, 8, 9, 10, 11, 12]].transpose

puts f[z]

Salida

E
C
A
G
F#
E
C#
F#
G
G#
D
G#
B
Level River St
fuente
3

C #, 131 bytes

string n(int[]s,int[]f){return string.Join(" ",s.Zip(f,(x,y)=>"E,F,F#,G,G#,A,A#,B,C,C#,D,D#".Split(',')[(7*x-7+y+(x<3?0:1))%12]));}

Ingrese dos listas separadas, las cadenas están basadas en 1.

Taco
fuente
1
Bienvenido al sitio! Buena primera respuesta.
DJMcMayhem
@DJMcMayhem: Gracias :-)
Taco
1

Clora , 55 bytes

@T[0,7,2,10,5,0,7]+N%12@T[,A,A#,B,C#,D,D#,E,F,F#,G,G#]!

Explicación

@ modo numérico (lectura de entrada como números)

T[0,7,2,10,5,0,7] Transformar la entrada usando la matriz, ex matriz [Entrada]

+N Agregar N (siguiente valor de entrada) a la entrada actual

%12 Módulo 12 el valor de entrada actual

@ Marcar modo numérico desactivado

T[,A,A#,B,C#,D,D#,E,F,F#,G,G#] Traduzca la entrada a una matriz

! Usar entrada como valor de salida

OPSXCQ
fuente
1

Java 7 197163 bytes

void f(int[]s,int[]f){String[]l={"A","A#","B","C","C#","D","D#","E","F","F#","G","G#"};int[]d={0,7,2,10,5,0,7};int j=0;for(int i:s)out.print(l[(d[i]+f[j++])%12]);}

Sin golf

  void f(int[]s,int[]f){
 String[]l={"A","A#","B","C","C#","D","D#","E","F","F#","G","G#"};
int[]d={0,7,2,10,5,0,7};
    int j=0;
    for(int i:s)
        out.print(l[(d[i]+f[j++])%12]);



}
Nudo numérico
fuente
0

Python 2, 94, 91 , 88 bytes

for s,f in input():print"A A# B C C# D D# E F F# G G#".split()[([7,2,10,5,0,7][s]+f)%12]

Probablemente hay algunas mejoras obvias por hacer. La entrada es una lista de pares, y las cadenas están indexadas en 0, por ejemplo:

[0, 4], [3, 2], [4, 6]...
DJMcMayhem
fuente
0

Haskell, 83 82 bytes

zipWith$(!!).(`drop`cycle(words"A# B C C# D D# E F F# G G# A")).([6,1,9,4,11,6]!!)

Toma una lista de cadenas y una lista de trastes, ambos indexados a 0. Ejemplo de uso:

Prelude >  ( zipWith$(!!).(`drop`cycle$words"A# B C C# D D# E F F# G G# A").([6,1,9,4,11,6]!!) ) [0,1,2,3,4,5] [0,0,0,0,0,0]
["E","B","G","D","A","E"]

De la lista infinita de notas que comienzan con A#, elimine el número de notas dadas por la lista [6,1,9,4,11,6]en el índice de la cadena y elija la nota en el índice del traste de la lista restante.

nimi
fuente
Lamentablemente, los intervalos entre cadenas no son todos iguales.
Neil
@Neil: ... arreglado.
nimi
Resultó ser una solución simple en JavaScript (s*7)+(s>2), así que ahora estoy usando eso en mi respuesta.
Neil
@Neil: ... trabajando en eso también.
nimi
0

JavaScript (ES6), 82 81 bytes

a=>a.map(b=>(q=(b[0]+.3+b[1]*7.3|0)%12/1.7+10.3).toString(17)[0]+(q%1>.5?"#":""))

Quería probar una respuesta matemática, pero resultó un poco larga. Tal vez hay una manera de jugar al golf ...

Fragmento de prueba

ETHproducciones
fuente
Quería usarlo, toString(17)pero luché por obtener un conteo de bytes razonable.
Neil
0

PHP, 102 bytes

<?foreach($_GET[i]as$t)echo[E,F,"F#",G,"G#",A,"A#",B,C,"C#",D,"D#"][[0,7,3,10,5][$t[0]%5]+$t[1]%12]._;

Ingrese como matriz múltiple, ambos basados ​​en 0, por ejemplo, '[[2,0], [5,3], [2,12], [3,8], [0,3]]'

Alternativa agradable 106 Bytes para establecer el # basado en mod 7 congruente

<?foreach($_GET[i]as$t)echo EFFGGAABCCDD[$d=[0,7,3,10,5][$t[0]%5]+$t[1]%12].["","#"][$d%7?$d%7%2?0:1:0]._;
Jörg Hülsermann
fuente