Beyaz tuşlar üzerinde piyano akorları


9

Backstory [bu doğru değil]

Bir piyano şu şekilde kurulur:

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

Ancak, piyanomda, tüm siyah tuşlar kırıldı!

Yine de kırık piyanoda bazı akorları çalabilmek istiyorum.

Müzikte akor, birlikte çalınan bir grup notadır. Akorların girilmesine izin vermek için önce bir yarı tonun ne olduğunu tanımlayacağım.

Yarı ton nedir?

Yarı ton, Batı müziğindeki en küçük mesafedir. Piyanonun üst kısmına bakarsanız, genellikle siyah bir tuştan beyaz bir tuşa veya tersi yönde hareket edebileceğinizi görürsünüz; Ancak aralarında Bve Cve Eve Fhiçbir siyah anahtar yoktur.

Akor nedir?

Bu zorluğun amaçları için, bir akoru, aralarında belirli sayıda yarı ton bulunan bir demet nota olarak tanımlarız. Örneğin, 4-3-3başlangıçta bir akor ele alalım C(müzik insanları için bu, F majörde bir V 7 akorudur). Biz başlıyoruz C. Biz 4 semitones saymak: C#, D, D#, E. Bir sonraki notudur Eve biz bundan sonra 3 semitones saymak: F, F#, G. Bir sonraki notudur Gve biz bundan sonra 3 semitones saymak: G#, A, Bb. Yani, anlıyoruz C-E-G-Bb. Yaşasın! Ama bekle ... Bbsiyah bir anahtar ve bunlar kırılmış ... Ancak, eğer biz başlarsak G, anlıyoruz G-B-D-F! Yaşasın!

Giriş

Girdi, herhangi bir makul biçimde tamsayıların bir listesi olarak verilir. Bu, yukarıda açıklandığı gibi akoru temsil eder.

Çıktı

Çıktı, yalnızca beyaz tuşlar kullanmaya başlayabileceğim notların bir listesi olmalıdır. Bu aynı zamanda en çok 7 notanın hepsinden oluşan bir dize olabilir, çünkü tüm anahtar adları bir karakter olacaktır. Boş bir çıktıya da sahip olmanız gerekir.

Test Durumları

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

Diğer özellikler

  • Standart Loopholes yasaktır
  • Girişin en az bir tamsayı olduğunu varsayabilirsiniz.
  • Tüm tamsayıların negatif olmadığını ve 12'den az olduğunu varsayabilirsiniz (çünkü piyano her 12 notada bir tekrarlanır)
  • Çıktı herhangi bir sırada olabilir

Kazanma Kriterleri

15 Nisan itibariyle en kısa geçerli başvuru kabul edilecektir.


"Olumsuz olmayan ve 12'den az" olduğunu varsayabiliriz - bu "pozitif ve 12'den küçük veya ona eşit" olmamalı mı?
Jonathan Allan

@JonathanAllan Temelde hiçbir fark yok; Benim yöntemim mükemmel bir birlikteliğe izin veriyor ama mükemmel bir oktav değil; tam tersi. Teorik olarak, kısıtlamanız daha anlamlı olabilir, ancak muhtemelen cevaplamamam gerekiyor çünkü zaten cevaplar var ve meydan okumayı temelden değiştirmiyor.
HyperNeutrino

Yanıtlar:


3

Jöle , 25 bayt

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

Çevrimiçi deneyin! veya bir test takımına bakın

Nasıl?

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 bayt

Düzeltme için Jonathan Allan'a teşekkürler .

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

Çevrimiçi deneyin! Veya tüm test senaryolarını doğrulayın .

açıklama

Desen 2 2 1 2 2 2 1, ardışık beyaz tuşlar arasındaki aralıkları belirtir. Program, her bir tuşu giriş akorunun potansiyel en düşük notası olarak test etmek için bu temel desene tüm döngüsel kaymaları uygulayan bir döngü kullanır. Her vardiya için, desenin kümülatif toplamı elde edilir. Örneğin, Bpotansiyel en düşük nota olarak, örüntüye kaydırılmıştır 1 2 2 1 2 2 2ve toplam değeri kadardır 1 3 5 6 8 10 12.

