Acordes de piano en teclas blancas

9

Historia de fondo [que no es verdad]

Un piano está configurado así:

! [http://www.piano-lessons-made-simple.com/images/2-Octave-Labled.gif

Sin embargo, en mi piano, ¡todas las teclas negras están rotas!

Sin embargo, todavía quiero poder tocar algunos acordes en mi piano roto.

En música, un acorde es un grupo de notas que se tocan juntas. Para permitir la entrada de acordes, primero definiré qué es un semitono.

¿Qué es un semitono?

Un semitono es la distancia más pequeña en la música occidental. Si observa la parte superior del piano, verá que generalmente puede pasar de una tecla negra a una tecla blanca, o viceversa; sin embargo, entre By Cy Ey Fno hay tecla negra.

¿Qué es un acorde?

Para los propósitos de este desafío, definimos un acorde como un grupo de notas con un cierto número de semitonos entre ellas. Por ejemplo, tomemos una toma en un 4-3-3acorde que comienza C(para la gente de la música, este es un acorde V 7 en fa mayor). Empezamos a C. Contamos hasta 4 semitonos: C#, D, D#, E. La siguiente nota es E, y contamos con 3 semitonos después de eso: F, F#, G. La siguiente nota es G, y contamos con 3 semitonos después de eso: G#, A, Bb. Entonces, lo tenemos C-E-G-Bb. ¡Hurra! Pero espera ... Bbes una llave negra y esas están rotas ... Sin embargo, si comenzamos desde G, ¡obtenemos G-B-D-F! ¡Hurra!

Entrada

La entrada se proporciona como una lista de enteros en cualquier formato razonable. Esto representa el acorde como se describió anteriormente.

Salida

La salida debería ser una lista de notas en las que puedo comenzar a necesitar solo usar teclas blancas. Esto también puede ser una cadena de todas las hasta 7 notas porque todos los nombres clave serán un solo carácter. También debe poder manejar tener una salida vacía.

Casos de prueba

input -> output // comments
4 3 -> C F G // this is a major triad
3 4 -> D E A // this is a minor triad
4 3 3 -> G // this is the major-minor seventh chord
3 3 3 -> [empty output] // this is the diminished-diminished seventh chord. All of them use black keys
4 4 -> [empty output] // this is an augmented triad
3 3 -> B // this is a diminished triad
1 -> B E // this is just a minor second
11 -> C F // this is just a major seventh

Otras especificaciones

  • Lagunas estándar prohibidas
  • Puede suponer que la entrada tiene al menos un número entero
  • Puede suponer que todos los enteros no son negativos y tienen menos de 12 (porque el piano se repite cada 12 notas)
  • La salida puede estar en cualquier orden

Criterios ganadores

Se aceptará la presentación válida más corta a partir del 15 de abril.

Hiperneutrino
fuente
Podemos suponer "no negativo y menor que 12". ¿No debería ser "positivo y menor o igual a 12"?
Jonathan Allan
@JonathanAllan Fundamentalmente no hay diferencia; mi método permite un perfecto unísono pero no una octava perfecta; el tuyo viceversa. Teóricamente, su restricción podría tener más sentido, pero creo que probablemente no debería cambiarla porque ya hay respuestas y no cambia el desafío fundamentalmente.
HyperNeutrino

Respuestas:

3

Jalea , 25 bytes

236ḃ2ṙЀ7+\€Ṭ
+\ịþ¢Ạ€TịØA

Pruébalo en línea! o ver un conjunto de pruebas

¿Cómo?

236ḃ2ṙЀ7+\€Ṭ - Link 1, white-note-offsets: no arguments
236ḃ2         - 236 in bijective base 2 [2, 2, 1, 2, 2, 1, 2] - semitones G->A, A->B ...
     ṙЀ7     - rotate left by, mapped over [1,2,3,4,5,6,7] - i.e. as above for each
                    starting white key (1st one A->B,B->C,...; 2nd B->C,C->D,...; etc)
         +\€  - reduce €ach with addition - i.e. absolute number of semitones: [[2,3,5,7,8,10,12],[1,3,5,6,8,10,12],[2,4,5,7,9,11,12],[2,3,5,7,9,10,12],[1,3,5,7,8,10,12],[2,4,6,7,9,11,12],[2,4,5,7,9,10,12]]
            Ṭ - untruth (vectorises) - make lists with 1s at those indexes: [[0,1,1,0,1,0,1,1,0,1,0,1],[1,0,1,0,1,1,0,1,0,1,0,1],[0,1,0,1,1,0,1,0,1,0,1,1],[0,1,1,0,1,0,1,0,1,1,0,1],[1,0,1,0,1,0,1,1,0,1,0,1],[0,1,0,1,0,1,1,0,1,0,1,1],[0,1,0,1,1,0,1,0,1,1,0,1]]

+\ịþ¢Ạ€TịØA - Main link: list of semitone gap integers (even negatives will work)
+\          - reduce by addition - gets the absolute semitone offsets needed
    ¢       - last link (1) as a nilad
   þ        - outer product with:
  ị         -     index into - 7 lists, each with 1s for white and 0s for black keys hit
                      note that indexing is modular and all the lists are length 12
                      so any integer is a valid absolute offset, not just 0-11 inclusive
     Ạ€     - all truthy for €ach - for each get a 1 if all keys are white ones, else 0
       T    - truthy indexes - get the valid starting white keys as numbers from 1 to 7
        ị   - index into:
         ØA -     the uppercase alphabet
Jonathan Allan
fuente
6

MATL , 31 bytes

Gracias a Jonathan Allan por una corrección.

'BAGFEDC'"GYs12X\110BQX@YSYsm?@

Pruébalo en línea! O verificar todos los casos de prueba .

Explicación

El patrón 2 2 1 2 2 2 1especifica los intervalos entre teclas blancas consecutivas. El programa utiliza un bucle que aplica todos los cambios cíclicos a este patrón básico, para probar cada tecla como una nota potencial más baja del acorde de entrada. Para cada turno, se obtiene la suma acumulativa del patrón. Por ejemplo, Bcomo la nota más baja potencial, el patrón se ha desplazado 1 2 2 1 2 2 2y su suma acumulativa es 1 3 5 6 8 10 12.

Ahora, para ver si esto puede soportar un 4 3 3acorde, calculamos la suma acumulativa de los intervalos de acordes, que es 4 7 10; reducirlo a través del módulo 12 basado en 1 (un intervalo de 14daría 2); y verifique si esos números son todos miembros de los valores permitidos 1 3 5 6 8 10 12. Ese no es el caso en este ejemplo. Si hubiera sido el caso, enviaríamos la carta B.

La correspondencia entre los cambios cíclicos y las letras de salida está definida por la cadena 'BAGFEDC'. Esto indica que 'B'(primer carácter) corresponde a un desplazamiento cíclico por 1; 'A'(segundo carácter) corresponde a un cambio cíclico por 2etc.

'BAGFEDC'  % Push this string
"          % For each character from the string
  G        %   Push input array
  Ys       %   Cumulative sum
  12X\     %   1-based modulo 12, element-wise (1,12,13,14 respectively give 1,12,1,2)
  110BQ    %   Push 110, convert to binary, add 1 element-wise: gives [2 2 1 2 2 2 1]
  X@       %   Push current iteration index, starting at 1
  YS       %   Cyclic shift to the right by that amount
  Ys       %   Cumulative sum
  m        %   Ismember. Gives an array of true of false entries
  ?        %   If all true
    @      %     Push current character
           %   End (implicit)
           % End (implicit)
           % Display (implicit)
Luis Mendo
fuente
5

Mathematica, 110 bytes (codificación ISO 8859-1)

±i_:=#&@@@Select["A#BC#D#EF#G#"~StringTake~{Mod[#,12,1]}&/@#&/@(Accumulate[i~Prepend~#]&/@Range@12),FreeQ@"#"]

Define una función unaria que ±toma una lista de enteros como entrada (sin restricciones en el tamaño o signos de los enteros, en realidad) y devuelve una lista de cadenas de un carácter. Por ejemplo, ±{3,4}vuelve {"A","D","E"}.

"A#BC#D#EF#G#"~StringTake~{Mod[#,12,1]}&/@#es una función que convierte una lista de enteros en los nombres de las notas correspondientes, excepto que #significa cualquier tecla negra. Esto se aplica a cada elemento de Accumulate[i~Prepend~#]&/@Range@12, que crea una lista de valores de notas a partir de la lista de entrada de la lista de intervalos de notas, comenzando con cada posible nota del 1 al 12. Filtramos todas las listas de nombres de notas que contienen el "#"uso Select[...,FreeQ@"#"], y luego devuelva la primera nota en cada lista restante usando #&@@@.

Greg Martin
fuente
Buena presentación!
HyperNeutrino
Pregunta: ¿Mathematica usa su propio sistema de bytes? Estos son 110 caracteres pero en UTF-8 son 111 bytes debido al +/-símbolo.
HyperNeutrino
Puede eliminar completamente la asignación y simplemente "devolver implícitamente" una función.
wizzwizz4
@ wizzwizz4: Descubrí que tenía que nombrar la variable Accumulate[i~Prepend~#]&porque, de lo contrario, habría un choque al curry. ¡Siéntete libre de encontrar una solución!
Greg Martin
@HyperNeutrino: tiene razón en que UTF-8 es la codificación estándar, pero Mathematica puede (generalmente) funcionar también en la codificación ISO 8859-1. Lo he notado en la publicación.
Greg Martin
3

Python 2, 159155 bytes

(Publicar esto después de asegurarse de que haya una presentación válida que sea más corta que esta)

import numpy
s='C.D.EF.G.A.B'
def k(y):return lambda x:s[(x+y)%12]
for i in range(12):
    if s[i]!='.'and'.'not in map(k(i),numpy.cumsum(input())):print s[i]

Casi solo la solución trivial. Entradas como una lista de enteros y salidas con cada carácter en una línea individual.

-4 bytes eliminando una variable innecesaria

Hiperneutrino
fuente
3

JavaScript (ES6), 72 71 68 bytes

a=>[..."C1D1EF1G1A1B"].filter((c,i,b)=>!+c>a.some(e=>+b[i+=e,i%12]))

Recorre cada tecla omitiendo las teclas negras, luego verifica que la suma acumulativa de semitonos nunca llegue a una tecla negra.

Editar: Guardado 3 bytes gracias a @Arnauld.

Neil
fuente
44
¡¿Legibilidad?! ¿Estás seguro de que estás en el sitio correcto? :-)
wizzwizz4