Hợp âm piano trên phím trắng


9

Backstory [không đúng sự thật]

Một cây đàn piano được thiết lập như thế này:

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

Tuy nhiên, trên cây đàn piano của tôi, tất cả các phím màu đen đều bị hỏng!

Tôi vẫn muốn có thể chơi một số hợp âm trên cây đàn piano bị hỏng của tôi.

Trong âm nhạc, hợp âm là một nhóm các nốt được chơi cùng nhau. Để cho phép nhập hợp âm, trước tiên tôi sẽ xác định semitone là gì.

Một nửa cung là gì?

Một nửa cung là khoảng cách nhỏ nhất trong âm nhạc phương Tây. Nếu bạn nhìn vào phần trên cùng của đàn piano, bạn sẽ thấy rằng bạn thường có thể chuyển từ phím đen sang phím trắng hoặc ngược lại; Tuy nhiên, giữa BCEFkhông có phím đen.

Hợp âm là gì?

Đối với mục đích của thử thách này, chúng tôi xác định hợp âm là một nhóm các nốt với một số lượng bán kết nhất định giữa chúng. Ví dụ: chúng ta hãy 4-3-3bắt đầu một hợp âm bắt đầu C(đối với người nghe nhạc, đây là hợp âm V 7 trong F chính). Chúng tôi bắt đầu tại C. Chúng tôi đếm lên 4 semitones: C#, D, D#, E. Những lưu ý tiếp theo là E, và chúng tôi đếm 3 semitones lên sau đó: F, F#, G. Những lưu ý tiếp theo là G, và chúng tôi đếm 3 semitones lên sau đó: G#, A, Bb. Vì vậy, chúng tôi nhận được C-E-G-Bb. Yay! Nhưng chờ đã ... Bblà một chìa khóa đen và chúng bị hỏng ... Tuy nhiên, nếu chúng ta bắt đầu từ đó G, chúng ta sẽ nhận được G-B-D-F! Yay!

Đầu vào

Đầu vào được đưa ra dưới dạng danh sách các số nguyên ở bất kỳ định dạng hợp lý nào. Điều này đại diện cho hợp âm như mô tả ở trên.

Đầu ra

Đầu ra phải là một danh sách các ghi chú mà tôi có thể bắt đầu chỉ cần sử dụng các phím trắng. Đây cũng có thể là một chuỗi của tất cả tối đa 7 ghi chú vì tất cả các tên khóa sẽ là một ký tự. Bạn phải có khả năng xử lý có một đầu ra trống là tốt.

Các trường hợp thử nghiệm

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

Thông số kỹ thuật khác

  • Lỗ hổng tiêu chuẩn bị cấm
  • Bạn có thể cho rằng đầu vào có ít nhất một số nguyên
  • Bạn có thể cho rằng tất cả các số nguyên đều không âm và nhỏ hơn 12 (vì piano lặp lại sau mỗi 12 nốt)
  • Đầu ra có thể theo thứ tự bất kỳ

Tiêu chí chiến thắng

Đệ trình hợp lệ ngắn nhất kể từ ngày 15 tháng 4 sẽ được chấp nhận.


Chúng tôi có thể giả sử "không âm và nhỏ hơn 12" - không nên "dương và nhỏ hơn hoặc bằng 12"?
Jonathan Allan

@Jonathan ALLan Về cơ bản không có sự khác biệt; phương pháp của tôi cho phép một Unison hoàn hảo nhưng không phải là một Octave hoàn hảo; của bạn ngược lại. Về mặt lý thuyết, hạn chế của bạn có thể có ý nghĩa hơn nhưng tôi nghĩ có lẽ tôi không nên thay đổi nó vì đã có câu trả lời và về cơ bản nó không thay đổi thử thách.
HyperNeutrino

Câu trả lời:


3

Thạch , 25 byte

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

Hãy thử trực tuyến! hoặc xem một bộ thử nghiệm

Làm sao?

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

6

MATL , 31 byte

Cảm ơn Jonathan Allan cho một sự điều chỉnh.

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

Hãy thử trực tuyến! Hoặc xác minh tất cả các trường hợp thử nghiệm .

Giải trình

