文字列のチューニング


9

仕事

所定の周波数にチューニングされ、所定のポイントで押し下げられたストリングの、チューニングのずれたセント数とともに、発音されたノートを決定するプログラムを記述します。

簡単にするために、生成される音の周波数と、押された場所の右側の弦の長さが反比例していると仮定します。

注:このタスクでは、基音のみを扱い、倍音やその他の倍音は扱いません。

入力

プログラムには2つのデータが渡されます。

  • 問題の文字列を表す、任意の長さの文字列。このストリングは、ストリングが押されるべきXでマークされます。

    [-----] is a string divided in six sections (five divisions).
    [--X--] is a string pressed at the exact center of the string.
    [X----] is a string pressed at 1/6 the length of the string. (Length used is 5/6)
    [-X--] is a string pressed at 2/5 of the length of the string. (Length used is 3/5)
    

    文字列のの右側の部分を使用して音が鳴ると仮定しXます。

  • 数値(必ずしも整数ではない)。文字列がチューニングされる頻度を示します。この数値の精度は、小数点以下最大4桁です。

渡された周波数が間にあるだろうと仮定することができる10 Hz40000 Hz

入力は任意の形式で渡すことができます。回答には、プログラムへの入力の受け入れ方法を指定してください。

出力

プログラムは、12トーンの平均律チューニングシステムで最も近い音符*と、弦で示される音が最も近い音符から離れたセントの数(最も近いセントに丸められる)の両方を出力する必要があります。

+nセントはn、ノートがシャープ/上にある-nセント、およびフラットがノートの下にある場合に使用します。

メモは科学的なピッチ表記で出力されます。A4がに調整されて440Hzいると仮定します。フラット/シャープなノートにはbと#を使用します。注:シャープまたはフラットのいずれかを使用できます。のメモは466.16HzA#またはのいずれかBbで出力されます。

出力に以前に指定された2つの情報のみが含まれている限り、出力の形式は自由です(つまり、可能なすべての出力を印刷することはできません)。

*最も近い音とは、入力によって示される音に最も近い音を指し、セント単位で測定されます(したがって、50 cents音の中にある音)。サウンドが50 cents2つの異なるノートから離れている場合(丸め後)、2つのノートのどちらかが出力される可能性があります。

プログラムは、以下の例だけでなく、すべてのケースで機能するはずです。

Output             Input Frequency   Input String
A4,  +0  cents     220               [-----X-----]
A5,  +0  cents     220               [--------X--]
D5,  -2  cents     440               [--X--------]
B4,  -49 cents     440               [X----------]
A#4, +19 cents*    314.1592          [X-]
Eb9, +8  cents*    400               [-----------------------X]
Eb11,+8  cents*    100               [--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------X]
D#1, +49 cents*    10                [--X]
A0,  -11 cents     11.7103           [---X--]

*シャープまたはフラットのどちらかが出力された可能性があります。

役立つ可能性のあるリンク

これはので、最も短い答えが優先されます。


あなたの例は少し矛盾していると思います:最初の例によると、[--X--]ストリングが配置されているディビジョンの中央で押されていますがx[-X--]このロジックに従うと、最後の例は3/8(2/5ではありません)になります。または私は何か間違ったことを理解していますか?
flawr 2014

最後の1つは@flawr [-X--]で、文字列は4か所で(したがって5つの部分に)分割され、これらの2番目の分割で押されます。したがって、それはで押され2/5、使用される長さは3/5です。
es1024 2014

わかりました。わかりました。それぞれが-基本的に部門の位置を表しています。説明していただきありがとうございます。
Flawr 2014

回答:


1

BBCベーシック、161#

  REM get frequency and string. Store length of string in n for later.
  INPUT f,s$
  n=LEN(s$)

  REM store floating-point value of note in semitones above (C0-0.5). Store integer value in n% (offset effectively means it will be rounded not truncated.)
  n=LN(f*(n-1)/(n-INSTR(s$,"X"))/15.8861)/LN(2)*12
  n%=n

  REM format printing to whole numbers only
  @%=2^17

  REM Output note name and octave. Output cents (discrepancy between n and n%, minus the offset of 0.5)
  PRINT MID$("C C#D D#E F F#G G#A A#B ",n%MOD12*2+1,2);INT(n/12)'(n-0.5-n%)*100'

スコアはコメントを除外します。まだゴルフをしていません。

出力

2つの長いものを除くすべてのテストケースで正しく実行されます。以下のためEb9には、テストケースから抜けて1つのダッシュがあるようです:22あります-し、1 X24等分に文字列を分割し、。私の手動計算によると、これは9600Hzで、D9を37セント上回っています。これはまさに私のプログラムが出力するものです。別のダッシュを追加すると、Eb9 + 8セントになります。残念ながら、BBC Basicは255文字を超える文字列を処理できないため、Eb11大文字と小文字はエラーになります。

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


3

C、179

main(n,d){float f;scanf("%*[^X]%nX%*[-]%n]%f",&n,&d,&f);f=log(f*d/(d-n))*17.3123-57.376;n=d=f+.5;n=n%12*7+784;printf("%c%d%c,%+2.0f cents\n",n/12,(d+9)/12,n%12/7*3+32,(f-d)*100);}

単独でライン上のアスキー画像を受け取り、別のラインで周波数を受け取ります。

