2

ギターの 6 つの弦を一連の範囲として表す PHP アプリケーションを作成しています。このようにして、一連の数値を加算または減算して、定義した典型的な構造を体系的に変更できます。

範囲は次のとおりです。

//E: 1-15, A: 26-40, D: 51-65, G: 76-90, b: 101-115, e: 126-140 

以下のコードに問題があります。

関数

//the key of the key value pair represents its position on the guitar, and the value 
//represents a theoretical function. If the inversion is "0", do nothing. If the 
//inversion is "1", all notes that have the value of "r" should have their key 
//incremented by 4 and their value changed to '3'. 

//example: 1=>"r",28=>"5",52=>"7",77=>"3"
function invChange($pattern, $inversion) {  
    if ($inversion == 1) {
        foreach ($pattern as $position => $function) {
            if ($function == 'r' ) { $position += 4; $junction = '3'; }
            if ($function == '3' ) { $position += 3; $junction = '5'; }
            if ($function == '5' ) { $position += 4; $junction = '7'; }
            if ($function == '7' ) { $position += 1; $junction = 'r'; }
            $modScale[$position] = $junction; 
        }
    }
    if ($inversion == 2) {
        foreach ($pattern as $position => $function) {
            if ($function == 'r' ) { $position += 7; $junction = '5';}
            if ($function == '3' ) { $position += 7; $junction = '7';}
            if ($function == '5' ) { $position += 5; $junction = 'r';}
            if ($function == '7' ) { $position += 5; $junction = '3';}
            $modScale[$position] = $junction; 
        }
    }
    if ($inversion == 3) {
        foreach ($pattern as $position => $function) {
            if ($function == 'r' ) { $position += 11; $junction = '7';}
            if ($function == '3' ) { $position += 8; $junction = 'r';}
            if ($function == '5' ) { $position += 9; $junction = '3';}
            if ($function == '7' ) { $position += 8; $junction = '5';}
            $modScale[$position] = $junction; 
        }
    }
    return $modScale;
}

ご覧のとおり、これは非常に反復的です。このコードを見るだけで、もっと良い方法が必要だと思います。私が必要としているのは、無限線形の方法で配列を使用することだと思います:

array("root" => 4, "third" => 3, "fifth" => 4, "seventh" => 1); 

ここで、定義済みの $note => $offset ペアのいずれかを取得し、この配列を 1、2、または 3 回ジャンプさせる必要があります。たとえば、ルートとして開始し、1 つのジャンプを行う場合、4 を追加して「3 番目」にし、その値を「3 番目」に変更する必要があります。しかし、ルートとして開始して 2 回ジャンプする場合は、4 を加算し、3 を加算してから、その値を「5 番目」に変更する必要があります。

4

1 に答える 1

1

TL;DR;

ええと.. 数学でそれを行うことができます。さらに、あなたが提供した制限により、実際には1 つの関数で実行できます。二次関数。

やり方

あなたがする必要があるのは、何らかの方法で数学関数を作成することです。これは、反転を引数として取り、特定の「関数」によって特定の位置を返します (PHP 関数内でどのように呼び出されるか)。「反転」には3つの値があるため、二次関数でこれを行うことができます:

f(x) = ax 2 + bx + c

aここでは、係数、b、およびcを特定のx値 ($inversionケースの場合) と関数値 (各「反転」ifブロックの「位置」の値) で見つける必要があります。

ただし、「関数」 (ブロック内) ごとに 4 つの異なる位置スイッチがあります。foreachそのため、実際には、4 つの二次関数を処理する必要があります。

さて、ジャンクションについて。論理的な意味でそれが何であるかはわかりませんが、確かに、依存関係は明らかです。すべての可能なジャンクションの配列を考えると、特定の「関数」の値は位置「現在」+「反転」のジャンクションです。したがって、接合配列['r', '3', '5', '7']が である場合、反転が1で電流が3の場合、結果は になります5。反転が2の場合、結果は7e tcになります。

そしてコード

どうぞ:

function invChangeN($pattern, $inversion)
{
   $junc = ['r', '3', '5', '7'];
   $pos  = [
      'r' => [ 1, 7, 14],
      '3' => [-3, 5, 14],
      '5' => [ 3, 5, 10],
      '7' => [-1, 7, 10]
   ];
   $inversion -= 2;
   $modScale   = [];
   foreach ($pattern as $p => $f)
   {
      $p += ($pos[$f][0]*pow($inversion,2) + $pos[$f][1]*$inversion + $pos[$f][2])/2;
      $j  = $junc[(array_search($f, $junc)+$inversion+2)%count($junc)];
      $modScale[$p] = $j; 
   }
   return $modScale;
}

ちょっと、なぜ私たちはやっているのですか$inversion -= 213 つの点を、2および3(元の反転値) から、-1および01転置するだけaです。bc

$pos各「関数」($fループ内)の二次関数の係数の配列が含まれています。線形方程式系を解決するため、それらはすべて「半分の整数」です (つまり、ビューを持っているため、W/2分数の分母は です2)。そのため、それらをすべて掛けて2、位置計算に 2 で除算を追加しました。

テスト

私はあなたの関数とこの新しい「数学」アナログのテストを行いました - もちろん成功した結果で、それはもちろん12および3のような反転です:

//derived from old function:
array(4) {
  [8]=>
  string(1) "5"
  [33]=>
  string(1) "r"
  [57]=>
  string(1) "3"
  [84]=>
  string(1) "7"
}
//derived from new function:
array(4) {
  [8]=>
  string(1) "5"
  [33]=>
  string(1) "r"
  [57]=>
  string(1) "3"
  [84]=>
  string(1) "7"
}

上記の結果は、パターン[1=>"r",28=>"5",52=>"7",77=>"3"]と反転の場合です2

于 2014-06-24T10:37:55.140 に答える