Kesesuaian atau disonansi?

36

Diberikan dua nama catatan, Anda harus menulis sebuah program yang menentukan apakah interval yang dibentuk oleh kedua catatan ini adalah konsonan atau disonan.

pengantar

Dalam musik Barat, hanya ada 12 nada "berbeda". Nama-nama mereka, diurutkan dari terendah ke tertinggi, adalah: C, C#, D, D#, E, F, F#, G, G#, A, A#, B. Urutannya adalah siklis, yaitu ia melanjutkan dengan yang lain Csetelah B, tanpa batas.

Jarak antara dua nada disebut interval . Interval antara dua not yang berdekatan dalam seri di atas (misalnya C — C#atau E — F) disebut semitone . Interval antara not-not yang lebih jauh didefinisikan sebagai jumlah langkah semiton yang diperlukan untuk mendapatkan dari yang pertama ke yang kedua (sementara mungkin membungkus urutannya). Beberapa contoh: D to E= 2 semitones, C to G= 7 semitones, B to D#= 4 semitones (ini membungkus urutan). 1

Sekarang, interval ini dibagi menjadi dua kategori: konsonan (terdengar menyenangkan jika Anda memainkan dua not sekaligus) dan disonan (tidak terlalu banyak).

Mari kita tentukan interval konsonan menjadi: 0, 3, 4, 5, 7, 8 dan 9 semiton.

Sisanya adalah disonan, yaitu: 1, 2, 6, 10 dan 11 semiton.

Tantangan

Tulis "program" (dalam arti kata yang umum: fungsi tidak masalah) untuk melakukan hal berikut:

  • Ambil dua nama note (string dari urutan di atas) sebagai input. Anda dapat mengambilnya sesuka Anda (dari stdin, sebagai argumen, dipisahkan oleh apa pun yang Anda inginkan, bahkan merasa bebas untuk menjadikannya sebagai daftar karakter (mis ["C","#"].). Namun, Anda tidak dapat menetapkan nama lain pada catatan (terutama Anda mungkin tidak memberi nomor dari 0 hingga 11 dan menggunakan angka).

  • Untuk Anda yang suka musik di luar sana, not akan ditentukan tanpa oktaf. Dalam hal ini, tidak masalah urutan not datang dan mana yang lebih rendah dan mana yang lebih tinggi. Akhirnya, Anda tidak perlu menangani nama apa pun yang tidak ada dalam daftar di atas. Tidak ada enharmonics lain seperti E#, tidak ada flat, perubahan ganda dan sebagainya.

  • Pilih dua nilai yang berbeda. Program Anda harus menampilkan salah satu dari mereka setiap kali interval yang dibentuk oleh dua catatan dalam input adalah konsonan, dan yang lainnya jika tidak. (Bisa jadi Truedan False, tetapi bahkan π dan e jika Anda mau :))

  • Ini adalah kode-golf. Program terpendek dalam byte di setiap bahasa menang. Selamat bersenang-senang!

Contoh dan Kasus Uji

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

Saya tidak menambahkan lebih dari mereka karena tidak ada kasus yang sangat berbahaya dalam hal ini.

Ini adalah tantangan pertamaku, jadi setiap kritik konstruktif disambut dengan hangat :—). Jika Anda menemukan penjelasan teori ceroboh, jangan ragu untuk bertanya. Akhirnya, tolong jangan katakan padaku bahwa ini adalah penipuan dari ini atau ini . Saya memastikan tidak. (Yang terakhir ini sangat mirip tetapi lebih kompleks. Saya pikir memasang tantangan yang lebih sederhana akan membuat orang lebih mudah untuk bergabung.)


1 : Saya mencoba menyederhanakan penjelasan ini sejauh yang saya bisa. Ada lebih banyak teori di sekitar interval. Tolong jangan bash saya untuk meninggalkannya.

Ramillies
sumber

Jawaban:

12

Jelly , 21 byte

Mengambil input sebagai daftar dua string. Pengembalian 0untuk disonan atau 1konsonan.

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

Cobalah 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

Pembuatan

Pertama-tama kita harus mencatat bahwa fungsi F yang kita cari adalah komutatif: untuk setiap pasangan catatan (A, B) , kita memiliki F (A, B) = F (B, A) .