Şimdi, bunun bir 4 3 3akoru destekleyip destekleyemeyeceğini görmek için akor aralıklarının kümülatif toplamını hesaplıyoruz 4 7 10; 1 tabanlı modulo 12 (bir aralık 14verir 2) ile azaltın ; ve bu numaraların izin verilen değerlerin üyesi olup olmadığını kontrol edin 1 3 5 6 8 10 12. Bu örnekte durum böyle değil. Durum böyle olsaydı, mektubun çıktısını alırdık B.

Döngüsel kaymalar ve çıktı harfleri arasındaki yazışma dizge tarafından tanımlanır 'BAGFEDC'. Bu, 'B'(ilk karakter) tarafından döngüsel bir kaymaya karşılık geldiğini gösterir 1; 'A'(ikinci karakter), 2vb. döngüsel kaymaya karşılık gelir .

'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

Mathematica, 110 bayt (ISO 8859-1 kodlaması)

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

±Tamsayıların listesini girdi olarak alan tekli bir işlevi tanımlar (aslında tamsayıların boyutu veya işaretleri üzerinde herhangi bir kısıtlama yoktur) ve tek karakterli dizelerin listesini döndürür. Örneğin, ±{3,4}döndürür {"A","D","E"}.

"A#BC#D#EF#G#"~StringTake~{Mod[#,12,1]}&/@#bir tamsayı listesini karşılık gelen not adlarına dönüştüren bir işlevdir, ancak #herhangi bir siyah tuş anlamına gelir. Bu, her bir elemanına uygulanan Accumulate[i~Prepend~#]&/@Range@12Biz içeren tüm bu tür not isim listesi filtre 1 ile 12 için olası her bir not ile başlayarak not aralıklarının giriş listesi listesinden not değerlerinin bir listesini oluşturur, "#"kullanılarak Select[...,FreeQ@"#"]ve daha sonra ile kalan her listedeki ilk notayı geri döndürün #&@@@.


Güzel teslim!
HyperNeutrino

Soru: Mathematica kendi bayt sistemini kullanıyor mu? Bu 110 karakterdir, ancak UTF-8'de +/-sembol nedeniyle 111 bayttır .
HyperNeutrino

Atamayı tamamen kaldırabilir ve sadece bir işlevi "örtük olarak döndürebilirsiniz".
wizzwizz4

@ wizzwizz4: Değişkeni isimlendirmem gerektiğine karar verdim Accumulate[i~Prepend~#]&çünkü aksi halde körili bir çatışma olurdu. Gerçi bir geçici çözüm bulmaktan çekinmeyin!
Greg Martin

@HyperNeutrino: UTF-8'in standart kodlama olduğu konusunda haklısınız, ancak Mathematica (genellikle) ISO 8859-1 kodlamasında da işlev görebilir. Bunu yazıda not ettim.
Greg Martin

3

Python 2, 159155 bayt

(Bundan daha kısa geçerli bir gönderim olduğundan emin olduktan sonra bunu yayınlayın)

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]

Hemen hemen önemsiz çözüm. Her bir karakterin ayrı bir satırda olduğu bir tamsayı listesi ve çıktı listesi olarak girilir.

Gereksiz bir değişkeni kaldırarak -4 bayt


3

JavaScript (ES6), 72 71 68 bayt

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

Siyah anahtarları atlayan her anahtardan geçer, ardından yarı tonların toplamının hiçbir zaman siyah bir anahtara gelmediğini kontrol eder.

Düzenleme: @Arnauld sayesinde 3 bayt kaydedildi.


4
Okunabilirlik ?! Doğru sitede olduğunuzdan emin misiniz? :-)
wizzwizz4
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.