マジックナンバー17.3123との精度を下げることで、いくつかのキャラクターを落とすことができます57.376

ゴルフをしなければ、プログラムは次のようになります。

main(n,d)
{
    float f; // 'float' and '%f' better than 'double' and '%lf'

    scanf("%*[^X]%nX%*[-]%n]%f", &n, &d, &f);
    // n is the number of chars before 'X'
    // d is the number of chars before ']'
    // f is the frequency

    // Calculate the tuned frequency
    f = f * d / (d - n);

    // Convert the frequency to logarithmic scale, relative to pitch A0
    f=log(f)*17.3123-57.376;
    // alternatively: f = log2(f / (440 / 16)) * 12;

    // Round to nearest integer
    n=d=f+.5;

    // Calculate the note name ('A', 'B', etc), multipled by 12 for convenience
    n=n%12*7+784;

    printf("%c%d%c,%+2.0f cents\n", // output example: B4 ,-49 cents
        n/12,        // note name
        (d+9)/12,    // octave number
        n%12/7*3+32, // if n%12 is large enough, it's '#' else ' ' (natural)
        (f-d)*100);  // number of cents; stdio rounds it to integer
}

2
素晴らしいscanfフォーマット文字列の+1 。あなたがそれができるとは思いもしませんでした。私は後であなたに出力コードをチェックします(私はCで、同様の何かが出力のために私に起こったけれども、私は競争力の全部を行う方法を見ることができなかった。このことについて考えた。)私は仮定d+9あなたがインデックス化しているためでありますノートAなので、オクターブ番号をノートCのインデックスに合わせる必要があります。それを回避する方法はあるのでしょうか。
Level River St

はい、+ 9はオクターブがCで始まるという事実を補正します。それはそれか、またはノート名の計算に同様の修正を加えることです。ノート名の場合、循環シフトはLUTで実装できますが、より「数学的な」方法で計算するのが好きです。
anatolyg 2014

1

JavaScript(199)

たとえば、 t('[X-]',314.1592)

t=(s,f)=>{l=s.length-1;p='C C# D D# E F F# G G# A B H'.split(' ');n=12*Math.log2(f*l/(l-s.indexOf('X'))/16.3515978);m=n+.5|0;return p[m%12]+(n/12|0)+' '+((n-m)*100+.5|0)}

修繕。(私はヨーロッパに住んでいるので、B =の代わりにBとHの代わりにBを使用しました)


フラー、ドイツ人?私はいつもBとHをヨーロッパの表記ではなくドイツの表記と考えていました。英国とアイルランドはBbとBを使用します。スペインとイタリアはSIbとSIを使用します(DO RE MI FA SOL LA SIなど)。とにかく、それは1文字の節約だけです。
Level River St

はい、私はドイツ語圏の国を形成しています。他のヨーロッパ諸国がそのドレミシステムを使用していることは知りませんでした(私は人々が子供の教育でそれを使用するのを聞いただけです)。とにかく、あなたが言ったように1文字しか節約せず、要件を実際には満たしていないため、それは主に冗談でした=)
flawr

これは、セントの数が負である(例えば、場合誤っセントの数を丸めるように思われるt('[---X--]',11.7103)(最後の例)を与える-10代わりに-11
es1024

を使用p="C0C#0D0D#0E0F0F#0G0G#0A0B0H".split(0)すると、さらに2文字節約できます。
Sean Latham 2014

@ es1024ああ、知っておくべきround(x) = x+.5|0でした。正の数に対してのみ正しい丸め関数を実装したためです。後で修正します。@ipiありがとう!
flawr 2014

1

Python 3:175

import math
def t(b,s):l=len(s)-1;n=12*math.log2(b*l/(l-s.index("X"))/16.35);m=round(n);return"%s%s%+d"%(("C C# D D# E F F# G G# A A# B".split()*99)[m],m//12,round(100*(n-m)))

非ゴルフ:

import math

c0 = 16.35

def tuning (base_frequency, string):
    return formatted (note_number (frequency (base_frequency, string)))

def formatted (note_number):
    return "{name}{octave:d}{cents:+d}".format (name=note_name (note_number),
                             octave=octave (note_number),
                             cents=cents_out (note_number))

def note_name (note_number):
    return ("C C# D D# E F F# G G# A A# B".split() * 99)[round (note_number)]

def note_number (frequency):
    return 12 * math.log2 (frequency / c0)

def octave (note_number):
    return round (note_number) // 12

def cents_out (note_number):
    return round (100 * (note_number - round (note_number)))

def frequency (base_frequency, string):
    string_length = len (string) - 1
    held_length = string_length - string.index ("X")
    return base_frequency * string_length / held_length

if "__main__" == __name__:

    print ("Testing functions against known values...")
    assert "A4+0"     == tuning (220,      "[-----X-----]")
    assert "A5+0"     == tuning (220,      "[--------X--]")
    assert "D5-2"     == tuning (440,      "[--X--------]")
    assert "B4-49"    == tuning (440,      "[X----------]")
    assert "A#4+19"   == tuning (314.1592, "[X-]")
    assert "D#9+8"    == tuning (400,      "[-----------------------X]")
    assert "D#11+8"   == tuning (100,      "[--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------X]")
    assert "D#1+49"   == tuning (10,       "[--X]")
    assert "A0-11"    == tuning (11.7103,  "[---X--]")
    print ("Tests passed.")
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.