Karena tidak ada terlalu banyak input yang mungkin dan hanya 2 output yang mungkin untuk ditangani, harus dimungkinkan untuk menemukan fungsi hash yang agak sederhana H , sedemikian rupa sehingga | H (A) - H (B) | menghasilkan kisaran nilai terbatas dan bebas tabrakan untuk semua pasangan catatan yang mungkin (A, B) sehubungan dengan output yang diharapkan.

Kita akan menguji serangkaian fungsi H (mul, mod) , yang didefinisikan sebagai:

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

Di mana ORD(s[0])kode ASCII dari karakter pertama note dan LEN(s)adalah panjang note ( 2 jika ada a '#'dan 1 jika tidak).

Di bawah ini adalah versi komentar dari kode JS yang digunakan untuk menemukan beberapa pasangan yang valid (mul, mod) dan bitmask yang dihasilkan. Ada banyak solusi yang mungkin, tetapi * 6 % 21yang paling pendek dengan metode ini.

Arnauld
sumber
3
Bagaimana Anda menemukan hal-hal ini? Apakah Anda mendapatkan 'algoritma' semacam ini dengan tangan atau dengan kekerasan? Dan terlepas dari jawaban pertanyaan kedua: bagaimana?! ..: S " literer integer 540205; bergeser ke kanan dengan (kode ASCII; kalikan dengan 6; modulo 21; pertahankan dulu; kurangi panjang ...); bitwise-AND 1 ". Jawaban Anda selalu membuat saya terkesan setiap saat ..
Kevin Cruijssen
@KevinCruijssen Saya telah menambahkan kode JS asli yang digunakan untuk menemukan nilai-nilai ini.
Arnauld
Terima kasih atas penjelasan yang ditambahkan. Saya masih terkesan seperti yang pertama, tetapi Anda memberikan penjelasan yang jelas tentang bagaimana Anda sampai pada itu. Sayang sekali, saya hanya bisa memilih satu kali.
Kevin Cruijssen
9

APL (Dyalog) , 62 39 byte

Penggunaan ⎕IO←0; 0 konsonan, 1 disonan. Mengambil daftar karakter catatan dasar sebagai argumen kiri dan daftar benda tajam sebagai argumen kanan.

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

Cobalah online!

{... } fungsi anonim di mana argumen kiri dan argumen kanan

⎕A[... ]∊'BCGKL' adalah A lphabet, diindeks oleh berikut, anggota dari string?

  ⍕# memformat namespace root (menghasilkan karakter tajam)

  ⍵= apakah argumen argumen yang tepat (benda tajam) sama dengan itu?

  (... )+ tambahkan yang berikut:

   'C D EF G A '⍳⍺ indeks argumen kiri karakter dalam string

  -/ perbedaan antara mereka

  | nilai mutlak

Uriel
sumber
Maukah Anda menambahkan penjelasan bagi kita yang tidak terbiasa dengan APL?
Draconis
@Draconis Explanation menambahkan.
Adám
9

MATL , 30 27 26 byte

,j'DJEFPGIALBC'&mQs]ZP7Mdm

Input kedua catatan dalam baris yang berbeda. Output 0untuk konsonan, 1untuk disonan.

Cobalah online! Atau verifikasi semua kasus uji .

Penjelasan

String 11 karakter

DJEFPGIALBC

mengkodekan catatan dan interval disonan, sebagai berikut.

Program pertama menemukan indeks berbasis 1 dari karakter input dalam string di atas. Masukan yang tidak tajam seperti Dakan memberi 1, Eakan memberi 3, ..., Cakan memberi 11. Angka-angka ini juga dapat dianggap 1 × 1 array numerik. Input tajam seperti C#akan memberikan array 1 × 2 [11 0], yang berarti Cditemukan pada posisi 11dan #tidak ditemukan.

Perhatikan bahwa surat-surat JPILtidak akan pernah ada dalam input. Untuk saat ini mereka hanya digunakan sebagai penampung, jadi misalnya note Eadalah dua semitone di atas D. Tetapi mereka juga akan berguna untuk mendefinisikan interval disonan.

Angka-angka dalam entri pertama dari array 1 × 1 atau 1 × 2 sesuai dengan nada nada di semitones, belum termasuk simbol yang tajam (belum). Perhatikan bahwa skala yang ditentukan oleh angka-angka ini tidak dimulai pada C; tapi itu tidak masalah karena kita hanya menginginkan interval, yaitu perbedaan antar catatan. Mengurangi angka yang diperoleh akan memberikan interval atau 12 dikurangi interval. Tapi pertama-tama kita perlu mempertimbangkan simbol yang tajam.

