Consonanza o dissonanza?


36

Dati due nomi di nota, devi scrivere un programma che determina se l'intervallo formato da queste due note è consonante o dissonante.

introduzione

Nella musica occidentale, ci sono solo 12 toni "diversi". I loro nomi, in ordine dal più basso al più alto, sono le seguenti: C, C#, D, D#, E, F, F#, G, G#, A, A#, B. La sequenza è ciclica, cioè continua con un'altra Cdopo l' Binfinito.

La distanza tra due toni è chiamata intervallo . L'intervallo tra due note qualsiasi che sono adiacenti nella serie sopra (es. C — C#O E — F) è chiamato semitono . L'intervallo tra le note più distanti è definito come il numero di passi di semitono necessari per passare dal primo al secondo (possibilmente avvolgendo la sequenza). Alcuni esempi: D to E= 2 semitoni, C to G= 7 semitoni, B to D#= 4 semitoni (questo avvolge la sequenza). 1

Ora, questi intervalli sono divisi in due categorie: consonante (che suona piacevolmente se suoni le due note contemporaneamente) e dissonante (non così tanto).

Definiamo gli intervalli di consonanti come: 0, 3, 4, 5, 7, 8 e 9 semitoni.

Il resto è dissonante, vale a dire: 1, 2, 6, 10 e 11 semitoni.

La sfida

Scrivi un "programma" (nel solito senso della parola: una funzione è perfettamente OK) per fare quanto segue:

  • Prendi due nomi di nota (stringhe della sequenza sopra) come input. Puoi prenderli come preferisci (da stdin, come argomenti, separati da qualsiasi cosa tu voglia, anche sentirti libero di prenderli come un elenco di caratteri (es ["C","#"].). Tuttavia, non puoi assegnare nessun altro nome alle note (specialmente tu non possono numerarli da 0 a 11 e usare i numeri).

  • Per i fanatici della musica, le note verranno specificate senza l'ottava. In questo caso, anche non importa in quale ordine arrivano le note e quale è più basso e quale è più alto. Infine, non è necessario gestire alcun nome non presente nell'elenco precedente. Nessun altro enharmonics piaceE# , nessun appartamento, doppie alterazioni e così via.

  • Scegli due valori diversi. Il tuo programma deve emetterne uno ogni volta che l'intervallo formato dalle due note nell'input è consonante e l'altro se non lo sono. (Potrebbe essere Truee False, ma anche π ed e se vuoi :))

  • Questo è un codice-golf. Vince il programma più breve in byte in ogni lingua. Divertiti!

Esempi e casi di test

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

Non ne aggiungo altri poiché non ci sono casi particolarmente insidiosi in questo.

Questa è una mia prima sfida, quindi ogni critica costruttiva è calorosamente benvenuta: -. Se trovi la spiegazione della teoria sciatta, sentiti libero di porre domande. Infine, per favore, non dirmi che questo è un aspetto negativo di questo o questo . Mi sono assicurato che non lo fosse. (Quest'ultima è abbastanza simile ma più complessa. Ho pensato che affrontare una sfida un po 'più semplice rendesse più facile la partecipazione delle persone.)


1 : ho cercato di semplificare al massimo questa spiegazione. C'è molta più teoria sugli intervalli. Per favore, non mi colpire per averlo lasciato fuori.

Risposte:


12

Gelatina , 21 byte

Prende l'input come un elenco di due stringhe. Restituisce 0per dissonante o 1per consonante.

OḢ6×%21_Lµ€IA“¬ɠṘ’æ»Ḃ

Provalo online!

OḢ6×%21_Lµ€IA“¬ɠṘ’æ»Ḃ   - main link
         µ€             - for each note             e.g. ["A#", "C"]
O                       -   convert to ASCII codes  -->  [[65, 35], 67]
 Ḣ                      -   keep the first element  -->  [65, 67]
  6×                    -   multiply by 6           -->  [390, 402]
    %21                 -   modulo 21               -->  [12, 3]
       _L               -   subtract the length     -->  [12, 3] - [2, 1] = [10, 2]
           IA           - absolute difference       -->  8
             “¬ɠṘ’      - the integer 540205
                  æ»    - right-shift               -->  540205 >> 8 = 2110
                    Ḃ   - isolate the LSB           -->  2110 & 1 = 0

Making-of

Dovremmo prima notare che la funzione F che stiamo cercando è commutativa: per ogni coppia di note (A, B) , abbiamo F (A, B) = F (B, A) .

Dato che non ci sono troppi input possibili e solo 2 possibili output da gestire, deve essere possibile trovare una funzione hash piuttosto semplice H , tale che | H (A) - H (B) | produce un intervallo limitato di valori ed è privo di collisioni per tutte le possibili coppie di note (A, B) rispetto all'output previsto.

Testeremo l'insieme delle funzioni H (mul, mod) , che sono definite come:

H(mul, mod)(s) = ((ORD(s[0]) * mul) MOD mod) - LEN(s)

Dov'è ORD(s[0])il codice ASCII del primo carattere della nota ed LEN(s)è la lunghezza della nota ( 2 se c'è un '#'e 1 in caso contrario).

