Dados dois nomes de notas, você deve escrever um programa que determine se o intervalo formado por essas duas notas é consoante ou dissonante.
Introdução
Na música ocidental, existem apenas 12 tons "diferentes". Seus nomes, ordenados menor para o maior, são estas: C, C#, D, D#, E, F, F#, G, G#, A, A#, B
. A sequência é cíclica, ou seja, continua com outra C
após o B
infinitamente.
A distância entre dois tons é chamada de intervalo . O intervalo entre duas notas adjacentes na série acima (por exemplo, C — C#
ou E — F
) é chamado de semitom . O intervalo entre as notas mais distantes é definido como o número de etapas de semitons necessárias para ir do primeiro ao segundo (enquanto possivelmente envolve a sequência). Alguns exemplos: D to E
= 2 semitons, C to G
= 7 semitons, B to D#
= 4 semitons (isso envolve a sequência). 1 1
Agora, esses intervalos são divididos em duas categorias: consoante (soando agradavelmente se você tocar as duas notas ao mesmo tempo) e dissonante (nem tanto).
Vamos definir os intervalos consoantes como: 0, 3, 4, 5, 7, 8 e 9 semitons.
O restante deles é dissonante, a saber: 1, 2, 6, 10 e 11 semitons.
O desafio
Escreva um "programa" (no sentido amplo da palavra: uma função está perfeitamente bem) para fazer o seguinte:
Pegue dois nomes de notas (sequências da sequência acima) como entrada. Você pode tomá-los como quiser (do stdin, como argumentos, separados pelo que você quiser, até sinta-se à vontade para tomá-los como uma lista de caracteres (por exemplo
["C","#"]
).) No entanto, você não pode atribuir nenhum outro nome às notas (especialmente você não pode numerá-los de 0 a 11 e usar os números).Para os fãs de música por aí, as notas serão especificadas sem a oitava. Nesse caso, também não importa em qual ordem as notas vêm e qual é mais baixa e qual é mais alta. Por fim, você não precisa manipular nenhum nome que não esteja na lista acima. Nenhuma outra enarmônica como
E#
, sem apartamentos, alterações duplas e assim por diante.Escolha dois valores diferentes. Seu programa deve produzir um deles sempre que o intervalo formado pelas duas notas na entrada for consoante e o outro, se não for. (Pode ser
True
eFalse
, mas até π e e se você quiser :))Este é um código de golfe. O programa mais curto em bytes em cada idioma vence. Diverta-se!
Exemplos e casos de teste
Note 1 Note 2 Output Interval [semitones]
C D Dissonant 2
A# A# Consonant 0
G D Consonant 7 (wraparound)
D# A Dissonant 6
F E Dissonant 11
A C Consonant 3
Não adiciono mais, pois não há casos particularmente traiçoeiros nisso.
Este é o meu primeiro desafio, portanto qualquer crítica construtiva é muito bem-vinda: --). Se você achar a explicação da teoria superficial, sinta-se à vontade para fazer perguntas. Finalmente, por favor, não me diga que este é um joguete de este ou este . Eu tive certeza de que não é. (O último é bem parecido, mas mais complexo. Pensei que colocar um desafio um pouco mais simples tornaria mais fácil a participação de pessoas.)
1 : Tentei simplificar essa explicação o máximo que pude. Há muito mais teoria sobre os intervalos. Por favor, não me bata por deixá-lo de fora.
APL (Dyalog) ,
6239 bytesUsos
⎕IO←0
; 0 é consoante, 1 é dissonante. Leva a lista de caracteres de nota de base como argumento à esquerda e a lista de objetos cortantes como argumento à direita.Experimente online!
{
…}
Função anônima onde⍺
está o argumento da esquerda e⍵
é o argumento da direita⎕A[
...]∊'BCGKL'
é o A lphabet, indexado pelo seguinte, um membro da corda?⍕#
formate o espaço para nome raiz (gera o caractere nítido)⍵=
os caracteres de argumento corretos (os cortantes) são iguais a isso?(
…)+
Adicione o seguinte:'C D EF G A '⍳⍺
índices do caractere esquerdo caracteres na string-/
diferença entre aqueles|
valor absolutofonte
MATL ,
302726 bytesIntroduz as duas notas em linhas diferentes. Saídas
0
para consoante,1
para dissonante.Experimente online! Ou verifique todos os casos de teste .
Explicação
A cadeia de 11 caracteres
codifica as notas e os intervalos dissonantes, como a seguir.
O programa encontra primeiro os índices baseados em 1 dos caracteres de entrada na sequência acima. Uma entrada não nítida como
D
dará1
,E
dará3
, ...,C
dará11
. Esses números também podem ser considerados matrizes numéricas 1 × 1. Uma entrada nítida comoC#
dará a matriz 1 × 2[11 0]
, o que significa queC
foi encontrado na posição11
e#
não foi encontrado.Observe que as letras
JPIL
nunca estarão presentes na entrada. Por enquanto, eles são usados apenas como espaços reservados, de modo que, por exemplo, noteE
estão dois semitons acimaD
. Mas eles também serão úteis para definir intervalos dissonantes.Os números na primeira entrada da matriz 1 × 1 ou 1 × 2 correspondem ao tom das notas em semitons, sem contar os símbolos nítidos (ainda). Observe que a escala definida por esses números não começa em
C
; mas isso não importa, porque queremos apenas intervalos, ou seja, diferenças entre as notas. Subtrair os números obtidos daria o intervalo ou 12 menos o intervalo. Mas primeiro precisamos considerar o símbolo afiado.Para considerar notas nítidas, uma maneira de jogar golfe (em MATL) é adicionar
1
a cada entrada da matriz 1 × 1 ou 1 × 2 obtida anteriormente e somar a matriz (2 bytes). Assim, as notas não nítidas são aumentadas1
e as notas nítidas em2
. Isso torna as notas nítidas 1 semitom mais altas que as notas não nítidas, conforme necessário. Também estamos adicionando um semitom extra a todas as notas, mas isso não altera os intervalos entre elas. Então agora a notaD
dará o número do arremesso2
,D#
dará3
, ...,C
dará12
,C#
dará13
.Intervalos dissonantes são
1
,2
,6
,10
, ou11
. Eles têm simetria no módulo 12 : um intervalo entre duas notas é dissonante se e somente se o intervalo com as notas na ordem inversa, módulo 12, for dissonante.Se calcularmos as diferenças consecutivas da string
'DJEFPGIALBC'
, obtemos o vetor numéricoque contém precisamente os intervalos dissonantes, além de alguns valores negativos, que não serão úteis nem prejudiciais. Observe que é a escolha de letras adicionais
JPIL
na string'DJEFPGIALBC'
que define (através de diferenças consecutivas) os intervalos dissonantes.Para ver se as duas notas de entrada são dissonantes, tomamos a diferença absoluta de seus números de afinação. Por exemplo,
C
eD#
dará números12
e3
, respectivamente, e a diferença absoluta é9
. A diferença real seria-9
e o intervalo real seria3
(obtido como-9
módulo 12). Mas, graças à simetria mencionada acima, podemos considerar em9
vez de3
. Como9
não está presente no vetor de diferenças consecutivas, as notas são consoantes.fonte
JavaScript (ES6),
6864 bytesFaz as anotações como duas strings na sintaxe de currying
(a)(b)
. Retorna0
para dissonante ou1
consoante.Casos de teste
Mostrar snippet de código
Formatado e comentado
fonte
Geléia , 26 bytes
Um link monádico que obtém uma lista das duas notas (como listas de caracteres) e retorna
0
para consoante e1
dissonante.Experimente online! ou veja todas as entradas no conjunto de testes .
Quão?
fonte
Gelatina , 31 bytes
Experimente online!
wheeeeee 32 bytes a mais
Explicação
fonte
"G#", "A"
(dissonante) produz uma diferença da11
qual não está[1,2,6]
.Mathematica, 55 bytes
Mapeie o interno interno
Sound`PitchToNumber
na entrada (lista de duas seqüências), faça a diferença absoluta e faça a correspondência de padrões para números de intervalo dissonantes.Apenas por diversão (não concorrente)
Aqui estão algumas funções mais curtas que violam a restrição "você não pode atribuir nenhum outro nome às notas". O rudimentar
Music`
pacote possui constantes de notas predefinidas (comoA4 = 440.
) e a funçãoHertzToCents
(que pode ser jogada no golfe). Em vez de strings, usaremos as constantes da nota como argumentos, mas fornecidas em um formato diferente para cada função.A importação do pacote
<<Music`;
leva 9 bytes.Essa função converte uma string (como
"F#"
) em uma constante de nota (comoFsharp3
):Para aceitar intervalos maiores que uma oitava, substitua
Abs[…]
porMod[…,12]
.Por que alguns intervalos são considerados dissonantes? Um intervalo é uma razão de duas frequências. Se a relação tiver um numerador e denominador "simples", ela tende a ser mais consoante. Em ajuste de 5 limites , as proporções podem ser fatoradas em potências inteiras de apenas números primos menores ou iguais a 5. Nenhum intervalo de temperamento igual, além da oitava, é apenas um intervalo ; são apenas aproximações aproximadas usando potências da 12a raiz de 2.
Em vez de codificar quais números de intervalo são dissonantes, podemos encontrar uma aproximação racional do intervalo e determinar se o numerador e o denominador são "simples" (o que significa que o denominador é menor que 5 e a razão não divide 7).
Esta tabela mostra cada uma das etapas desse processo.
A aproximação racional está dentro
1/17
do intervalo, porque esse é o maior limite que distingue entre os 12 intervalos temperados iguais. Combinamos números racionais com o padrãoRational[a_,b_]
(ou apenasa_~_~b_
) primeiro e depois os inteiros com apenas_
.Isso culmina na seguinte função bastante curta que determina se uma taxa de frequência arbitrária (maior que 1) é consoante ou dissonante.
fonte
Mathematica, 118 bytes
Formulário de entrada
Saídas
obrigado @JonathanFrech -16 bytes
fonte
Consonant
eDissonant
. Você pode gerar dois valores em vez deles (0/1, ... qualquer que seja). Isso pode economizar alguns bytes.If[...,0,1]
e definirTrue->Consonant; False->Dissonant
?StringCases["CC#DD#EFF#GG#AA#B",_~~"#"...]
# 42 Bytes{1,2,6,10,11}
por1|2|6|10|11
Carvão , 30 bytes
Experimente online! Link é a versão detalhada do código. Saídas 1 para consoante, 0 para dissonante. Explicação:
fonte
⌕ζ
é usado para "encontrar índice"?ζ
é a variável atribuída anteriormente.J, 68 bytes
explicação
Uma implementação direta e não super-golfe em J:
A entrada é fornecida como notas detalhadas em caixas (produzidas usando corte), em ordem.
Encontre seus índices no intervalo de notas:
(<;._1',C,C#,D,D#,E,F,F#,G,G#,A,A#,B')i.]
Subtraia o primeiro do segundo:
-~/
Pegue o restante quando dividido por 12:
12|
Verifique se é uma das notas dissonantes:
e.&1 2 6 10 11
Experimente online!
fonte
/// ,
9088 bytesExperimente online! (todos os casos de teste de uma vez)
,B#
em cada caso de teste.,
para consoante,,#
para dissonante.##
) ouE#
em alguns casos particulares. Caso contrário, a saída é,
para consoante,#,
para dissonante (graças à simetria do módulo 12)fonte
C (gcc) , 91 bytes
ligar:
f("A#", "D")
Valor de retorno:
Bônus: A função não diferencia maiúsculas de minúsculas.
Experimente online!
fonte
return (
s?g(char*s){s=(s[1]&1|2**s&15)*4/5;}f(char*x,char*y){x=1952220<<g(x)>>g(y)&2048;}
boa solução!Python 2,
125 117 83 7877 bytesOnde
""
no final, na verdade, contém os caracteres"\x02\x04\x0c\x14\x16"
Experimente Online!
(+3 porque esqueci 11 ou 22 na lista, para começar)
-8 bytes de Jonathan Frech e alternando para Python 2 .
-34 bytes com sugestões de Jonathan Frech e usando
str
o índice em vez delist
.-4 bytes de inlining
i
e Neil invertendo a sugestão de string (apenas -2 realmente, como esqueci em()
torno de um gerador)-5 bytes de inline
i
e alterando o formato de entrada-1 bytes de Jonathan Frech com
map()
e não imprimíveis.Recebe entrada em uma linha de stdin no formato:
True
é dissonante,False
é consoante.Explicação antiga:
Python
str.index
retorna o menor índice inicial (positivo) de uma substring correspondente, so"ABACABA".index("A") == 0
e"ABACABA".index("BA") == 1
. Por esse motivo, podemos colocar os nomes das notas espaçados igualmente em uma sequência e, desde que (por exemplo)A
venha antesA#
, o compartilhamentoA
não será um problema.i
agora é uma função que retorna o índice em'C C#D D#E F F#G G#A A#B'
seu argumento (um nome de nota), que é 2 * (o número de semitons dessa notaC
)O Python 2
input()
é (na maior parte) equivalente aoeval(input())
Python3, portanto, com uma entrada válida do formato'C#','F'
(por exemplo)a='C#'
eb='F'
Se a distância entre a primeira nota e a segunda nota na sequência não for 2, 4, 12 ou 20 (como os nomes das notas estão representados em 2 caracteres), o intervalo é dissonante, imprima True, caso contrário, é consoante, imprimir Falso.
fonte
eval(input())
(13 bytes) em vez deinput().split()
(15 bytes).
) em vez de uma sequência vazia.C (gcc) , 115
117120bytesExperimente online!
Retorne 1/0 para consonat e dissonat. É sempre interessante fazer a manipulação de strings com C. puro.
f("A#", "C")
fonte
PowerShell , 107 bytes
Experimente online!
Saídas
True
para dissonante eFalse
consoante.Recebe entrada
$a
e$b
, as duas notas, como seqüências de caracteres. Executa uma-split
operação na balança, que se divide em espaço em branco, para criar uma matriz de notas e as armazena$x
. Localiza o.indexof
$b
nessa matriz, subtrai o índice de$a
e, em seguida, obtém oabs
valor olute. Verifica se esse número é-in
o intervalo dissonante.fonte
Python 2 , 68 bytes
Experimente online!
Saídas:
1
é dissonante,0
é consoante.fonte
SQL, 582 bytes
SQL Fiddle
Eu ainda tenho algum golfe para fazer, mas eu queria pegá-lo aqui antes que acabasse quebrando completamente.
Se a entrada estiver em um formato de letra, colocar essas letras em uma tabela com valores é aceitável, certo?
fonte
Perl 5 , 106 bytes
Experimente online!
Retorna false para dissonante, true para consoante.
fonte