Untuk mempertimbangkan not yang tajam, cara golf (dalam MATL) adalah menambahkan 1setiap entri dari array 1 × 1 atau 1 × 2 yang diperoleh sebelumnya dan kemudian jumlah array (2 byte). Dengan demikian nada non-tajam meningkat 1dan nada tajam meningkat 2. Ini membuat nada tajam 1 semitone lebih tinggi dari nada tidak tajam, seperti yang disyaratkan. Kami juga menambahkan nada semi tambahan untuk semua catatan, tetapi itu tidak mengubah interval di antara mereka. Jadi sekarang note Dakan memberikan nomor nada 2, D#akan memberi 3, ..., Cakan memberi 12, C#akan memberi 13.

Interval disonan adalah 1, 2, 6, 10, atau 11. Ini memiliki simetri modulo-12 : interval antara dua not adalah disonan jika dan hanya jika interval dengan not dalam urutan terbalik, modulo 12, adalah disonan.

Jika kita menghitung perbedaan berturut-turut dari string 'DJEFPGIALBC'kita mendapatkan vektor numerik

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

yang mengandung interval disonan yang tepat, di samping beberapa nilai negatif, yang tidak akan berguna atau berbahaya. Perhatikan bahwa itu adalah pilihan huruf tambahan JPILdalam string 'DJEFPGIALBC'yang mendefinisikan (melalui perbedaan berurutan) interval disonan.

Untuk melihat apakah kedua nada masukan itu disonan, kami mengambil perbedaan absolut dari angka nada mereka. Misalnya, Cdan D#akan memberikan angka 12dan 3masing - masing, dan perbedaan mutlaknya adalah 9. Perbedaan yang sebenarnya adalah -9, dan interval yang sebenarnya akan 3(diperoleh sebagai -9modulo 12). Namun berkat simetri disebut di atas, kita dapat mempertimbangkan 9bukan 3. Karena 9tidak ada dalam vektor perbedaan berurutan, not-not tersebut adalah konsonan.

Luis Mendo
sumber
2
Saya suka cara Anda menyandikan catatan dan interval disonan dalam string yang sama.
celtschk
8

JavaScript (ES6), 68 64 byte

Membawa catatan sebagai dua string dalam sintaks currying (a)(b). Pengembalian 0untuk disonan atau 1konsonan.

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

Uji kasus

Diformat dan dikomentari

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
sumber
7

Jelly , 26 byte

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

Tautan monadik mengambil daftar kedua catatan (sebagai daftar karakter) dan kembali 0untuk konsonan dan 1disonan.

Cobalah online! atau lihat semua input dalam test-suite .

Bagaimana?

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
sumber
5

Jelly , 31 byte

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

Cobalah online!

wheeeeee 32 byte terlalu panjang

Penjelasan

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
sumber
Hei, itu jawaban yang bagus! Saya bertanya-tanya apakah seseorang memanfaatkan simetri, dan Anda melakukannya. Dan saya suka metode Anda untuk mencocokkan nama catatan dengan angka juga! +1.
Ramillies
Perbedaan semitone mungkin simetris tetapi Anda masih mendapatkan hasil duff - misalnya "G#", "A"(disonan) menghasilkan perbedaan 11yang tidak ada di dalamnya[1,2,6] .
Jonathan Allan
@ Jonathan Allan oh uh well itu memalukan; Saya pikir perbedaan mutlak diperbaiki bahwa ... ._. akan memperbaiki lol
HyperNeutrino
1
@JonathanAllan diperbaiki untuk beberapa byte tambahan (3 IIRC)
HyperNeutrino
4

Mathematica, 55 byte

function                                                  arguments        bytes

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

Memetakan built-in internal Sound`PitchToNumberpada input (daftar dua string), mengambil perbedaan absolut, kemudian mencocokkan pola untuk angka interval disonan.


Hanya untuk bersenang-senang (tidak bersaing)

Berikut adalah beberapa fungsi yang lebih pendek yang melanggar batasan “Anda tidak boleh menetapkan nama lain untuk catatan tersebut.” Paket yang belum sempurnaMusic` memiliki konstanta note yang sudah ditentukan (seperti A4 = 440.) dan fungsi HertzToCents(yang dapat di-golf). Alih-alih string, kita akan menggunakan konstanta note sebagai argumen, tetapi diberikan dalam format berbeda untuk setiap fungsi.

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