Di seguito è riportata una versione commentata del codice JS che è stata utilizzata per trovare un paio di coppie valide (mul, mod) e le maschere bit risultanti. Esistono molte soluzioni possibili, ma * 6 % 21è la più breve con questo metodo.


3
Come ti vengono in mente queste cose? .. Stai ricevendo questo tipo di "algoritmi" a mano o con forza bruta? E indipendentemente dalla risposta della seconda domanda: come?! ..: S " intero letterale 540205; spostato a destra con (codice ASCII; moltiplicalo per 6; modulo 21; mantieni primo; sottrai lunghezza ...); bit a bit-AND 1 ". Le tue risposte continuano a impressionarmi ogni volta ..
Kevin Cruijssen,

@KevinCruijssen Ho aggiunto il codice JS originale che è stato utilizzato per trovare questi valori.
Arnauld,

Grazie per la spiegazione aggiunta. Sono ancora impressionato come il primo, ma hai dato una chiara spiegazione di come ti sei inventato. Peccato che posso votare una sola volta.
Kevin Cruijssen,

9

APL (Dyalog) , 62 39 byte

Usi ⎕IO←0; 0 è consonante, 1 è dissonante. Prende un elenco di caratteri della nota di base come argomento sinistro e un elenco di oggetti taglienti come argomento destro.

