Konsonans czy dysonans?

36

Biorąc pod uwagę dwie nazwy nut, masz napisać program, który określa, czy interwał utworzony przez te dwie nuty jest spółgłoskowy czy dysonansowy.

Wprowadzenie

W muzyce zachodniej jest tylko 12 „różnych” dźwięków. Ich nazwiska, sortowane od najniższego do najwyższego, są następujące: C, C#, D, D#, E, F, F#, G, G#, A, A#, B. Sekwencja jest cykliczna, tzn. Kontynuowana jest następna Cpo Bnieskończoności.

Odległość między dwoma tonami nazywana jest interwałem . Odstęp między dowolnymi dwiema nutami sąsiadującymi z powyższą serią (np. C — C#Lub E — F) nazywa się półtonem . Przerwa między bardziej odległymi nutami jest zdefiniowana jako liczba kroków półtonowych potrzebnych do przejścia od pierwszego do drugiego (przy możliwym owinięciu wokół sekwencji). Kilka przykładów: D to E= 2 półtonów, C to G= 7 półtonów, B to D#= 4 półtonów (dotyczy to sekwencji). 1

Teraz te interwały są podzielone na dwie kategorie: spółgłoska (brzmi przyjemnie, jeśli grasz dwie nuty jednocześnie) i dysonans (nie tak bardzo).

Zdefiniujmy przedziały spółgłosek: 0, 3, 4, 5, 7, 8 i 9 półtonów.

Reszta jest dysonansowa, a mianowicie: 1, 2, 6, 10 i 11 półtonów.

Wyzwanie

Napisz „program” (w szerokim znaczeniu tego słowa: funkcja jest całkowicie OK), aby wykonać następujące czynności:

  • Weź jako nazwę dwie nazwy nut (ciągi z powyższej sekwencji). Możesz wziąć je w dowolny sposób (od standardowego, jako argumenty, oddzielone czymkolwiek chcesz, możesz nawet wziąć je jako listę znaków (np ["C","#"].). Jednak nie możesz przypisywać żadnych innych nazw notatkom (szczególnie ty nie może ich numerować od 0 do 11 i używać liczb).

  • Dla waszych maniaków muzycznych nuty zostaną określone bez oktawy. W tym przypadku nie ma również znaczenia, w jakiej kolejności przychodzą nuty, a która jest niższa, a która wyższa. Wreszcie, nie musisz obsługiwać żadnych nazw, których nie ma na powyższej liście. Żadnych innych ulepszeń, takich jak E#mieszkania, podwójnych przeróbek i tak dalej.

  • Wybierz dowolne dwie różne wartości. Twój program musi wypisać jeden z nich, ilekroć interwał utworzony przez dwie nuty na wejściu jest spójny, a drugi, jeśli tak nie jest. (Może być Truei False, ale nawet gatunku i e jeśli chcesz :))

  • To jest golf golfowy. Wygrywa najkrótszy program w bajtach w każdym języku. Baw się dobrze!

Przykłady i przypadki testowe

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

Nie dodam ich więcej, ponieważ nie ma w tym szczególnie zdradliwych przypadków.

To moje pierwsze wyzwanie, więc wszelka konstruktywna krytyka jest mile widziana :—). Jeśli uważasz, że wyjaśnienie teorii jest niechlujne, możesz zadawać pytania. Na koniec, proszę nie mów mi, że jest to dupe od tego czy tego . Upewniłem się, że tak nie jest. (Ta ostatnia jest dość podobna, ale bardziej złożona. Myślałem, że postawienie nieco prostszego wyzwania ułatwi ludziom przyłączenie się.)


1 : Starałem się maksymalnie uprościć to wyjaśnienie. Istnieje wiele teorii dotyczących interwałów. Proszę nie bić mnie za to, że to pominęłem.

Ramillies
źródło

Odpowiedzi:

12

Galaretka , 21 bajtów

Pobiera dane wejściowe jako listę dwóch ciągów. Zwraca 0za dysonans lub 1spółgłoskę.

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

Wypróbuj 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

Najpierw powinniśmy zauważyć, że funkcja F , której szukamy, jest przemienna: dla każdej pary nut (A, B) mamy F (A, B) = F (B, A) .

Ponieważ nie ma zbyt wielu możliwych danych wejściowych i tylko 2 możliwe dane wyjściowe, z którymi trzeba sobie poradzić, musi być możliwe znalezienie raczej prostej funkcji skrótu H , takiej że | H (A) - H (B) | generuje ograniczony zakres wartości i jest bezkolizyjny dla wszystkich możliwych par nut (A, B) w odniesieniu do oczekiwanego wyniku.

