Piano Chords pada White Keys

9

Backstory [yang tidak benar]

Piano diatur seperti ini:

! [http://www.piano-lessons-made-simple.com/images/2-Octave-Labled.gif

Namun, di piano saya, semua kunci hitam rusak!

Saya masih ingin dapat memainkan beberapa akor pada piano saya yang rusak.

Dalam musik, akor adalah sekelompok not yang dimainkan bersama. Untuk memungkinkan input akord, pertama-tama saya akan menentukan apa semitone itu.

Apa itu semitone?

Semitone adalah jarak terkecil dalam musik Barat. Jika Anda melihat bagian atas piano, Anda melihat bahwa Anda biasanya dapat berpindah dari kunci hitam ke kunci putih, atau sebaliknya; namun, antara Bdan Cdan Edan Ftidak ada kunci hitam.

Apa itu akord?

Untuk keperluan tantangan ini, kami mendefinisikan akord sebagai sekelompok not dengan sejumlah semitone di antara mereka. Sebagai contoh, mari kita mulai dengan 4-3-3chord mulai C(untuk orang musik, ini adalah chord V 7 di F mayor). Kita mulai dari C. Kami menghitung 4 semitone: C#, D, D#, E. Catatan berikutnya adalah E, dan kita menghitung 3 semitone setelah itu: F, F#, G. Catatan berikutnya adalah G, dan kita menghitung 3 semitone setelah itu: G#, A, Bb. Jadi, kita dapatkan C-E-G-Bb. Yay! Tapi tunggu ... Bbadalah kunci hitam dan itu rusak ... Namun, jika kita mulai dari G, kita dapatkan G-B-D-F! Yay!

Memasukkan

Input diberikan sebagai daftar bilangan bulat dalam format apa pun yang masuk akal. Ini mewakili akor seperti dijelaskan di atas.

Keluaran

Keluaran harus berupa daftar catatan yang dapat saya mulai hanya perlu menggunakan tombol putih. Ini juga bisa menjadi string dari semua hingga 7 catatan karena semua keynames akan menjadi satu karakter. Anda harus dapat menangani memiliki output kosong juga.

Uji Kasus

input -> output // comments
4 3 -> C F G // this is a major triad
3 4 -> D E A // this is a minor triad
4 3 3 -> G // this is the major-minor seventh chord
3 3 3 -> [empty output] // this is the diminished-diminished seventh chord. All of them use black keys
4 4 -> [empty output] // this is an augmented triad
3 3 -> B // this is a diminished triad
1 -> B E // this is just a minor second
11 -> C F // this is just a major seventh

Spesifikasi lainnya

  • Standar Lubang terlarang
  • Anda dapat mengasumsikan bahwa input memiliki setidaknya satu bilangan bulat
  • Anda dapat mengasumsikan bahwa semua bilangan bulat adalah non-negatif dan kurang dari 12 (karena piano mengulangi setiap 12 nada)
  • Output mungkin dalam urutan apa pun

Kriteria Menang

Pengajuan terpendek yang berlaku pada 15 April akan diterima.

HyperNeutrino
sumber
Kita dapat berasumsi "non-negatif dan kurang dari 12" - haruskah itu tidak "positif dan kurang dari atau sama dengan 12"?
Jonathan Allan
@ JonathanAllan Pada dasarnya tidak ada perbedaan; metode saya memungkinkan untuk Serempak Sempurna tetapi bukan Oktaf Sempurna; milik Anda sebaliknya. Secara teoritis, batasan Anda mungkin lebih masuk akal, tetapi saya pikir saya mungkin tidak boleh mengubahnya karena sudah ada jawaban dan itu tidak mengubah tantangan secara mendasar.
HyperNeutrino

Jawaban:

3

Jelly , 25 byte

236ḃ2ṙЀ7+\€Ṭ
+\ịþ¢Ạ€TịØA

Cobalah online! atau lihat test suite

Bagaimana?

236ḃ2ṙЀ7+\€Ṭ - Link 1, white-note-offsets: no arguments
236ḃ2         - 236 in bijective base 2 [2, 2, 1, 2, 2, 1, 2] - semitones G->A, A->B ...
     ṙЀ7     - rotate left by, mapped over [1,2,3,4,5,6,7] - i.e. as above for each
                    starting white key (1st one A->B,B->C,...; 2nd B->C,C->D,...; etc)
         +\€  - reduce €ach with addition - i.e. absolute number of semitones: [[2,3,5,7,8,10,12],[1,3,5,6,8,10,12],[2,4,5,7,9,11,12],[2,3,5,7,9,10,12],[1,3,5,7,8,10,12],[2,4,6,7,9,11,12],[2,4,5,7,9,10,12]]
            Ṭ - untruth (vectorises) - make lists with 1s at those indexes: [[0,1,1,0,1,0,1,1,0,1,0,1],[1,0,1,0,1,1,0,1,0,1,0,1],[0,1,0,1,1,0,1,0,1,0,1,1],[0,1,1,0,1,0,1,0,1,1,0,1],[1,0,1,0,1,0,1,1,0,1,0,1],[0,1,0,1,0,1,1,0,1,0,1,1],[0,1,0,1,1,0,1,0,1,1,0,1]]

+\ịþ¢Ạ€TịØA - Main link: list of semitone gap integers (even negatives will work)
+\          - reduce by addition - gets the absolute semitone offsets needed
    ¢       - last link (1) as a nilad
   þ        - outer product with:
  ị         -     index into - 7 lists, each with 1s for white and 0s for black keys hit
                      note that indexing is modular and all the lists are length 12
                      so any integer is a valid absolute offset, not just 0-11 inclusive
     Ạ€     - all truthy for €ach - for each get a 1 if all keys are white ones, else 0
       T    - truthy indexes - get the valid starting white keys as numbers from 1 to 7
        ị   - index into:
         ØA -     the uppercase alphabet
Jonathan Allan
sumber
6

MATL , 31 byte

Terima kasih kepada Jonathan Allan untuk koreksi.

'BAGFEDC'"GYs12X\110BQX@YSYsm?@

Cobalah online! Atau verifikasi semua kasus uji .

Penjelasan

Pola 2 2 1 2 2 2 1menentukan interval antara tombol putih berturut-turut. Program menggunakan loop yang menerapkan semua perubahan siklik pada pola dasar ini, untuk menguji setiap kunci sebagai nada terendah potensial dari kunci input. Untuk setiap shift, jumlah kumulatif dari pola diperoleh. Misalnya, untuk Bcatatan terendah potensial, polanya telah bergeser ke 1 2 2 1 2 2 2dan jumlah kumulatifnya adalah 1 3 5 6 8 10 12.

Sekarang, untuk melihat apakah ini dapat mendukung 4 3 3akor, kami menghitung jumlah kumulatif dari interval akor, yaitu 4 7 10; menguranginya melalui modulo 12 berbasis-1 (interval 14memberi akan 2); dan periksa apakah angka-angka itu semua adalah anggota dari nilai yang diizinkan 1 3 5 6 8 10 12. Tidak demikian halnya dalam contoh ini. Kalau begitu, kami akan mengeluarkan surat itu B.

Korespondensi antara pergeseran siklik dan huruf keluaran didefinisikan oleh string 'BAGFEDC'. Ini menunjukkan bahwa 'B'(karakter pertama) sesuai dengan pergeseran siklik oleh 1; 'A'(karakter kedua) berhubungan dengan perubahan siklik oleh 2dll.

'BAGFEDC'  % Push this string
"          % For each character from the string
  G        %   Push input array
  Ys       %   Cumulative sum
  12X\     %   1-based modulo 12, element-wise (1,12,13,14 respectively give 1,12,1,2)
  110BQ    %   Push 110, convert to binary, add 1 element-wise: gives [2 2 1 2 2 2 1]
  X@       %   Push current iteration index, starting at 1
  YS       %   Cyclic shift to the right by that amount
  Ys       %   Cumulative sum
  m        %   Ismember. Gives an array of true of false entries
  ?        %   If all true
    @      %     Push current character
           %   End (implicit)
           % End (implicit)
           % Display (implicit)
Luis Mendo
sumber
5

Mathematica, 110 byte (penyandian ISO 8859-1)

±i_:=#&@@@Select["A#BC#D#EF#G#"~StringTake~{Mod[#,12,1]}&/@#&/@(Accumulate[i~Prepend~#]&/@Range@12),FreeQ@"#"]

Mendefinisikan fungsi unary dengan ±mengambil daftar bilangan bulat sebagai input (sebenarnya tidak ada batasan pada ukuran atau tanda-tanda bilangan bulat) dan mengembalikan daftar string satu karakter. Misalnya, ±{3,4}kembali {"A","D","E"}.

"A#BC#D#EF#G#"~StringTake~{Mod[#,12,1]}&/@#adalah fungsi yang mengubah daftar bilangan bulat menjadi nama catatan yang sesuai, kecuali yang #berarti kunci hitam apa pun. Ini diterapkan untuk setiap elemen Accumulate[i~Prepend~#]&/@Range@12, yang membangun daftar nilai catatan dari daftar input interval catatan, mulai dengan setiap catatan yang mungkin dari 1 hingga 12. Kami menyaring semua daftar nama-catatan seperti itu yang mengandung "#"menggunakan Select[...,FreeQ@"#"], dan kemudian kembalikan catatan pertama di setiap daftar yang tersisa menggunakan #&@@@.

Greg Martin
sumber
Pengiriman yang bagus!
HyperNeutrino
Pertanyaan: Apakah Mathematica menggunakan sistem byte sendiri? Ini adalah 110 karakter tetapi dalam UTF-8 itu 111 byte karena +/-simbol.
HyperNeutrino
Anda dapat sepenuhnya menghapus tugas dan hanya "mengembalikan fungsi" secara implisit.
wizzwizz4
@ wizzwizz4: Saya menemukan saya harus memberi nama variabel Accumulate[i~Prepend~#]&karena jika tidak akan ada bentrokan kari. Jangan ragu untuk menemukan solusinya!
Greg Martin
@HyperNeutrino: Anda benar bahwa UTF-8 adalah penyandian standar, tetapi Mathematica dapat (biasanya) berfungsi dalam penyandian ISO 8859-1 juga. Saya telah mencatatnya di posting.
Greg Martin
3

Python 2, 159 155 byte

(Posting ini setelah memastikan ada kiriman yang valid yang lebih pendek dari yang ini)

import numpy
s='C.D.EF.G.A.B'
def k(y):return lambda x:s[(x+y)%12]
for i in range(12):
    if s[i]!='.'and'.'not in map(k(i),numpy.cumsum(input())):print s[i]

Cukup banyak solusi sepele. Input sebagai daftar integer dan output dengan masing-masing karakter pada setiap baris.

-4 byte dengan menghapus variabel yang tidak perlu

HyperNeutrino
sumber
3

JavaScript (ES6), 72 71 68 byte

a=>[..."C1D1EF1G1A1B"].filter((c,i,b)=>!+c>a.some(e=>+b[i+=e,i%12]))

Ulangi setiap tombol tanpa kunci hitam, lalu periksa bahwa jumlah kumulatif semitone tidak pernah mendarat pada kunci hitam.

Sunting: Disimpan 3 byte berkat @Arnauld.

Neil
sumber
4
Keterbacaan ?! Apakah Anda yakin berada di situs yang benar? :-)
wizzwizz4