{⎕A[|-/('C D EF G A '⍳⍺)+⍵=⍕#]∊'BCGKL'}

Provalo online!

{... } funzione anonima dove è l'argomento sinistro ed è l'argomento giusto

⎕A[... ]∊'BCGKL' è la A lphabet, indicizzato dal seguente, un membro della stringa?

  ⍕# formattare lo spazio dei nomi di root (restituisce il carattere nitido)

  ⍵= i caratteri dell'argomento giusto (gli oggetti taglienti) sono uguali a quello?

  (...)+  aggiungi quanto segue:

   'C D EF G A '⍳⍺ indici dei caratteri dell'argomento sinistro nella stringa

  -/ differenza tra quelli

  | valore assoluto


Ti dispiacerebbe aggiungere una spiegazione per quelli di noi che non hanno familiarità con APL?
Draconis,

@Draconis Spiegazione aggiunta.
Adám,

9

MATL , 30 27 26 byte

,j'DJEFPGIALBC'&mQs]ZP7Mdm

Inserisce le due note in righe diverse. Uscite 0per consonante, 1per dissonante.

Provalo online! Oppure verifica tutti i casi di test .

Spiegazione

La stringa di 11 caratteri

DJEFPGIALBC

codifica sia le note che gli intervalli dissonanti, come segue.

Il programma trova prima gli indici in base 1 dei caratteri di input nella stringa sopra. Un input non nitido come Ddarà 1, Edarà 3, ..., Cdarà 11. Questi numeri possono anche essere considerati array numerici 1 × 1. Un input nitido come C#darà l'array 1 × 2 [11 0], il che significa che è Cstato trovato in posizione 11e #non è stato trovato.

Si noti che le lettere JPILnon saranno mai presenti nell'input. Per ora sono usati solo come segnaposto, quindi ad esempio la nota Eè due semitoni sopra D. Ma saranno anche utili per definire intervalli dissonanti.

I numeri nella prima voce dell'array 1 × 1 o 1 × 2 corrispondono al tono delle note in semitoni, senza contare i simboli acuti (ancora). Osservare che la scala definita da questi numeri non inizia da C; ma questo non importa perché vogliamo solo intervalli, cioè differenze tra le note. Sottraendo i numeri ottenuti si darebbe l'intervallo o 12 meno l'intervallo. Ma prima dobbiamo considerare il simbolo appuntito.

Per considerare le note acute, un modo da golf (in MATL) è quello di aggiungere 1ad ogni voce dell'array 1 × 1 o 1 × 2 ottenuto in precedenza e quindi sommare l'array (2 byte). Pertanto le note non acute vengono aumentate di 1e le note acute di 2. Ciò rende le note acute 1 semitono più alte delle note non acute, come richiesto. Stiamo anche aggiungendo un semitono in più a tutte le note, ma ciò non cambia gli intervalli tra loro. Quindi ora nota Ddarà il numero del passo 2, D#darà 3, ..., Cdarà 12, C#darà 13.

Intervalli dissonanti sono 1, 2, 6, 10, o 11. Questi hanno una simmetria modulo-12 : un intervallo tra due note è dissonante se e solo se l'intervallo con le note in ordine inverso, modulo 12, è dissonante.

Se calcoliamo le differenze consecutive della stringa 'DJEFPGIALBC'otteniamo il vettore numerico

6 -5 1 10 -9 2 -8 11 -10 1

che contiene precisamente gli intervalli dissonanti, oltre ad alcuni valori negativi, che non saranno né utili né dannosi. Si noti che è la scelta di lettere aggiuntive JPILnella stringa 'DJEFPGIALBC'che definisce (tramite differenze consecutive) gli intervalli dissonanti.

Per vedere se le due note di input sono dissonanti prendiamo la differenza assoluta dei loro numeri di tono. Ad esempio, Ce D#darà numeri 12e 3rispettivamente, e la differenza assoluta è 9. La differenza effettiva sarebbe -9e l'intervallo effettivo sarebbe 3(ottenuto come -9modulo 12). Ma grazie alla simmetria di cui sopra, possiamo considerare 9invece di 3. Poiché 9non è presente nel vettore delle differenze consecutive, le note sono consonanti.


2
Mi piace il modo in cui hai codificato sia le note che gli intervalli dissonanti nella stessa stringa.
Celtschk,

8

JavaScript (ES6), 68 64 byte

Prende le note come due stringhe nella sintassi del curry (a)(b). Restituisce 0per dissonante o 1per consonante.

a=>b=>488055>>(g=s=>'C D EF G A'.search(s[0])-!s[1])(a)-g(b)+9&1

Casi test

Formattato e commentato

a => b =>                       // given the two notes 'a' and 'b'
  488055 >>                     // 19-bit lookup bitmask: 1110111001001110111
    (g = s =>                   // we use g() to convert a note 's' into a semitone index
      'C D EF G A'.search(s[0]) // position of the note: -1 for 'B' (not found) to 9 for 'A'
      - !s[1]                   // subtract 1 semitone if the '#' is not there
    )(a)                        // compute the result for 'a'  --> [ -2 ...  9]
    - g(b)                      // subtract the result for 'b' --> [-11 ... 11]
    + 9                         // add 9                       --> [ -2 ... 20]
  & 1                           // test the bitmask at this position (0 if negative or > 18)

7

Gelatina , 26 byte

i@€ØAo.SḤ’d5ḅ4µ€ạ/“¢£©½¿‘ċ

Un collegamento monadico che prende un elenco delle due note (come elenchi di caratteri) e ritorna 0per consonante e 1dissonante.

Provalo online! oppure vedi tutti gli input nella suite di test .

Come?

i@€ØAo.SḤ’d5ḅ4µ€ạ/“¢£©½¿‘ċ - Link: list of lists of characters, notes
              µ€           - for €ach note in notes: (call the resulting list x)
   ØA                      -   yield the uppercase alphabet
i@€                        -   first index of c in ^ for €ach character, c
                           -     ...note '#' is not there so yields 0 (A->1, B->2,...)
      .                    -   literal one half
     o                     -   or (vectorised)  - e.g. "C#" -> [3, 0] -> [3, 0.5]
       S                   -   sum
        Ḥ                  -   double - that is ...  C C#  D D#  E  F F#  G G#  A A#  B
                                                 ->  6  7  8  9 10 12 13 14 15  2  3  4
         ’                 -   decrement         ->  5  6  7  8  9 11 12 13 14  1  2  3
           5               -   literal five
          d                -   divmod                (e.g. 9 -> [1,4] or 11 -> [2,1])
             4             -   literal four
            ḅ              -   convert from base     (e.g. [1,4] -> 8 or [2,1] -> 9)
                                                 ->  4  5  6  7  8  9 10 11 12  1  2  3
                 /         - reduce x with:
                ạ          -   absolute difference   (e.g. ["G#", "A"] -> [12, 1] -> 11)
                  “¢£©½¿‘  - code-page indices = [1, 2, 6, 10, 11]
                         ċ - count occurrences (1 if in the list, 0 if not)

5

Gelatina , 31 byte

O_65ị“¢[ḋṃ’b⁴¤+L$€Ḣ€ạ/e“cṾ’b12¤

Provalo online!

wheeeeee 32 byte troppo a lungo

Spiegazione

O_65ị“¢[ḋṃ’b⁴¤+L$€Ḣ€ạ/e“cṾ’b12¤  Main link
O                                Cast each character to an int using Python `ord`
 _65                             Subtract 65 (A is 0, G is 7)
     “¢[ḋṃ’b⁴¤                   [2, 3, 5, 7, 9, 10, 0]
     “¢[ḋṃ’                      37058720
           b                     Digits in base
            ⁴                    16
    ị                            Index into this list; this creates the gaps for sharps
                 €               For each sublist
              +L$                Add the length to each element (Sharpens sharp notes)
              +                  Add
               L                 Length
                   €             For each sublist
                  Ḣ              Take the first element
                    ạ/           Absolute difference between the two (unoctaved) pitches # It's convenient that every interval's inverse (?) has the same consonance/dissonance
                      e          Is the semitone difference in
                       “cṾ’b12¤  [1, 2, 6, 10, 11]?
                       “cṾ’      25178
                           b     base
                            12   12

Ehi, è un'ottima risposta! Mi chiedevo se qualcuno si avvale della simmetria, e tu l'hai fatto. E mi piace anche il tuo metodo per abbinare i nomi delle note ai numeri! +1.
Ramillies,

La differenza del semitono può essere simmetrica ma si ottengono comunque risultati difficili - ad esempio "G#", "A"(dissonante) si ottiene una differenza di 11cui non è presente[1,2,6] .
Jonathan Allan,

@JonathanAllan oh beh, questo è imbarazzante; Ho pensato che la differenza assoluta ha risolto che ... ._. risolverà lol
HyperNeutrino il

1
@JonathanAllan corretto per un paio di byte extra (3 IIRC)
HyperNeutrino,

4

Mathematica, 55 byte

function                                                  arguments        bytes

FreeQ[1|2|6|10|11]@Abs[#-#2&@@Sound`PitchToNumber/@#]&    [{"C","F#"}]     55

Mappare l'integrato interno Sound`PitchToNumbersull'input (elenco di due stringhe), prendere la differenza assoluta, quindi corrispondere al modello per i numeri di intervallo dissonanti.


Solo per divertimento (non competitivi)

Ecco alcune funzioni più brevi che violano la restrizione "non è possibile assegnare altri nomi alle note". Il pacchetto rudimentaleMusic` ha costanti di nota predefinite (come A4 = 440.) e la funzione HertzToCents(che può essere giocata a golf). Invece delle stringhe, useremo le costanti della nota come argomenti, ma fornite in un formato diverso per ogni funzione.

FreeQ[1|2|6|10|11]@Abs@@Round[.01HertzToCents@#]&         [{C3,Fsharp3}]   50+9=59
FreeQ[1|2|6|10|11]@Abs@Round[17Log[#2/#]]&                [C3,Fsharp3]     43+9=52
FreeQ[1|2|6|10|11]@Abs@Round[17Log@#]&                    [C3/Fsharp3]     39+9=48

L'importazione del pacchetto <<Music`;richiede 9 byte.

Questa funzione converte una stringa (come "F#") in una costante di nota (come Fsharp3):

Symbol[StringReplace[#,"#"->"sharp"]<>"3"]&                                44

Per accettare intervalli più grandi di un'ottava, sostituire Abs[…]con Mod[…,12].


Perché alcuni intervalli sono considerati dissonanti? Un intervallo è un rapporto di due frequenze. Se il rapporto ha un numeratore e un denominatore "semplici", tende ad essere più consonante. Nell'accordatura a 5 limiti , i rapporti possono essere fattorizzati in potenze intere di soli numeri primi inferiori o uguali a 5. Nessun intervallo in temperamento uguale, oltre all'ottava, è un intervallo giusto ; sono solo approssimazioni ravvicinate usando i poteri della 12a radice di 2.

Invece di codificare a fondo quali numeri di intervallo sono dissonanti, possiamo trovare un'approssimazione razionale dell'intervallo e quindi determinare se il suo numeratore e denominatore sono "semplici" (il che significa che il denominatore è inferiore a 5 e il rapporto non divide 7).

Questa tabella mostra ciascuno dei passaggi di quel processo.

Table[
  Module[{compoundInterval,simpleInterval,rationalApprox,denomLeq5,div7,consonant},
    compoundInterval = Power[2, i/12];
    simpleInterval   = 2^Mod[Log2[compoundInterval], 1];
    rationalApprox   = Rationalize[N@simpleInterval, 1/17];
    denomLeq5        = Denominator[rationalApprox]<=5;
    div7             = Denominator[rationalApprox]>1 && rationalApprox\[Divides]7;
    consonant        = FreeQ[1|2|6|10|11][Mod[i,12]];

    InputForm/@{
      i, simpleInterval, rationalApprox, 
      denomLeq5, div7, denomLeq5 && !div7,
      consonant
    }
  ], {i, 0, 12}
]

i   sInterval  ratio   denomLeq5  div7       den&&!div  | consonant?

0   1          1       True       False      True       | True
1   2^(1/12)   17/16   False      False      False      | False
2   2^(1/6)    9/8     False      False      False      | False
3   2^(1/4)    6/5     True       False      True       | True
4   2^(1/3)    5/4     True       False      True       | True
5   2^(5/12)   4/3     True       False      True       | True
6   Sqrt[2]    7/5     True       True       False      | False
7   2^(7/12)   3/2     True       False      True       | True
8   2^(2/3)    8/5     True       False      True       | True
9   2^(3/4)    5/3     True       False      True       | True
10  2^(5/6)    7/4     True       True       False      | False
11  2^(11/12)  11/6    False      False      False      | False
12  1          1       True       False      True       | True

L'approssimazione razionale si trova all'interno 1/17dell'intervallo perché quella è la soglia più grande che distingue tra tutti i 12 intervalli temperati uguali. Abbiniamo numeri razionali al modello Rational[a_,b_](o soloa_~_~b_ ), quindi abbiniamo solo i numeri interi_ .

Questo culmina nella seguente funzione piuttosto breve che determina se un rapporto di frequenza arbitrario (maggiore di 1) è consonante o dissonante.

Rationalize[#,1/17]/.{a_~_~b_:>b<=5&&!a∣7,_->True}&       [Fsharp3/C3]     51+9=60

1
Caspita, non dirmi che Mathematica ha un sistema integrato anche per questo ...: D
Ramillies,

3

Mathematica, 118 byte

FreeQ[{1,2,6,10,11},Min@Mod[Differences[Min@Position["C|C#|D|D#|E|F|F#|G|G#|A|A#|B"~StringSplit~"|",#]&/@{#,#2}],12]]&


Modulo di input

["ANNO DOMINI"]

Uscite

True->Consonant  
False->Dissonant   

grazie @JonathanFrech -16 byte


Solo un'osservazione: non è necessario generare stringhe Consonante Dissonant. È possibile generare due valori qualsiasi al posto di essi (0/1, ... comunque). Ciò potrebbe salvare alcuni byte.
Ramillies,

1
Non puoi omettere If[...,0,1]e definire True->Consonant; False->Dissonant?
Jonathan Frech,

1
StringCases["CC#DD#EFF#GG#AA#B",_~~"#"...]- 42 byte
celtschk

1
Inoltre, è possibile salvare 2 byte sostituendo {1,2,6,10,11}con1|2|6|10|11
celtschk il

1
@Skyler Vedi la risposta sotto.
hftf

3

Carbone , 30 byte

≔B#A#G#FE#D#C槔o∧⌈ς”⁻⌕ζ⮌θ⌕ζ⮌η

Provalo online! Il collegamento è alla versione dettagliata del codice. Uscite 1 per consonante, 0 per dissonante. Spiegazione:

≔B#A#G#FE#D#Cζ                  Store reversed note names in z
                        θ       First input
                       ⮌        Reversed
                     ⌕ζ         Find index in z
                            η   Second input
                           ⮌    Reversed
                         ⌕ζ     Find index in z
                     ⁻          Subtract
               ”o∧⌈ς”           Compressed string 100111011100
              §                 Circularly index
                                Implicitly print

per curiosità, c'è un motivo mnemonico per cui il glifo ⌕ζviene utilizzato per "trova indice"?
Giona,

@Jonah ζè la variabile assegnata a prima.
Neil,

2

J, 68 byte

[:e.&1 2 6 10 11[:(12| -~/)(<;._1',C,C#,D,D#,E,F,F#,G,G#,A,A#,B')i.]

spiegazione

Un'implementazione semplice, non super golf in J:

  • L'input viene dato come note dettagliate in scatola (prodotte usando il taglio), in ordine.

  • Trova i loro indici nell'intervallo di note: (<;._1',C,C#,D,D#,E,F,F#,G,G#,A,A#,B')i.]

  • Sottrai il primo dal secondo: -~/

  • Prendi il resto quando diviso per 12: 12|

  • Controlla se è una delle note dissonanti: e.&1 2 6 10 11

Provalo online!


2

/// , 90 88 byte

/^/"\///^\/\///C^D/##"E/DD"F/E#"G/FD"A/GD"B/AD"#,#/,"B#^B/#"A#/#"A^G#^G^F#/#"F^E^D#^D/#/

Provalo online! (tutti i casi di test contemporaneamente)

  • Inserisci l'input dopo il codice.
  • Separare i nomi delle note con ,B# in ciascun caso di test.
  • L'output è ,per consonante, ,#per dissonante.
  • Supporto per doppie alterazioni ( ##) o E#in alcuni casi particolari. Altrimenti l'output è ,per consonante, #,per dissonante (grazie alla simmetria modulo 12)
  • Può gestire più casi di test contemporaneamente (se separati ragionevolmente)
  • I caratteri minuscoli vengono stampati esattamente.

2

C (gcc) , 91 byte

g(char*s){return (s[1]&1|2**s&15)*4/5;}f(char*x,char*y){return (1952220<<g(x)>>g(y))&2048;}

chiamata: f("A#", "D")

Valore di ritorno:

  • Consonante: 2048
  • Dissonante: 0

Bonus: la funzione non fa distinzione tra maiuscole e minuscole.

Provalo online!


Non ci sono due spazi non necessari in entrambi i return (s?
Jonathan Frech,

Puoi provare g(char*s){s=(s[1]&1|2**s&15)*4/5;}f(char*x,char*y){x=1952220<<g(x)>>g(y)&2048;}e una bella soluzione!
Keyu Gan,

1

Python 2, 125 117 83 78 77 byte

a,b=map("C C#D D#E F F#G G#A A#B".index,input())
print chr(abs(a-b))in""

Dove ""alla fine contiene effettivamente i personaggi"\x02\x04\x0c\x14\x16"

Provalo online!

(+3 perché ho dimenticato 11 o 22 nell'elenco per cominciare)

-8 byte da Jonathan Frech e passaggio a Python 2.

-34 byte con suggerimenti di Jonathan Frech e utilizzo strdell'indice invece che di list.

-4 byte da inline ie Neil sta invertendo il suggerimento di stringa (solo -2 davvero, dato che mi sono dimenticato di ()un generatore)

-5 byte da disinserimento ie modifica del formato di input

-1 byte da Jonathan Frech con map()e non stampabili.

Accetta input in una riga di stdin nel formato:

'C','C#'

Trueè dissonante, Falseè consonante.

Vecchia spiegazione:

i='C C#D D#E F F#G G#A A#B'.index
a,b=input()
print abs(i(a)-i(b))in[2,4,12,20]

Python str.indexrestituisce l'indice iniziale più basso (positivo) di una sottostringa corrispondente, quindi "ABACABA".index("A") == 0e "ABACABA".index("BA") == 1. Per questo motivo, possiamo inserire i nomi delle note equidistanti in una stringa e finché (ad esempio) Aviene prima A#, la condivisione Anon sarà un problema.

i='C C#D D#E F F#G G#A A#B'.index

iè ora una funzione che restituisce l'indice nel 'C C#D D#E F F#G G#A A#B'suo argomento (un nome di nota) è, che è 2 * (il numero di semitoni da cui è nota la nota C)

a,b=input()

Python 2 input()è (principalmente) equivalente a eval(input())in Python3, quindi con un input valido del formato 'C#','F'(ad esempio), a='C#'eb='F'

print abs(i(a)-i(b))in[2,4,12,20]

If the disttance between the first note and the second note in the string is not 2, 4, 12, or 20 (since the note names are represented in 2 characters), then the interval is dissonant, print True, else it is consonant, print False.


Since the input format is not strict, you can use eval(input()) (13 bytes) instead of input().split() (15 bytes).
Jonathan Frech




1
You could use Unicode characters () instead of an emtpy string.
Jonathan Frech

1

C (gcc), 115 117 120 bytes

g(char*a){a=*a-65+!!a[1]*(7-*a/70-*a/67);}f(x,y)char*x,*y;{x="(pP$HL<lt<X"[g(x)]*32+"=ZukW-^h1F6"[g(x)]>>g(y)&1;}

Try it online!

Return 1/0 for consonat and dissonat. It is always interesting to do string manipulation with pure C. Take input as f("A#", "C")


0

PowerShell, 107 bytes

param($a,$b)[math]::abs(($x=-split'C C# D D# E F F# G G# A A# B').indexof($b)-$x.indexof($a))-in1,2,6,10,11

Try it online!

Outputs True for dissonant and False for consonant.

Takes input $a and $b, the two notes, as strings. Performs a -split operation on the scale, which splits on whitespace, to create an array of the notes, stores that into $x. Finds the .indexof $b in that array, subtracts the index of $a, and then takes the absolute value thereof. Checks whether that number is -in the dissonant ranges.



0

SQL, 582 bytes

SQL Fiddle

I still have some golfing to do on it, but I wanted to get it down here before I end up breaking it completely.

If the input is in a letter format, then putting those letters in a table with values is okay, right?

CREATE TABLE N(N char(2),v int)
Insert Into N values('A',1),('A#',2),('B',3),('C',4),('C#',5),('D',6),('D#',7),('E',8),('F',9),('F#',10),('G',11),('G#',12);
CREATE TABLE D(D char(9),v int) 
Insert Into D values('C',0),('D',1),('D',2),('C',3),('C',4),('C',5),('D',6);
CREATE FUNCTION I(@A char(2),@B char(2))
RETURNS char(9) as
BEGIN
DECLARE @E int=(SELECT v from N where n=@A),@F int=(SELECT v from N where n=@B)
DECLARE @C char(9) = (SELECT case D when 'D' then 'Dissonant' when 'C' then 'Consonant' END from D where v in(abs(@e-@f),12-abs(@e-@f)))
RETURN isnull(@C,'NotANote')
END

0

Perl 5, 106 bytes

("C,C#,D,D#,E,F,F#,G,G#,A,A#,B,"x2)=~/$F[0],(.*?)$F[1],/;$r=(1+($1=~y/,//))%12;say(grep/$r/,(0,3..5,7..9))

Try it online!

Returns false for dissonant, true for consonant.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.