このメモの頻度は?


21

クイックミュージックリフレッシャー:

ピアノの鍵盤は88音で構成されています。各オクターブには、12の音符がC, C♯/D♭, D, D♯/E♭, E, F, F♯/G♭, G, G♯/A♭, A, A♯/B♭ありBます。「C」を押すたびに、パターンは1オクターブ高くなります。

ここに画像の説明を入力してください

メモ一意キーボードの0〜8〜第3音の数は1)任意のシャープまたはフラットを含む文字、および2)オクターブによって識別されているA0, A♯/B♭B0。この後、オクターブ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♭1とのフルクロマチックスケールが続きますB1。この後、オクターブ2、3、4、5、6、および7のフルクロマティックスケールが続きます。その後、最後の音符はになりC8ます。

各音は20〜4100 Hzの範囲の周波数に対応しています。A0正確27.500ヘルツから始まる、それぞれ対応するノートは、二つの、又は略1.059463の第十二回ルート前のノートです。より一般的な式は次のとおりです。

ここに画像の説明を入力してください

ここで、nはノートの番号で、A0は1です(詳細はこちら)。

チャレンジ

メモを表す文字列を取り込み、そのメモの頻度を出力または返すプログラムまたは関数を作成します。#シャープ記号(または、Younginsのハッシュタグ)にはポンド記号を使用bし、フラット記号には小文字を使用します。すべての入力は(uppercase letter) + (optional sharp or flat) + (number)空白なしで表示されます。入力がキーボードの範囲外(A0未満またはC8を超える)であるか、無効な文字、欠落文字、または余分な文字がある場合、これは無効な入力であり、処理する必要はありません。また、E#やCbなどの奇妙な入力を取得しないと安全に想定できます。

精度

無限の精度は実際には不可能なので、真の値の1セント以内であれば何でもかまいません。余分な詳細に進むことなく、セントは2の1200のルート、つまり1.0005777895です。具体例を使用して、より明確にします。入力がA4だったとします。この音の正確な値は440 Hzです。一度セントフラットです440 / 1.0005777895 = 439.7459。一度セントシャープになると、440 * 1.0005777895 = 440.2542したがって、439.7459より大きく440.2542より小さい数値であれば、十分に正確にカウントできます。

テストケース

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.

無効な入力を処理する必要がないことに注意してください。プログラムが実際の入力のふりをして値を出力する場合、それは受け入れられます。プログラムがクラッシュした場合、それも許容できること。あなたがそれを手に入れると、何でも起こります。入力と出力の完全なリストについては、このページを参照してください

いつものように、これはコードゴルフなので、標準の抜け穴が適用され、バイト単位の最短回答が勝ちます。


9
「H#4-> Hは実際の音ではなく、無効な入力です。」ヨーロッパを除く。
ルイ

6
@Luiヨーロッパ全体が使っているHかのように、ヨーロッパについてこのことは何ですか?HBはドイツ語圏でのみ使用されるAFAIKを意味します。(ここBでBbを意味します。)イギリス人とアイルランド人がBを呼ぶものは、スペインとイタリアでSiまたはTiと呼ばれます。DoRe Mi Fa Sol La Siのように。
レベル川セント

3
ビオラでB♯2を演奏したことがありますが、これは完全に合理的な音であり、まったく変ではありません。
ニール

3
@steveverrillはHによると、ドイツ、チェコ、スロバキア、ポーランド、ハンガリー、セルビア、デンマーク、ノルウェー、フィンランド、エストニア、オーストリアで使用されているウィキペディア。(フィンランドでも確認できます。)
PurkkaKoodari

6
@Neilそれはたぶん偶然だった。;)
ビーカー

回答:


21

Japt、41 37 35 34バイト

ようやく¾使えるようになりました!:-)

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

オンラインでお試しください!

使い方

          // 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.

テストケース

すべての有効なテストケースは正常に処理されます。奇妙なのは無効なものです...

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
+¾¾:)使用する
anatolyg

1
これは実際には38バイトではありませんか?
パトリックロバーツ

