Bu notun sıklığı nedir?


21

Hızlı müzik tazeleme:

Piyano klavyesi 88 notadan oluşmaktadır. Her oktavda, 12 nota vardır C, C♯/D♭, D, D♯/E♭, E, F, F♯/G♭, G, G♯/A♭, A, A♯/B♭ve B. Bir 'C' ye her basışınızda, desen bir oktav daha yükseğe tekrarlar.

görüntü tanımını buraya girin

Bir not benzersiz klavyenin 0 8. ilk üç notlar arasında bir sayıdır 1) herhangi bir kavuz veya düz yüzeylerin de dahil olmak üzere harf, ve 2) oktav tanımlanır vardır A0, A♯/B♭ve B0. Bundan sonra oktav 1. C1, C♯1/D♭1, D1, D♯1/E♭1, E1, F1, F♯1/G♭1, G1, G♯1/A♭1, A1, A♯1/B♭1ve kromatik tam kromatik ölçek gelir B1. Bu, 2, 3, 4, 5, 6 ve 7 oktavlarda tam bir kromatik ölçek geldikten sonra, son nota C8.

Her nota 20-4100 Hz aralığında bir frekansa karşılık gelir. İle A0tam olarak 27,500 hertz başlayarak karşılık gelen her nota iki veya kabaca 1.059463 önceki nota süreleri onikinci köküdür. Daha genel bir formül:

görüntü tanımını buraya girin

n, notun numarasıdır; A0, 1'dir. ( Burada daha fazla bilgi var )

Meydan okuma

Bir notu temsil eden bir dizgede geçen ve bu notun sıklığını yazdırır veya döndüren bir program veya işlev yazın. #Keskin sembol (ya da sizin gençler için hashtag) için bir pound işareti bve düz sembol için bir küçük harf kullanacağız . Tüm girişler (uppercase letter) + (optional sharp or flat) + (number)boşluksuz olarak görünecektir . Giriş klavyenin aralığının dışındaysa (A0'dan düşük veya C8'den yüksek) veya geçersiz, eksik veya fazladan karakterler varsa, bu geçersiz bir giriştir ve işlemeniz gerekmez. Ayrıca, E # veya Cb gibi garip girdiler almayacağınızı da güvenle kabul edebilirsiniz.

Hassas

Sonsuz hassasiyet gerçekten mümkün olmadığından , gerçek değerin bir kuruşundaki herhangi bir şeyin kabul edilebilir olduğunu söyleyeceğiz . Aşırı ayrıntıya girmeden, bir yüzde iki veya 1.0005777895'in 1200. köküdür. Bunu daha açık hale getirmek için somut bir örnek kullanalım. Diyelim ki girişiniz A4. Tam bu kayda değer 440 Hz'dir. Bir kez yüzde düz 440 / 1.0005777895 = 439.7459. Yüzde keskin olduğu için 440 * 1.0005777895 = 440.2542, 439.7459'dan büyük ancak 440.2542'den küçük herhangi bir sayı sayılacak kadar kesindir.

Test durumları

A0  --> 27.500
C4  --> 261.626
F#3 --> 184.997
Bb6 --> 1864.66
A#6 --> 1864.66
A4  --> 440
D9  --> Too high, invalid input.
G0  --> Too low, invalid input.
Fb5 --> Invalid input.
E   --> Missing octave, invalid input
b2  --> Lowercase, invalid input
H#4 --> H is not a real note, invalid input.

Geçersiz girişleri işlemeniz gerekmediğini unutmayın. Programınız gerçek girişlermiş gibi görünüyorsa ve bir değer yazıyorsa, bu kabul edilebilir. Programınız çökerse, bunun da kabul edilebilir olduğunu. Bir tane aldığında her şey olabilir. Giriş ve çıkışların tam listesi için bu sayfaya bakın.

Her zaman olduğu gibi, bu kod golf, bu yüzden standart boşluklar geçerlidir ve baytlarda en kısa cevap kazanır.


9
"H # 4 -> H gerçek bir not değil, geçersiz giriş." Avrupa'da hariç.
Lui,

6
@ Lui, Avrupa’nın bütününün kullandığı gibi Avrupa’yla ilgili bu şey Hnedir? HB anlamı AFAIK sadece Almanca konuşulan ülkelerde kullanılır. ( Bbu arada Bb anlamına gelir.) İngilizlerin ve İrlandalıların B dedikleri şey, İspanya ve İtalya'da Do Re Mi Fa Sol La Si'deki gibi Si veya Ti denir.
Seviye Nehri St