Mẫu 2 2 1 2 2 2 1chỉ định khoảng giữa các phím trắng liên tiếp. Chương trình sử dụng một vòng lặp áp dụng tất cả các ca tuần hoàn cho mẫu cơ bản này, để kiểm tra từng phím như một nốt thấp nhất tiềm năng của hợp âm đầu vào. Đối với mỗi ca, tổng tích lũy của mẫu được lấy. Ví dụ, đối Bvới lưu ý thấp nhất tiềm năng, mẫu đã được chuyển sang 1 2 2 1 2 2 2và tổng tích lũy của nó là 1 3 5 6 8 10 12.

Bây giờ, để xem điều này có thể hỗ trợ 4 3 3hợp âm hay không, chúng tôi tính tổng tích lũy của các khoảng hợp âm, đó là 4 7 10; giảm nó thông qua modulo 12 dựa trên 1 (một khoảng thời gian 14sẽ cung cấp 2); và kiểm tra xem những con số đó có phải là thành viên của các giá trị được phép không 1 3 5 6 8 10 12. Đó không phải là trường hợp trong ví dụ này. Nếu nó là trường hợp, chúng tôi sẽ xuất thư B.

Sự tương ứng giữa các ca tuần hoàn và các chữ cái đầu ra được xác định bởi chuỗi 'BAGFEDC'. Điều này chỉ ra rằng 'B'(ký tự đầu tiên) tương ứng với sự dịch chuyển theo chu kỳ 1; 'A'(ký tự thứ hai) tương ứng với dịch chuyển theo chu kỳ, 2v.v.

'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)

5

Mathicala, 110 byte (mã hóa ISO 8859-1)

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

Xác định hàm unary ±lấy danh sách các số nguyên làm đầu vào (thực tế không hạn chế kích thước hoặc dấu hiệu của số nguyên) và trả về danh sách các chuỗi một ký tự. Ví dụ, ±{3,4}trả về {"A","D","E"}.

"A#BC#D#EF#G#"~StringTake~{Mod[#,12,1]}&/@#là một hàm biến danh sách các số nguyên thành các tên ghi chú tương ứng, ngoại trừ #viết tắt của bất kỳ khóa đen nào. Điều này được áp dụng cho từng yếu tố Accumulate[i~Prepend~#]&/@Range@12, trong đó xây dựng danh sách các giá trị ghi chú từ danh sách đầu vào danh sách các khoảng ghi chú, bắt đầu với từng ghi chú có thể từ 1 đến 12. Chúng tôi lọc ra tất cả các danh sách tên ghi chú có chứa "#"bằng cách sử dụng Select[...,FreeQ@"#"], sau đó trả lại ghi chú đầu tiên trong mỗi danh sách còn lại bằng cách sử dụng #&@@@.


Trình tốt đẹp!
HyperNeutrino

Câu hỏi: Mathicala có sử dụng hệ thống byte của riêng mình không? Đây là 110 ký tự nhưng trong UTF-8, nó là 111 byte vì +/-ký hiệu.
HyperNeutrino

Bạn hoàn toàn có thể loại bỏ bài tập và chỉ "hoàn trả" một hàm.
wizzwizz4

@ wizzwizz4: Tôi thấy tôi phải đặt tên cho biến Accumulate[i~Prepend~#]&vì nếu không sẽ có một cuộc đụng độ cà ri. Hãy tìm một cách giải quyết mặc dù!
Greg Martin

@HyperNeutrino: bạn nói đúng rằng UTF-8 là mã hóa tiêu chuẩn, nhưng Mathicala cũng có thể (thường) hoạt động trong mã hóa ISO 8859-1. Tôi đã lưu ý rằng trong bài viết.
Greg Martin

3

Python 2, 159 155 byte

(Đăng bài này sau khi đảm bảo có một bài nộp hợp lệ ngắn hơn bài này)

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]

Khá nhiều chỉ là giải pháp tầm thường. Nhập vào dưới dạng danh sách các số nguyên và đầu ra với mỗi ký tự trên một dòng riêng lẻ.

-4 byte bằng cách loại bỏ một biến không cần thiết


3

JavaScript (ES6), 72 71 68 byte

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

Vòng lặp qua từng phím bỏ qua các phím đen, sau đó kiểm tra xem tổng tích lũy của nửa cung không bao giờ rơi vào khóa đen.

Chỉnh sửa: Đã lưu 3 byte nhờ @Arnauld.


4
Dễ đọc?! Bạn có chắc là bạn đang ở đúng trang web? :-)
wizzwizz4
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.