@PatrickRobertsこれはUTF-8では38バイトですが、JaptはISO-8859-1エンコーディングを使用します。このエンコーディングでは、各文字は正確に1バイトです。
-ETHproductions

8

Pyth、46 44 43 42 39 35バイト

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

オンラインでお試しください。 テストスイート。

コードはETHproductionsのJapt answerと同様のアルゴリズムを使用するようになりました。

説明

                                            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)

古いバージョン(42バイト、39パック文字列)

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

説明


これは面白い。Pythは文字列をどのようにパックしますか?
ルイスメンドー

@LuisMendoこれに関する情報はdocsにあります。基本的に、それはにデータを変換するための最小のベースを見つけ、その後、ベース256に結果をコード
PurkkaKoodari

7

Mathematica、77バイト

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

説明

この関数の主なアイデアは、音符の列を相対的なピッチに変換し、その周波数を計算することです。

私が使用する方法は、サウンドをMIDIにエクスポートし、生​​データをインポートすることですが、もっとエレガントな方法があると思います。


テストケース

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
通常、問題を簡単に解決するMathematicaビルトインを見るのは悲しいですが、これは実際にはかなり刺激的な方法です。
ロバートフレイザー

4

MATL56 53 50 49 48バイト

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

現在のリリース(10.1.0)を使用します。これは、この課題よりも前のものです。

オンラインでお試しください

説明

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

ルビー、69 65

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

テストプログラムでゴルフをしていない

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]]}

出力

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バイト

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

期待どおりに「B#2」の入力で130.8127826502993を返します。

編集:@ user81655のおかげで3バイトを保存しました。


@ user81655 2*3**3*2は、Firefoxのブラウザーコンソールで108であり、に同意し2*(3**3)*2ます。また、そのページには、?:それよりも高い優先順位があります=が、実際には同等の優先順位があると考えられていることに注意してください(考慮a=b?c=d:e=f)。
ニール

ああ、わかった。私のFirefoxにはない**ので、テストすることはできませんでした。あなたの例では、三項を実行するのではなく、三項の結果に設定されているため?:、より高い優先順位を持っていると思い=ます。他の2つの割り当ては3進数で囲まれているため、特別なケースです。ab
user81655

@ user81655 e=f三元の内部はどうですか?
ニール

検討してくださいa=b?c=d:e=f?g:h。それらが同じ優先順位であり、最初の3項が=after eで終了した場合、無効な左代入エラーが発生します。
user81655

@ user81655しかし?:=とにかく優先度が高ければ、それも問題になります。式は、あたかもグループ化する必要がありa=(b?c=d:(e=(f?g:h)))ます。優先順位が同じでない場合、それはできません。
ニール

2

C、123バイト

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);}

使用法:

#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"));
}

浮動小数点数から可能な限り多くの桁を切り取るため、計算値は常に正確な値よりも約0.8セント小さくなります。

コードの概要:

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バイト

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

インデントと改行あり:

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

使用法:

> 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バイト

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(およびその他)の、古い'C@D@EF@G@A@B'空白文字などの文字列内のノートのインデックスを検索する古いアプローチに基づいています。反復可能なアンパックを使用して、条件なしでノート文字列を解析します。変換式を簡素化するために、最後に少し代数をしました。アプローチを変えずに短くすることができるかどうかわからない。


1
私が考えるb==['#']に短縮することができ'#'in b、およびnot bb>[]
Zgarb

ナイスポイント!テストスイートで動作します、ありがとう。おかげで、Pythonで条件付きゴルフをかなり改善できると思います。
-Ogaday

1

Wolfram言語(Mathematica)、69バイト

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

次のように、式として音符を入力するだけでその頻度を評価する音楽パッケージを使用します

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

パッケージのインポートを回避してバイトを節約するには <<Musicには、完全修飾名を使用しますMusic`Eflat3。しかし、私はまだ交換する必要がbflat#してsharp、私はシンプルで何の問題、の入力形式を一致させますStringReplace

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.