3
Daha önce bir violada B♯2 oynamıştım, tamamen mantıklı bir not ve hiç de garip değil.
Neil

3
@steveverrill Hgöre, Almanya, Çek Cumhuriyeti, Slovakya, Polonya, Macaristan, Sırbistan, Danimarka, Norveç, Finlandiya, Estonya ve Avusturya'da kullanılan Wikipedia . (Ayrıca kendim de Finlandiya için onaylayabilirim.)
PurkkaKoodari

6
@Neil Muhtemelen sadece kazaydı. ;)
kabı

Yanıtlar:


21

Japt, 41 37 35 34 bayt

Sonunda ¾iyi kullanabilme şansım oldu ! :-)

55*2pU¬®-1¾ª"C#D EF G A B"bZ /C} x

Çevrimiçi deneyin!

Nasıl çalışır

          // Implicit: U = input string, C = 12
U¨    }  // Take U, split into chars, and map each item Z by this function:
-1¾       //  Subtract 1.75 from Z. This produces NaN for non-digits.
ª"..."bZ  //  If the result is falsy (NaN), instead return the index of Z in this string.
          //  C produces 0, D -> 2, E -> 4, F -> 5, G -> 7, A -> 9, B -> 11.
          //  # -> 1, and b -> -1, so we don't need to calculate them separately.
/C        //  Divide the index by 12.
x         // Sum.
2p        // Take 2 to the power of the result.
55*       // Multiply by 55.

Test durumları

Geçerli tüm test durumları iyi sonuçlandı. Garipleşen geçersiz olanlar ...