Zamierzamy przetestować zestaw funkcji H (mul, mod) , które są zdefiniowane jako:

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

Gdzie ORD(s[0])jest kod ASCII pierwszego znaku nuty i LEN(s)jest długością nuty ( 2, jeśli jest '#'a 1, jeśli nie).

Poniżej znajduje się skomentowana wersja kodu JS, który został użyty do znalezienia kilku prawidłowych par (mul, mod) i powstałych masek bitowych. Istnieje wiele możliwych rozwiązań, ale * 6 % 21ta metoda jest najkrótsza.

Arnauld
źródło
3
Jak w ogóle wymyślisz te rzeczy? Czy dostajesz tego rodzaju „algorytmy” ręcznie czy brutalnie? I niezależnie od odpowiedzi na drugie pytanie: jak?! ..: S " dosłowna liczba całkowita 540205; przesunięta w prawo za pomocą (kod ASCII; pomnóż przez 6; modulo 21; zachowaj pierwszy; odejmij długość ...); bitowo-AND 1 „. Twoje odpowiedzi
robią na
@KevinCruijssen Dodałem oryginalny kod JS, który został użyty do znalezienia tych wartości.
Arnauld,
Dzięki za dodatkowe wyjaśnienia. Wciąż jestem pod wrażeniem pierwszego, ale jasno wyjaśniłeś, jak to wymyśliłeś. Szkoda, że ​​mogę głosować tylko raz.
Kevin Cruijssen,
9

APL (Dyalog) , 62 39 bajtów

Zastosowania ⎕IO←0; 0 oznacza spółgłoskę, 1 jest dysonansem. Pobiera listę znaków nuty podstawowej jako lewy argument, a listę ostrych znaków jako prawy argument.

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

Wypróbuj online!

{} Anonimowa funkcja gdzie lewy argument i prawy argument

⎕A[... ]∊'BCGKL' jest lphabet, indeksowane przez następujących, członek ciąg?

  ⍕# sformatuj główną przestrzeń nazw (daje ostry znak)

  ⍵= czy odpowiednie znaki argumentów (śruty) są równe?

  ()+ Dodaj:

   'C D EF G A '⍳⍺ indeksy znaków lewego argumentu w ciągu

  -/ różnica między nimi

  | całkowita wartość

Uriel
źródło
Czy mógłbyś dodać wyjaśnienie dla tych z nas, którzy nie znają APL?
Draconis,
@Draconis Dodano wyjaśnienie.
Adám
9

MATL , 30 27 26 bajtów

,j'DJEFPGIALBC'&mQs]ZP7Mdm

Wprowadza dwie nuty w różnych wierszach. Wyjścia 0dla spółgłoski, 1dla dysonansu.

Wypróbuj online! Lub sprawdź wszystkie przypadki testowe .

Wyjaśnienie

Ciąg 11 znaków

DJEFPGIALBC

koduje zarówno nuty, jak i dysonansowe interwały w następujący sposób.

Program najpierw znajduje indeksy 1 znaków wejściowych w powyższym ciągu. Nieostre dane wejściowe Ddadzą 1, Edadzą 3, ... Cdadzą 11. Liczby te można również uznać za tablice numeryczne 1 × 1. Takie ostre wejście C#da tablicę 1 × 2 [11 0], co oznacza, że Cznaleziono ją w pozycji 11i #nie znaleziono.

Zauważ, że litery JPILnigdy nie będą obecne na wejściu. Na razie są one używane tylko jako symbole zastępcze, tak że na przykład uwaga Eto dwa półtony powyżej D. Przydadzą się jednak również do zdefiniowania dysonansowych interwałów.

Liczby w pierwszym wpisie tablicy 1 × 1 lub 1 × 2 odpowiadają skokowi nut w półtonach, nie licząc ostrych symboli (jeszcze). Zauważ, że skala zdefiniowana przez te liczby nie zaczyna się od C; ale to nie ma znaczenia, ponieważ chcemy tylko interwałów, czyli różnic między nutami. Odjęcie uzyskanych liczb dałoby albo interwał, albo 12 minus interwał. Ale najpierw musimy wziąć pod uwagę ostry symbol.

