Dada una lista de acordes los etiqueta como 'Mayor' o 'Menor'.
Entrada
La entrada será una lista de acordes, uno por línea, compuesta de 3 notas separadas por un espacio. Cada nota consistirá en el nombre de la nota en mayúscula ( A
- G
) y un accidental opcional ( #
o b
). Los acordes pueden estar en cualquier inversión (es decir, las notas pueden estar en cualquier orden).
Salida
Si el acorde es mayor, salga 'Mayor'. Si el acorde es menor, envíe 'Menor'. Si el acorde no es mayor ni menor, genera una línea en blanco.
Ejemplo
Entrada
C E G
F Ab C
C Eb Gb
E G B
Db F Ab
Bb G D
D A Gb
Salida
Major
Minor
Minor
Major
Minor
Major
Scripts de prueba
Como en algunas de mis preguntas anteriores, una vez más eliminé algunos scripts de prueba creados originalmente por Joey y Ventero para proporcionar algunos casos de prueba para esta pregunta:
Uso: ./test [your program and its arguments]
Recompensas
Cada entrada que pueda verificar que cumpla con las especificaciones, pase las pruebas y obviamente haya tenido algún intento de jugar al golf recibirá un voto positivo de mí (así que proporcione instrucciones de uso con su respuesta). La solución más corta para fines del 13/10/2012 será aceptada como ganadora.
Una pequeña teoría
Para aquellos de ustedes que no tienen conocimientos de teoría musical, aquí hay suficiente información para que puedan competir.
Un acorde mayor o menor se compone de tres notas que están separadas por un patrón específico de semitonos. Si consideramos que la raíz (nota inferior) del acorde es 0, entonces un acorde mayor es el patrón 0-4-7 y un acorde menor es el patrón 0-3-7. Las cosas se vuelven más incómodas por el hecho de que algunas notas están separadas por un semitono y otras son un tono aparte. La propagación de semitonos de Ab
- G#
es la siguiente:
G#/Ab A A#/Bb B/Cb B#/C C#/Db D D#/Eb E/Fb E#/F F#/Gb G G#/Ab
0 1 2 3 4 5 6 7 8 9 10 11 12
G#/Ab
significa que esa G#
es la misma nota que Ab
. De esto podemos ver que el acorde Ab C Eb
es un acorde mayor, y eso Ab Cb Eb
es menor.
Para complicar más las cosas, el acorde Eb Cb Ab
se considera que es la misma que Ab Cb Eb
, Cb Eb Ab
y Cb Ab Eb
etcétera. Cada una de estas variaciones sigue siendo un acorde menor.
Respuestas:
GolfScript, 83 caracteres
Esta es una primera solución rápida; Estoy seguro de que esto se puede jugar más. Pasa el conjunto de pruebas de bash, después de corregir el error señalado por flodel en los comentarios.
Edición 1: guardado 5 caracteres con una forma más corta de reconocer los patrones de acordes mayores y menores canonicalizados.
Edición 2: guardó 2 caracteres más con una codificación de salida más compacta inspirada en la solución de grc. (¡Gracias!) Como efecto secundario, el código ahora imprime una línea en blanco adicional después de la salida, pero el arnés de prueba parece aceptar eso, así que supongo que está bien. :)
Así es como funciona:
El bucle externo
n%{ }%n*
solo divide la entrada en líneas, ejecuta el código dentro de las llaves para cada línea y une los resultados con nuevas líneas.' '%
divide cada línea en una matriz de notas. Para cada una de esas notas,1\{'A#BC D EF G'?+}/
luego convierte esa nota en un número de semitono buscando cada uno de sus caracteres en la cadena'A#BC D EF G'
y sumando las posiciones (que será -1 para cualquier carácter que no se encuentre en la cadena, incluyendo notablementeb
). (Estoy seguro de que he visto este truco usado antes). Finalmente,.
duplica cada número, de modo que, al final del ciclo, por ejemplo, la entradaF Ab C
se ha convertido[9 9 0 0 4 4]
.Luego ordenamos las notas con
$
, movemos la primera nota al final con(+
y dividimos la matriz en pares con2/
, de modo que ahora se vea, por ejemplo, como[[9 0] [0 4] [4 9]]
. Luego{~- 12%}%
mapea cada par de notas en su módulo de diferencia 12, convirtiendo nuestra matriz de ejemplo en[9 8 7]
.A continuación,
.(+
hace una copia de la matriz y gira sus elementos a la izquierda en una posición. Hacemos esto dos veces y recopilamos las copias en una matriz con]
, de modo que nuestro ejemplo ahora se ve así[[9 8 7] [8 7 9] [7 9 8]]
.Luego clasificamos esta matriz de matrices con
$
y tomamos el primer elemento, en este caso[7 9 8]
, con0=
. Luego hacemos una copia de esta matriz (.
), la clasificamos ($
), recopilamos la matriz sin clasificar y la sin clasificar en otra matriz de matrices (]
), y buscamos la primera aparición de la matriz[7 8 9]
(que se escribe10,7>
para guardar dos caracteres) ) en eso.Esto nos da ya sea
0
(si la matriz sin clasificar era[7 8 9]
, y por lo tanto el acorde es mayor),1
(si la matriz sin clasificar era una permutación de[7 8 9]
, que, dado que su primer elemento debe ser más pequeño, solo puede ser[7 9 8]
, haciendo que el acorde sea menor) o-1
(si incluso la matriz ordenada no es igual[7 8 9]
).Este número se usa como índice inicial en la cadena
"MMaijnoorr\n\n"
(donde los\n
s se dan como avances de línea reales en el código), de donde tomamos ese carácter y cada segundo posterior como salida. Si el índice es -1, comenzamos desde el último carácter de la cadena, que es solo un avance de línea.fuente
echo "G# B# Eb" | ruby golfscript.rb ilmari.gs
pero ¿cómo ejecuto el script de prueba en ella? Lo intenté./test ruby golfscript.rb ilmari.gs
pero no tenía nada de eso. (Ya te he dado un +1 porque obviamente funciona, pero tengo curiosidad)args="$@"
conargs=("$@")
ygot=$("$cmd" "$args")
congot=$("$cmd" "${args[@]}")
. (O simplemente hacergolfscript.rb
ejecutable y ejecutarlo como./test ./golfscript.rb chords.gs
.)Python, 160
fuente