input --> output       (program's reasoning)
A0  --> 27.5           (Yep, I can do that for you!)
C4  --> 261.625565...  (Yep, I can do that for you!)
F#3 --> 184.997211...  (Yep, I can do that for you!)
Bb6 --> 1864.6550...   (Yep, I can do that for you!)
A#6 --> 1864.6550...   (Yep, I can do that for you!)
A4  --> 440            (Yep, I can do that for you!)
D9  --> 9397.27257...  (Who says that's too high?)
G0  --> 24.49971...    (I've heard that note before.)
Fb5 --> 659.25511...   (Wait, Fb isn't supposed to be a note?)
E   --> 69.295657...   (I'm gonna guess that the missing octave is 1¾.)
b2  --> 61.735412...   (I assume that b means Cb...)
H#4 --> 261.625565...  (H# is C!)

13
+ ¾ using :) kullandığınız için
anatolyg

1
Bu aslında 38 bayt değil mi?
Patrick Roberts,

@PatrickRoberts Bu UTF-8'deki 38 bayttır, ancak Japt her karakterin tam olarak bir bayt olduğu ISO-8859-1 kodlamasını kullanır .
ETHProductions

8

Pyth, 46 44 43 42 39 35 bayt

*55^2tsm.xsdc-x"C D EF GbA#B"d9 12z

Çevrimiçi deneyin. Test odası.

Kod şimdi ETHproductions'un Japt cevabına benzer bir algoritma kullanıyor , bu yüzden ona kredi ver .

açıklama

                                            implicit: z = input
       m                          z         for each character in input:
          sd                                  try parsing as number
        .x                                    if that fails:
               "C D EF GbA#B"                   string "C D EF GbA#B"
              x              d                  find index of character in that
             -                9                 subtract 9
            c                   12              divide by 12
      s                                     sum results
     t                                      decrement
   ^2                                       get the correct power of 2
*55                                         multiply by 55 (frequency of A1)

Eski versiyon (42 bayt, 39 w / paketli dize)

*55^2+tsezc+-x"C D EF G A B"hz9-}\#z}\bz12

açıklama


Bu ilginç. Pyth paketi dizeleri nasıl?
Luis Mendo,

@LuisMendo Bununla ilgili bilgileri belgelerde bulabilirsiniz . Temel olarak, verileri dönüştürmek için en küçük üssü bulur ve sonucu taban
256'da

7

Mathematica, 77 bayt

2^((Import[".mid"~Export~Sound@SoundNote@#,"RawData"][[1,3,3,1]]-69)/12)440.&

Açıklama :

Bu işlevin ana fikri, not dizesini göreceli perdesine dönüştürmek ve sonra frekansını hesaplamaktır.

Kullandığım yöntem sesi ham veriyi midi ve içe aktarmak için dışa aktarmaktır, ancak daha şık bir yol olduğundan şüpheleniyorum.


Test durumları :

f=%; (* assign the function above to f *)
f["A4"]    (* 440.    *)
f["A5"]    (* 880.    *)
f["C#-1"]  (* 8.66196 *)
f["Fb4"]   (* 329.628 *)
f["E4"]    (* 329.628 *)
f["E"]     (* 329.628 *)

2
Genelde sorunları önemsizce çözen Mathematica yapılarını gördüğüm için üzgünüm, ama bu aslında bunu yapmak için oldukça ilham verici bir yol.
Robert Fraser,

4

MATL , 56 53 50 49 48 bayt

Hj1)'C D EF G A B'=f22-'#b'"G@m]-s+ 12/G0)U+^55*

Bu zorluktan daha önceki olan geçerli sürümü (10.1.0) kullanır .

Çevrimiçi deneyin !

açıklama

H                   % push 2
j1)                 % get input string. Take first character (note)
'C D EF G A B'=f    % find index of note: 1 for C, 3 for D...
22-                 % subtract 22. This number comes from three parts:
                    % 9; 1 for 0-based indexing; 12 to subtract 1 octave
'#b'"G@m]-s         % For loop. Gives 1 if input contains '#', -1 if 'b', 0 otherwise
+                   % add to previous number. Space needed to separate from next literal
12/                 % divide by 12
G0)                 % push input and get last character (octave)
U+                  % convert to number and add to previous number
^                   % raise 2 (that was initially pushed) to accumulated number 
55*                 % multiply by 55 (=27.5*2). Implicitly display


3

Ruby, 69 65

->n{2**((n.ord*13/8%12-n.size+(n=~/#/?7:5))/12.0+n[-1].to_i)*55/4}

Test programında Ungolfed

f=->n{
  2**(                    #raise 2 to the power of the following expression:
   (
     n.ord*13/8%12-       #note name C..B maps to number 0..11 calculated from the ascii code of n[0] 
     n.size+(n=~/#/?7:5)  #Correction for flat: length of n is 1 more for flat (or sharp) than for natural. Then apply correction for sharp
                          #now we have a number 3..14 for C..B (so 12 for A, will be a whole number when divided)
   )/12.0+                #divide by 12 to convert into a fraction of an octave

  n[-1].to_i              #add the octave number, last character in n
  )*                      #end of power expression, now we have A0=2,A1=4,A2=4 etc

  55/4                    #multiply to get correct frequency, this is shorter than 13.75 or 440/32                      
}

#complete octave test case
puts %w{A0 A#0 Bb0 B0 C1 C#1 Db1 D1 D#1 Eb1 E1 F1 F#1 Gb1 G1 G#1 Ab1 A1 A#1}.map{|e|[e,f[e]]}

#test case per OP
puts %w{A0 C4 F#3 Bb6 A#6}.map{|e|[e,f[e]]}

Çıktı

A0
27.5
A#0
29.13523509488062
Bb0
29.13523509488062
B0
30.867706328507758
C1
32.70319566257483
C#1
34.64782887210901
Db1
34.64782887210901
D1
36.70809598967595
D#1
38.890872965260115
Eb1
38.890872965260115
E1
41.20344461410875
F1
43.653528929125486
F#1
46.2493028389543
Gb1
46.2493028389543
G1
48.999429497718666
G#1
51.91308719749314
Ab1
51.91308719749314
A1
55.0
A#1
58.27047018976123
A0
27.5
C4
261.6255653005986
F#3
184.9972113558172
Bb6
1864.6550460723593
A#6
1864.6550460723593

2

ES7, 82 bayt

s=>55*2**(+s.slice(-1)+("C D EF G A B".search(s[0])+(s[1]<'0')-(s[1]>'9')-21)/12)

Beklendiği gibi "B # 2" girişinde 130.8127826502993 değerini döndürür.

Düzenleme: @ user81655 sayesinde 3 bayt kaydedildi.


@ user81655 2*3**3*2, Firefox'un tarayıcı konsolunda bulunan ve aynı fikirde olduğu 108 2*(3**3)*2. Ayrıca, bu sayfanın ?:, öncekinden daha yüksek önceliğe sahip olduğunu =ancak aslında eşit önceliğe sahip olduğunu da unutmayın (dikkate alın a=b?c=d:e=f).
Neil

Ah tamam. Firefox'um yok, **bu yüzden hiç test edemedim. Sanırım ?:örneğinizde olduğundan daha yüksek önceliğe sahip, =çünkü örneğinizde aüçlünün yerine daha bsonra üçlünün sonucuna ayarlanmış . Diğer iki ödev üçlü içine alınmıştır, bu yüzden özel bir durumdur.
user81655 15

@ user81655 e=fÜçlü içindeki nasıl ?
Neil

Düşünün a=b?c=d:e=f?g:h. Aynı önceliğe sahiplerse ve ilk üçlü daha =sonra biterse e, geçersiz bir sol el atama hatasına neden olur.
user81655

@ user81655 Ancak yine de ?:yüksek önceliğe sahip olsaydı, bu da bir problem olurdu =. İfadenin, öyleymiş gibi gruplanması gerekir a=(b?c=d:(e=(f?g:h))). Aynı önceliğe sahip değilse, bunu yapamazsınız.
Neil

2

C, 123 bayt

float d(char*s){int n=*s++,m=(n*12+(n<67?90:6))/7,o=*s++,a=o^35?o^98?0:-1:1;return exp((m+(a?*s++:o)*12+a)/17.3123-37.12);}

Kullanımı:

#include <stdio.h>
#include <math.h>

float d(char*s){int n=*s++,m=(n*12+(n<67?90:6))/7,o=*s++,a=o^35?o^98?0:-1:1;return exp((m+(a?*s++:o)*12+a)/17.3123-37.12);}

int main()
{
    printf("%f\n", d("A4"));
}

Hesaplanan değer her zaman kesin değerden yaklaşık 0,8 kuruş daha azdır, çünkü kayan nokta sayılarından mümkün olduğu kadar çok sayı keserim.

Koda genel bakış:

float d(char*s){
    int n=*s++,        // read the letter
        m=(n*12+       // multiply by 12/7 to convert from A...G to 0...11
        (n<67?90:6)    // if A or B, add 1 octave; also add some fix-up rounding value
        )/7,

        o=*s++,        // read next char: the octave digit or accidental

        a=o^35?o^98?0:-1:1; // if accidental, convert it into +1 or -1; else 0

        return exp((m+ // I adjusted the factors to use exp instead of pow
            (a?*s++:o) // if was accidental, now read the octave digit
            *12+a)/
            17.3123-   // a more exact value is 17.3123404447
            37.12);    // a more exact value is 37.1193996632
}

1

R, 157 150 141 136 bayt

f=function(x){y=strsplit(x,"")[[1]];55*2^(as.double(y[nchar(x)])-1+(c(10,12,1,3,5,6,8)[LETTERS==y[1]]-switch(y[2],"#"=9,"b"=11,10))/12)}

Girinti ve yeni satırlarla:

f=function(x){
     y=strsplit(x,"")[[1]]
     55 * 2^(as.double(y[nchar(x)]) - 1 + 
         (c(10,12,1,3,5,6,8)[LETTERS==y[1]] - 
         switch(y[2],"#"=9,"b"=11,10))/12)
     }

Kullanımı:

> f("A0")
[1] 27.5
> f("C8")
[1] 4186.009
> sapply(c("C4","Bb6","A#6","A4"),f)
       C4       Bb6       A#6        A4 
 261.6256 1864.6550 1864.6550  440.0000 

1

Python, 97 95 bayt

def f(n):a,*b,c=n;return 2**(int(c)+('C@D@EF@G@A@B'.find(a)-(21,(22,20)['#'in b])[b>[]])/12)*55

Pietu1998'in (ve diğerlerinin) eski 'C@D@EF@G@A@B'boş bir karakter ya da bir başkası için dizedeki notun indeksini aramaya yönelik eski yaklaşımı temel alınmıştır . Not dizesini koşulsuz ayrıştırmak için yinelemeli paket açma kullanıyorum. Sonunda dönüşüm ifadesini basitleştirmek için biraz cebir yaptım. Yaklaşımımı değiştirmeden kısaltabilir miyim bilmiyorum.


1
Ben ve için b==['#']kısaltılabileceğini düşünüyorum . '#'in bnot bb>[]
Zgarb

Güzel puanlar! Test takımım için çalışıyor, teşekkürler. Python'daki şart koşularında golf oynamayı oldukça geliştirebileceğimi düşünüyorum.
Ogaday

1

Wolfram Dili (Mathematica), 69 bayt

ToExpression@("Music`"<>StringReplace[#,{"b"->"flat","#"->"sharp"}])&

Bir ifadeyi yalnızca bir not olarak girme sıklığını değerlendiren müzik paketini kullanmak, şöyle:

 In[1]:= Eflat3
Out[1]:= 155.563

İle paketi almak için kaçınarak bayt kaydetmek için <<Music, ben tam isimleri kullanıyorum: Music`Eflat3. Ancak, ben yine de değiştirmek zorunda bolan flatve #birlikte sharpbir basit ilgisi sorusuna, giriş formatını eşleştirmek için StringReplace.

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.