Aby rozważyć ostre nuty, golfowym sposobem (w MATL) jest dodanie 1do każdego wpisu uzyskanej wcześniej tablicy 1 × 1 lub 1 × 2, a następnie zsumowanie tablicy (2 bajty). Tak więc nuty nieostre są zwiększane o, 1a nuty ostre o 2. To sprawia, że ​​ostre nuty 1 półton są wyższe niż nuty nieostre, zgodnie z wymaganiami. Dodajemy również dodatkowy półton do wszystkich nut, ale to nie zmienia odstępów między nimi. Więc teraz nuta Dpoda numer tonu 2, D#da 3, ... Cda 12, C#da 13.

Dissonant interwały 1, 2, 6, 10, lub 11. Mają one symetrię modulo-12 : przerwa między dwiema nutami jest dysonansowa wtedy i tylko wtedy, gdy interwał z nutami w odwrotnej kolejności, modulo 12, jest dysonansowy.

Jeśli obliczymy kolejne różnice łańcucha 'DJEFPGIALBC', otrzymamy wektor numeryczny

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

który zawiera dokładnie przedziały dysonansowe, oprócz niektórych wartości ujemnych, które nie będą ani użyteczne, ani szkodliwe. Zauważ, że wybór dodatkowych liter JPILw ciągu 'DJEFPGIALBC'określa (poprzez kolejne różnice) interwały dysonansowe.

Aby sprawdzić, czy dwie nuty wejściowe są dysonansowe, bierzemy bezwzględną różnicę ich liczb wysokości. Na przykład Ci D#poda odpowiednio liczby 12i 3, a absolutna różnica wynosi 9. Rzeczywista różnica byłaby -9, a rzeczywisty przedział byłby 3(uzyskany jako -9modulo 12). Ale dzięki symetrii, o której mowa powyżej, możemy rozważyć 9zamiast 3. Ponieważ 9nuty nie występują w wektorze kolejnych różnic, nuty są spójne.

Luis Mendo
źródło
2
Podoba mi się sposób, w jaki kodowałeś zarówno nuty, jak i dysonansowe interwały w tym samym ciągu.
celtschk
8

JavaScript (ES6), 68 64 bajtów

Zapisuje nuty jako dwa ciągi w składni curry (a)(b). Zwraca 0za dysonans lub 1spółgłoskę.

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

Przypadki testowe

Sformatowane i skomentowane

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)
Arnauld
źródło
7

Galaretka , 26 bajtów

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

Monadyczny link pobierający listę dwóch notatek (jako listy znaków) i powracający 0 spółgłoskę i 1dysonans.

Wypróbuj online! lub zobacz wszystkie dane wejściowe w pakiecie testowym .

W jaki sposób?

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)
Jonathan Allan
źródło
5

Galaretka , 31 bajtów

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

Wypróbuj online!

wheeeeee 32 bajty za długie

Wyjaśnienie

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
HyperNeutrino
źródło
Hej, to świetna odpowiedź! Zastanawiałem się, czy ktoś korzysta z symetrii, a ty to zrobiłeś. Podoba mi się również twoja metoda dopasowywania nazw nut do liczb! +1.
Ramillies,
Różnica półtonowa może być symetryczna, ale nadal uzyskujesz słabe wyniki - na przykład "G#", "A"(dysonans) daje różnicę, 11której nie ma[1,2,6] .
Jonathan Allan
@JonathanAllan, no cóż, to żenujące; Myślałem, że ta absolutna różnica naprawiła to ... naprawi lol
HyperNeutrino
1
@JonathanAllan naprawiono dla kilku dodatkowych bajtów (3 IIRC)
HyperNeutrino
4

Mathematica, 55 bajtów

function                                                  arguments        bytes

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

Odwzoruj wewnętrzne wbudowane Sound`PitchToNumberwejście (lista dwóch ciągów), weź absolutną różnicę, a następnie dopasuj wzór dla dysonansowych liczb interwałów.


Dla zabawy (niekonkurencyjny)

Oto kilka krótszych funkcji, które naruszają ograniczenie „nie możesz przypisywać żadnych innych nazw nutom”. Podstawowy Music`pakiet ma predefiniowane stałe nut (jak A4 = 440.) i funkcję HertzToCents(którą można grać w golfa). Zamiast łańcuchów użyjemy stałych notatek jako argumentów, ale podanych w innym formacie dla każdej funkcji.

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

