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 C
setelah 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
True
danFalse
, 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.
APL (Dyalog) ,
6239 bytePenggunaan
⎕IO←0
; 0 konsonan, 1 disonan. Mengambil daftar karakter catatan dasar sebagai argumen kiri dan daftar benda tajam sebagai argumen kanan.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 mutlaksumber
MATL ,
302726 byteInput kedua catatan dalam baris yang berbeda. Output
0
untuk konsonan,1
untuk disonan.Cobalah online! Atau verifikasi semua kasus uji .
Penjelasan
String 11 karakter
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
D
akan memberi1
,E
akan memberi3
, ...,C
akan memberi11
. Angka-angka ini juga dapat dianggap 1 × 1 array numerik. Input tajam sepertiC#
akan memberikan array 1 × 2[11 0]
, yang berartiC
ditemukan pada posisi11
dan#
tidak ditemukan.Perhatikan bahwa surat-surat
JPIL
tidak akan pernah ada dalam input. Untuk saat ini mereka hanya digunakan sebagai penampung, jadi misalnya noteE
adalah dua semitone di atasD
. 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
1
setiap entri dari array 1 × 1 atau 1 × 2 yang diperoleh sebelumnya dan kemudian jumlah array (2 byte). Dengan demikian nada non-tajam meningkat1
dan nada tajam meningkat2
. 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 noteD
akan memberikan nomor nada2
,D#
akan memberi3
, ...,C
akan memberi12
,C#
akan memberi13
.Interval disonan adalah
1
,2
,6
,10
, atau11
. 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 numerikyang mengandung interval disonan yang tepat, di samping beberapa nilai negatif, yang tidak akan berguna atau berbahaya. Perhatikan bahwa itu adalah pilihan huruf tambahan
JPIL
dalam 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,
C
danD#
akan memberikan angka12
dan3
masing - masing, dan perbedaan mutlaknya adalah9
. Perbedaan yang sebenarnya adalah-9
, dan interval yang sebenarnya akan3
(diperoleh sebagai-9
modulo 12). Namun berkat simetri disebut di atas, kita dapat mempertimbangkan9
bukan3
. Karena9
tidak ada dalam vektor perbedaan berurutan, not-not tersebut adalah konsonan.sumber
JavaScript (ES6),
6864 byteMembawa catatan sebagai dua string dalam sintaks currying
(a)(b)
. Pengembalian0
untuk disonan atau1
konsonan.Uji kasus
Tampilkan cuplikan kode
Diformat dan dikomentari
sumber
Jelly , 26 byte
Tautan monadik mengambil daftar kedua catatan (sebagai daftar karakter) dan kembali
0
untuk konsonan dan1
disonan.Cobalah online! atau lihat semua input dalam test-suite .
Bagaimana?
sumber
Jelly , 31 byte
Cobalah online!
wheeeeee 32 byte terlalu panjang
Penjelasan
sumber
"G#", "A"
(disonan) menghasilkan perbedaan11
yang tidak ada di dalamnya[1,2,6]
.Mathematica, 55 byte
Memetakan built-in internal
Sound`PitchToNumber
pada 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 sempurna
Music`
memiliki konstanta note yang sudah ditentukan (sepertiA4 = 440.
) dan fungsiHertzToCents
(yang dapat di-golf). Alih-alih string, kita akan menggunakan konstanta note sebagai argumen, tetapi diberikan dalam format berbeda untuk setiap fungsi.Impor paket
<<Music`;
membutuhkan 9 byte.Fungsi ini mengubah string (seperti
"F#"
) menjadi konstanta nada (sepertiFsharp3
):Untuk menerima interval yang lebih besar dari satu oktaf, ganti
Abs[…]
denganMod[…,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.
Perkiraan rasional terletak dalam
1/17
interval karena itu adalah ambang batas terbesar yang membedakan antara semua 12 interval temper yang sama. Kami mencocokkan angka-angka rasional dengan polaRational[a_,b_]
(atau hanyaa_~_~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.
sumber
Mathematica, 118 byte
Formulir input
Keluaran
terima kasih @ JonathanFrech -16 byte
sumber
Consonant
danDissonant
. Anda dapat menampilkan dua nilai alih-alih nilai (0/1, ... apa pun). Itu bisa menghemat beberapa byte.If[...,0,1]
dan mendefinisikanTrue->Consonant; False->Dissonant
?StringCases["CC#DD#EFF#GG#AA#B",_~~"#"...]
- 42 Bytes{1,2,6,10,11}
dengan1|2|6|10|11
Arang , 30 byte
Cobalah online! Tautan adalah untuk mengucapkan versi kode. Output 1 untuk konsonan, 0 untuk disonan. Penjelasan:
sumber
⌕ζ
digunakan untuk "menemukan indeks"?ζ
adalah variabel yang ditugaskan sebelumnya.J, 68 byte
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!
sumber
/// ,
9088 byteCobalah online! (semua kasus uji sekaligus)
,B#
di setiap test case.,
untuk konsonan,,#
untuk disonan.##
) atauE#
dalam beberapa kasus tertentu. Kalau tidak, outputnya adalah,
untuk konsonan,#,
untuk disonan (terima kasih kepada modulo 12 simetri)sumber
C (gcc) , 91 byte
panggilan:
f("A#", "D")
Nilai pengembalian:
Bonus: Fungsi tidak peka huruf besar-kecil.
Cobalah online!
sumber
return (
?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!Python 2,
125 117 83 7877 byteDi 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
str
indeks alih-alihlist
.-4 byte dari inlining
i
dan 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:
True
disonan,False
konsonan.Penjelasan Lama:
Python
str.index
mengembalikan indeks awal terendah (positif) dari substring yang cocok, jadi"ABACABA".index("A") == 0
dan"ABACABA".index("BA") == 1
. Karena itu, kita dapat menempatkan nama catatan dengan spasi yang sama dalam suatu string, dan selama (misalnya)A
datang sebelumnyaA#
, yang dibagikanA
tidak akan menjadi masalah.i
sekarang 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 naikC
)Python 2
input()
(kebanyakan) setara denganeval(input())
di Python3, jadi dengan input format yang valid'C#','F'
(misalnya),a='C#'
danb='F'
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
sumber
eval(input())
(13 byte) alih-alihinput().split()
(15 byte).
) alih-alih string emtpy.C (gcc) , 115
117120byteCobalah online!
Kembalikan 1/0 untuk consonat dan dissonat. Itu selalu menarik untuk melakukan manipulasi string dengan murni C. Ambil input sebagai
f("A#", "C")
sumber
PowerShell , 107 byte
Cobalah online!
Output
True
untuk disonan danFalse
untuk konsonan.Mengambil input
$a
dan$b
, kedua not, sebagai string. Melakukan-split
operasi pada skala, yang terbagi pada spasi putih, untuk membuat array catatan, menyimpannya ke dalam$x
. Temukan.indexof
$b
dalam array itu, kurangi indeks$a
, dan kemudian ambil nilaiabs
olute daripadanya. Cek apakah angka itu adalah-in
rentang disonan.sumber
Python 2 , 68 byte
Cobalah online!
Keluaran:
1
disonan,0
konsonan.sumber
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?
sumber
Perl 5 , 106 byte
Cobalah online!
Mengembalikan nilai false untuk dissonant, true untuk konsonan.
sumber