Dada uma lista de acordes, identifique-os como 'Maior' ou 'Menor'.
Entrada
A entrada será uma lista de acordes, um por linha, composta de 3 notas separadas por um espaço. Cada nota consistirá no nome da nota em maiúsculas ( A
- G
) e um acidental ( #
ou b
) opcional . Os acordes podem estar em qualquer inversão (ou seja, as notas podem estar em qualquer ordem).
Resultado
Se o acorde for maior, produza 'Maior'. Se o acorde for menor, produza 'Menor'. Se o acorde não for maior nem menor, produza uma linha em branco.
Exemplo
Entrada
C E G
F Ab C
C Eb Gb
E G B
Db F Ab
Bb G D
D A Gb
Resultado
Major
Minor
Minor
Major
Minor
Major
Scripts de teste
Como em algumas das minhas perguntas anteriores, mais uma vez massacrei alguns scripts de teste criados originalmente por Joey e Ventero para fornecer alguns casos de teste para esta pergunta:
Uso: ./test [your program and its arguments]
Recompensas
Cada entrada que eu possa verificar que atenda às especificações, passa nos testes e obviamente teve alguma tentativa de jogar golfe receberá um voto positivo de mim (por isso, forneça instruções de uso com sua resposta). A solução mais curta até o final de 13/10/2012 será aceita como vencedora.
Um pouco de teoria
Para aqueles que não têm conhecimento de teoria musical, aqui estão informações suficientes para poder competir.
Um acorde maior ou menor é composto de três notas que são separadas por um padrão específico de semitons. Se considerarmos que a raiz (nota inferior) do acorde é 0, um acorde maior é o padrão 0-4-7 e um acorde menor é o padrão 0-3-7. As coisas ficam mais estranhas pelo fato de que algumas notas são um semitom à parte e outras são um tom à parte. A propagação de semitons de Ab
- G#
é a seguinte:
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 essa G#
é a mesma nota que Ab
. A partir disso, podemos ver que o acorde Ab C Eb
é um acorde maior e Ab Cb Eb
menor.
Para complicar ainda mais, o acorde Eb Cb Ab
é considerado o mesmo que Ab Cb Eb
, Cb Eb Ab
e Cb Ab Eb
e assim por diante. Cada uma dessas variações ainda é um acorde menor.
Respostas:
GolfScript, 83 caracteres
Esta é uma primeira solução rápida; Tenho certeza de que isso pode ser jogado ainda mais. Passa no conjunto de testes do bash, após corrigir o erro apontado pelo flodel nos comentários.
Editar 1: salvou 5 caracteres com uma maneira mais curta de reconhecer os padrões de acordes maior e menor canonizados.
Edit 2: economizou mais 2 caracteres com codificação de saída mais compacta inspirada na solução da grc. (Obrigado!) Como efeito colateral, o código agora imprime uma linha em branco extra após a saída, mas o equipamento de teste parece aceitar isso, então acho que está tudo bem. :)
Veja como funciona:
O loop externo
n%{ }%n*
apenas divide a entrada em linhas, executa o código dentro das chaves para cada linha e junta os resultados com novas linhas.' '%
divide cada linha em uma matriz de notas. Para cada uma dessas anotações,1\{'A#BC D EF G'?+}/
converte a anotação em um número de semitons pesquisando cada um de seus caracteres na sequência'A#BC D EF G'
e adicionando as posições (que será -1 para qualquer caractere não encontrado na sequência, incluindo inclusiveb
). (Tenho certeza de que já vi esse truque antes.) Finalmente, o.
número é duplicado, de modo que, no final do loop, por exemplo, a entradaF Ab C
foi transformada[9 9 0 0 4 4]
.Em seguida, classificamos as notas com
$
, movemos a primeira nota para o final com(+
e dividimos o array em pares com2/
, para que agora pareça, por exemplo[[9 0] [0 4] [4 9]]
. Em seguida,{~- 12%}%
mapeia cada par de notas para o seu módulo de diferença 12, transformando nosso exemplo de matriz[9 8 7]
.Em seguida,
.(+
faz uma cópia da matriz e gira seus elementos deixados em uma posição. Fazemos isso duas vezes e coletamos as cópias em uma matriz com]
, de modo que nosso exemplo agora seja semelhante[[9 8 7] [8 7 9] [7 9 8]]
.Em seguida, classificamos essa matriz de matrizes
$
e pegamos o primeiro elemento - nesse caso[7 9 8]
- com0=
. Em seguida, fazemos uma cópia dessa matriz (.
), classificamos ($
), coletamos a matriz não classificada e a não classificada em outra matriz de matrizes (]
) e pesquisamos a primeira ocorrência da matriz[7 8 9]
(que é escrita10,7>
para salvar dois caracteres). ) iniciar.Isso nos fornece
0
(se a matriz não classificada era[7 8 9]
e, portanto, o acorde é maior),1
(se a matriz não classificada era uma permutação de[7 8 9]
que, dado que seu primeiro elemento deve ser menor, só pode ser[7 9 8]
, tornando a corda menor) ou-1
(se mesmo a matriz classificada não for igual[7 8 9]
).Esse número é então usado como um índice inicial na string
"MMaijnoorr\n\n"
(onde os\n
s são dados como feeds de linha reais no código), a partir dos quais tomamos esse caractere e cada segundo subsequente como saída. Se o índice for -1, começamos com o último caractere da string, que é apenas um feed de linha.fonte
echo "G# B# Eb" | ruby golfscript.rb ilmari.gs
mas como executo o script de teste? Eu tentei,./test ruby golfscript.rb ilmari.gs
mas não estava tendo nada disso. (Eu já te dei um +1, porque, obviamente, funciona, mas eu sou apenas curioso)args="$@"
porargs=("$@")
egot=$("$cmd" "$args")
comgot=$("$cmd" "${args[@]}")
. (Ou simplesmente tornargolfscript.rb
executável e executá-lo como./test ./golfscript.rb chords.gs
.)Python, 160
fonte