Impor paket <<Music`;membutuhkan 9 byte.

Fungsi ini mengubah string (seperti "F#") menjadi konstanta nada (seperti Fsharp3):

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

Untuk menerima interval yang lebih besar dari satu oktaf, ganti Abs[…]dengan Mod[…,12].


Mengapa beberapa interval dianggap disonan? Interval adalah rasio dua frekuensi. Jika rasio memiliki pembilang dan penyebut "sederhana", ia cenderung lebih konsonan. Dalam penyetelan 5-batas , rasio dapat difaktorkan ke dalam bilangan bulat dengan hanya bilangan prima kurang dari atau sama dengan 5. Tidak ada interval dalam temperamen yang sama, selain oktaf, adalah interval yang adil ; mereka hanyalah perkiraan dekat menggunakan kekuatan akar ke-12 dari 2.

Alih-alih hard-coding angka interval mana yang disonan, kita dapat menemukan pendekatan rasional dari interval dan kemudian menentukan apakah pembilang dan penyebutnya “sederhana” (artinya penyebutnya kurang dari 5 dan rasionya tidak membagi 7).

Tabel ini menunjukkan setiap langkah dalam proses itu.

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

Perkiraan rasional terletak dalam 1/17interval karena itu adalah ambang batas terbesar yang membedakan antara semua 12 interval temper yang sama. Kami mencocokkan angka-angka rasional dengan pola Rational[a_,b_](atau hanya a_~_~b_) pertama, dan kemudian mencocokkan bilangan bulat dengan hanya _.

Ini memuncak dalam fungsi agak pendek berikut yang menentukan apakah rasio frekuensi arbitrer (lebih besar dari 1) adalah konsonan atau disonan.

Rationalize[#,1/17]/.{a_~_~b_:>b<=5&&!a∣7,_->True}&       [Fsharp3/C3]     51+9=60
hftf
sumber
1
Astaga, jangan bilang Mathematica punya builtin bahkan untuk ini ...: 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]]&


Formulir input

["IKLAN"]

Keluaran

True->Consonant  
False->Dissonant   

terima kasih @ JonathanFrech -16 byte

J42161217
sumber
Hanya komentar: Anda tidak perlu menghasilkan string Consonantdan Dissonant. Anda dapat menampilkan dua nilai alih-alih nilai (0/1, ... apa pun). Itu bisa menghemat beberapa byte.
Ramillies
1
Bisakah Anda tidak menghilangkan If[...,0,1]dan mendefinisikan True->Consonant; False->Dissonant?
Jonathan Frech
1
StringCases["CC#DD#EFF#GG#AA#B",_~~"#"...]- 42 Bytes
celtschk
1
Juga, 2 byte dapat disimpan dengan mengganti {1,2,6,10,11}dengan1|2|6|10|11
celtschk
1
@ Skyler Lihat jawaban di bawah ini.
hftf
3

Arang , 30 byte

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

Cobalah online! Tautan adalah untuk mengucapkan versi kode. Output 1 untuk konsonan, 0 untuk disonan. Penjelasan:

≔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
sumber
karena penasaran, apakah ada alasan mnemonik mesin terbang ⌕ζdigunakan untuk "menemukan indeks"?
Jonah
@Jonah ζadalah variabel yang ditugaskan sebelumnya.
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.]

penjelasan

Implementasi yang mudah, tidak super golf di J:

  • Input diberikan sebagai catatan terperinci dalam kotak (diproduksi menggunakan potongan), secara berurutan.

  • Temukan indeks mereka dalam rentang catatan: (<;._1',C,C#,D,D#,E,F,F#,G,G#,A,A#,B')i.]

  • Kurangi yang pertama dari yang kedua: -~/

  • Ambil sisanya ketika dibagi 12: 12|

  • Periksa apakah itu salah satu catatan yang disonan: e.&1 2 6 10 11

Cobalah online!

Jonah
sumber
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/#/

Cobalah online! (semua kasus uji sekaligus)

  • Masukkan input setelah kode.
  • Pisahkan nama catatan dengan ,B#di setiap test case.
  • Outputnya adalah ,untuk konsonan, ,#untuk disonan.
  • Dukungan untuk perubahan ganda ( ##) atau E#dalam beberapa kasus tertentu. Kalau tidak, outputnya adalah ,untuk konsonan, #,untuk disonan (terima kasih kepada modulo 12 simetri)
  • Dapat menangani beberapa kasus uji sekaligus (jika dipisahkan secara wajar)
  • Huruf kecil dicetak persis.
pengguna202729
sumber
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;}

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

Nilai pengembalian:

  • Konsonan: 2048
  • Disonan: 0

Bonus: Fungsi tidak peka huruf besar-kecil.

Cobalah online!

celtschk
sumber
Apakah tidak ada dua ruang yang tidak perlu di keduanya return (?
Jonathan Frech
Anda dapat mencoba g(char*s){s=(s[1]&1|2**s&15)*4/5;}f(char*x,char*y){x=1952220<<g(x)>>g(y)&2048;}dan solusi yang bagus!
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""

Di mana ""di bagian akhir sebenarnya berisi karakter"\x02\x04\x0c\x14\x16"

Cobalah secara Online!

(+3 karena saya lupa 11 atau 22 dalam daftar untuk memulai)

-8 byte dari Jonathan Frech dan beralih ke Python 2 .

-34 byte dengan saran dari Jonathan Frech dan menggunakan strindeks alih-alih list.

-4 byte dari inlining idan Neil membalikkan saran string (hanya -2 benar-benar, karena saya lupa ()generator)

-5 byte dari un-inlining i& mengubah format input

-1 byte dari Jonathan Frech dengan map()dan tidak dapat dicetak.

Mengambil input dalam satu baris stdin dalam format:

'C','C#'

Truedisonan, Falsekonsonan.

Penjelasan Lama:

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.indexmengembalikan indeks awal terendah (positif) dari substring yang cocok, jadi "ABACABA".index("A") == 0dan "ABACABA".index("BA") == 1. Karena itu, kita dapat menempatkan nama catatan dengan spasi yang sama dalam suatu string, dan selama (misalnya) Adatang sebelumnya A#, yang dibagikan Atidak akan menjadi masalah.

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

isekarang merupakan fungsi yang mengembalikan indeks dalam 'C C#D D#E F F#G G#A A#B'argumennya (nama catatan) adalah, yaitu 2 * (jumlah semitone yang dicatat dari catatan naik C)

a,b=input()

Python 2 input() (kebanyakan) setara dengan eval(input())di Python3, jadi dengan input format yang valid 'C#','F'(misalnya), a='C#'danb='F'

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

Jika jarak antara not pertama dan not kedua dalam string bukan 2, 4, 12, atau 20 (karena nama not direpresentasikan dalam 2 karakter), maka intervalnya adalah disonansi, cetak True, selain itu konsonan, cetak salah

pizzapants184
sumber
Karena format input tidak ketat, Anda dapat menggunakan eval(input())(13 byte) alih-alih input().split()(15 byte).
Jonathan Frech
101 bytes
Jonathan Frech
98 byte
Jonathan Frech
79 byte
Jonathan Frech
1
Anda bisa menggunakan karakter Unicode ( ) alih-alih string emtpy.
Jonathan Frech
1

C (gcc) , 115117 120 byte

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

Cobalah online!

Kembalikan 1/0 untuk consonat dan dissonat. Itu selalu menarik untuk melakukan manipulasi string dengan murni C. Ambil input sebagaif("A#", "C")

Keyu Gan
sumber
0

PowerShell , 107 byte

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

Cobalah online!

Output Trueuntuk disonan dan Falseuntuk konsonan.

Mengambil input $adan $b, kedua not, sebagai string. Melakukan -splitoperasi pada skala, yang terbagi pada spasi putih, untuk membuat array catatan, menyimpannya ke dalam $x. Temukan .indexof $bdalam array itu, kurangi indeks $a, dan kemudian ambil nilai absolute daripadanya. Cek apakah angka itu adalah -inrentang disonan.

AdmBorkBork
sumber
0

Python 2 , 68 byte

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

Cobalah online!

Keluaran: 1disonan, 0konsonan.

Lynn
sumber
0

SQL, 582 byte

SQL Fiddle

Saya masih memiliki beberapa golf untuk dilakukan, tetapi saya ingin mendapatkannya di sini sebelum akhirnya saya benar-benar memecahnya.

Jika inputnya dalam format huruf, maka menempatkan huruf-huruf itu dalam tabel dengan nilai tidak apa-apa, kan?

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
phroureo
sumber
0

Perl 5 , 106 byte

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

Cobalah online!

Mengembalikan nilai false untuk dissonant, true untuk konsonan.

Xcali
sumber