Import pakietu <<Music`;zajmuje 9 bajtów.

Ta funkcja przekształca ciąg znaków (jak "F#") w stałą nutową (jak Fsharp3):

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

Aby zaakceptować odstępach większych niż oktawę, wymienić Abs[…]z Mod[…,12].


Dlaczego niektóre interwały są uważane za dysonansowe? Interwał to stosunek dwóch częstotliwości. Jeśli stosunek ma „prosty” licznik i mianownik, jest on bardziej spójny. W 5-limitowym strojeniu stosunki można rozdzielić na liczby całkowite tylko liczb pierwszych mniejszych lub równych 5. Żaden przedział w równym temperamencie, oprócz oktawy, nie jest tylko przedziałem ; są one jedynie bliskimi przybliżeniami przy użyciu mocy 12. pierwiastka z 2.

Zamiast twardego kodowania, które liczby przedziałów są dysonansowe, możemy znaleźć racjonalne przybliżenie przedziału, a następnie ustalić, czy jego licznik i mianownik są „proste” (co oznacza, że ​​mianownik jest mniejszy niż 5, a stosunek nie dzieli 7).

Ta tabela pokazuje każdy z etapów tego procesu.

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

Racjonalne przybliżenie leży w 1/17przedziale, ponieważ jest to największy próg, który rozróżnia wszystkie 12 równych temperowanych interwałów. Najpierw dopasowujemy liczby wymierne do wzorca Rational[a_,b_](lub tylko a_~_~b_), a następnie dopasowujemy tylko liczby całkowite _.

Kulminuje to następująca raczej krótka funkcja, która określa, czy arbitralny stosunek częstotliwości (większy niż 1) jest spółgłoskowy czy dysonansowy.

Rationalize[#,1/17]/.{a_~_~b_:>b<=5&&!a∣7,_->True}&       [Fsharp3/C3]     51+9=60
hftf
źródło
1
Kurcze, nie mów mi, że Mathematica ma wbudowane nawet do tego ...: D
Ramillies
3

Mathematica, 118 bajtów

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]]&


Formularz wejściowy

["OGŁOSZENIE"]

Wyjścia

True->Consonant  
False->Dissonant   

dzięki @JonathanFrech -16 bajtów

J42161217
źródło
Tylko uwaga: nie musisz generować ciągów Consonanti Dissonant. Zamiast nich możesz wypisać dowolne dwie wartości (0/1, ... cokolwiek). To może zaoszczędzić trochę bajtów.
Ramillies,
1
Nie możesz pominąć If[...,0,1]i zdefiniować True->Consonant; False->Dissonant?
Jonathan Frech,
1
StringCases["CC#DD#EFF#GG#AA#B",_~~"#"...]- 42 bajtów
celtschk
1
Można również zapisać 2 bajty, zastępując {1,2,6,10,11}je1|2|6|10|11
celtschk
1
@ Skyler Zobacz odpowiedź poniżej.
hftf 10.10.17
3

Węgiel drzewny , 30 bajtów

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

Wypróbuj online! Link jest do pełnej wersji kodu. Wyjścia 1 dla spółgłoski, 0 dla dysonansu. Wyjaśnienie:

≔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
Neil
źródło
z ciekawości, czy istnieje mnemoniczny powód, dla którego glif ⌕ζjest używany do „znajdowania indeksu”?
Jonasz
@Jonah ζjest zmienną przypisaną wcześniej.
Neil
2

J, 68 bajtów

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

wyjaśnienie

Prosta, niezbyt golfowa implementacja w J:

  • Dane wejściowe są podawane w postaci notatek w pudełkach (wytworzonych przy użyciu cięcia), w kolejności.

  • Znajdź ich indeksy w zakresie notatek: (<;._1',C,C#,D,D#,E,F,F#,G,G#,A,A#,B')i.]

  • Odejmij pierwszy od drugiego: -~/

  • Resztę podziel po podzieleniu przez 12: 12|

  • Sprawdź, czy jest to jedna z dysonansowych notatek: e.&1 2 6 10 11

Wypróbuj online!

Jonasz
źródło
2

/// , 90 88 bajtów

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

Wypróbuj online! (wszystkie przypadki testowe jednocześnie)

  • Umieść dane wejściowe po kodzie.
  • Oddziel nazwy notatek za pomocą ,B# w każdym przypadku testowym.
  • Dane wyjściowe są ,dla spółgłoski,,# dla dysonansu.
  • Obsługa podwójnych zmian ( ##) lub E#w niektórych szczególnych przypadkach. W przeciwnym razie dane wyjściowe są ,dla spółgłoski,#, dla dysonansu (dzięki symetrii modulo 12)
  • Może obsłużyć wiele przypadków testowych jednocześnie (jeśli są odpowiednio rozdzielone)
  • Małe litery są drukowane dokładnie.
użytkownik202729
źródło
2

C (gcc) , 91 bajtów

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

połączenie: f("A#", "D")

Zwracana wartość:

  • Consonant: 2048
  • Dissonant: 0

Bonus: funkcja nie rozróżnia wielkości liter.

Wypróbuj online!

celtschk
źródło
Czy w obu return (s nie ma dwóch niepotrzebnych miejsc ?
Jonathan Frech,
Możesz spróbować g(char*s){s=(s[1]&1|2**s&15)*4/5;}f(char*x,char*y){x=1952220<<g(x)>>g(y)&2048;}i fajne rozwiązanie!
Keyu Gan,
1

Python 2, 125 117 83 78 77 bajtów

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

Gdzie ""na końcu faktycznie znajdują się postacie"\x02\x04\x0c\x14\x16"

Wypróbuj online!

(+3, ponieważ na początku zapomniałem 11 lub 22)

-8 bajtów od Jonathana Frecha i przejście na Python 2 .

-34 bajty z sugestiami Jonathana Frecha i użyciem strindeksu zamiast list.

-4 bajty z inliningu ii Neil odwraca sugestię ciągu znaków (tylko -2 tak naprawdę, jak zapomniałem() o generatorze)

-5 bajtów od cofania ii zmiany formatu wejściowego

-1 bajty od Jonathana Frecha zi bez map()nadruku.

Pobiera dane wejściowe w jednym wierszu standardowego formatu:

'C','C#'

Truejest dysonansowy, Falsejest spółgłoskowy.

Stare objaśnienie:

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.indexzwraca najniższy (dodatni) indeks początkowy pasującego podciągu, "ABACABA".index("A") == 0a więc i "ABACABA".index("BA") == 1. Z tego powodu możemy umieścić nazwy nut równomiernie rozmieszczone w łańcuchu i dopóki (na przykład) Apojawi się wcześniej A#, udostępnianie Anie będzie stanowiło problemu.

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

ijest teraz funkcją, która zwraca indeks w 'C C#D D#E F F#G G#A A#B'argumencie (nazwa nuty), który wynosi 2 * (liczba półtonów, od której nuta jest wyższa C)

a,b=input()

Python 2 input()jest (przeważnie) równoważny z eval(input())Python3, więc z poprawnym wejściem formatu 'C#','F'(na przykład) a='C#'ib='F'

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

Jeśli odległość między pierwszą nutą a drugą nutą w ciągu nie jest równa 2, 4, 12 lub 20 (ponieważ nazwy nut są reprezentowane przez 2 znaki), wówczas interwał jest dysonansowy, drukuj True, w przeciwnym razie jest zgodny, wydrukuj False.

pizzapanty184
źródło
Ponieważ format wejściowy nie jest ścisły, można użyć eval(input())(13 bajtów) zamiast input().split()(15 bajtów).
Jonathan Frech,
101 bajtów
Jonathan Frech
98 bajtów
Jonathan Frech
79 bajtów
Jonathan Frech,
1
Możesz użyć znaków Unicode ( ) zamiast ciągu pustego.
Jonathan Frech,
1

C (gcc) , 115117 120 bajty

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;}

Wypróbuj online!

Zwraca 1/0 dla spółgłosek i dyssonatów. Zawsze interesujące jest wykonywanie operacji na łańcuchach za pomocą czystego C. Weź dane jakof("A#", "C")

Keyu Gan
źródło
0

PowerShell , 107 bajtów

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

Wypróbuj online!

Wyjścia Truedla dyssonantu i Falsedla spółgłoski.

Pobiera dane wejściowe $ai $bdwie notatki jako ciągi znaków. Wykonuje -splitoperację na skali, która dzieli się na białe znaki, aby utworzyć tablicę notatek, przechowuje ją w $x. Znajduje .indexof $bw tej tablicy, odejmuje indeks $a, a następnie przyjmuje absjego wartość olute. Sprawdza, czy ta liczba jest -indysonansowymi zakresami.

AdmBorkBork
źródło
0

Python 2 , 68 bajtów

lambda a,b,f='C C#D D#E F F#G G#A A#B'.find:3142>>(f(a)-f(b))/2%12&1

Wypróbuj online!

Wyjścia: 1dysonans, 0spółgłoska.

Lynn
źródło
0

SQL, 582 bajty

SQL Fiddle

Nadal mam trochę do zrobienia w golfa, ale chciałem go tu zabrać, zanim całkowicie go zniszczę.

Jeśli dane wejściowe są w formacie literowym, to umieszczenie tych liter w tabeli z wartościami jest w porządku, prawda?

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
froureo
źródło
0

Perl 5 , 106 bajtów

("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))

Wypróbuj online!

Zwraca false dla dysonansu, true dla spółgłoski.

Xcali
źródło