2016-08-22 2 views
0

私は配列の各部分で最大の整数を強制しながら、整数の配列で数学を実行しようとしています。これと同じように:整数の配列で数式を計算するとき、どのようにロールオーバーするのですか?

function add($amount) { 
    $result = array_reverse([0, 0, 0, 100, 0]); 
    $max = 100; 

    for ($i = 0; $i < count($result); ++$i) { 
    $int = $result[$i]; 
    $new = $int + $amount; 
    $amount = 0; 

    while ($new > $max) { 
     $new = $new - $max; 
     ++$amount; 
    } 

    $result[$i] = $new; 
    } 

    return array_reverse($result); 
} 

add(1); // [0, 0, 0, 100, 1] 
add(100); // [0, 0, 0, 100, 100] 
add(101); // [0, 0, 1, 0, 100] 

これ以上の整数を追加すると動作が遅くなります。私はビット単位のシフトでこれをやろうとしてきましたが、近づいてきましたが、何らかの理由で動作させることができません。私は第三者の視点が必要だと思う。誰かがヒントを持っていますか?

+0

よく、1つの簡単な最適化:無意味な配列逆転を停止します。 'for($ i = count(...); $ i> 0; $ i - )' –

答えて

0

min($max, $number)を使用して$number$maxに限定する。

for ($i = 0; $i < count($result); ++$i) { 
    $result[$i] = min($max, $result[$i] + $amount); 
} 
+0

いいえ、それは '++ 'でなければなりません。 $ i'、ちょうど質問のように。ちょうどタイプミス。 – Barmar

1

大部分を占める部分はwhileループです。 100を超える値が得られるまで、値を繰り返し減らしています。しかし、PHPを使ってループを起こすと、膨大な時間がかかります(私のローカルマシンでは20秒以上で12桁の整数がカウントされます)。代わりに、乗算と除算を使用します(ifと一緒に)。それはより速いです。同じ12桁の整数は、このコードを完了するために、秒未満を取った:

function add($amount) { 
    $result = array_reverse([0, 0, 0, 100, 0]); 
    $max = 100; 

    for ($i = 0, $size = count($result); $i < $size; ++$i) { 
     $int = $result[$i]; 
     $new = $int + $amount; 
     $amount = 0; 

     if($new > $max) { 
      $remainder = $new % $max; 
      // Amount is new divided by max (subtract 1 if remainder is 0 [see next if]) 
      $amount = ((int) ($new/$max)); 
      // If remainder exists, new is the the number of times max goes into new 
      // minus the value of max. Otherwise it is the remainder 
      if($remainder == 0) { 
       $amount -= 1; 
       $new = $new - ((($new/$max) * $max) - $max); 
      } else { 
       $new = $remainder; 
      } 
     } 

     $result[$i] = $new; 
    } 

    return array_reverse($result); 
} 

はまた、私は、forループの変数の初期化セクションにあなたの count($result)コールを移動していることに注意してください。式セクションの中にあるとき、それはforループが繰り返されるたびに実行されます。これは関数を実行する全体的な時間にも追加できます。

このような数学的な変化が大きい場合、アウトライアーがないことを確実にするために計算すると期待される値の範囲をアサートすることもできます。私は小さい範囲をして、彼らはすべて同じように出てきましたが、私はあなた自身を実行することをお勧めします。

+0

これは、ロールオーバーを正しく処理しません。私が 'add(400);を実行すると、' [0、0、0、101、145] 'を得るでしょう。 – Dustin

+0

@Dustin - あなたは別の関数を使用していますか?私はあなたの機能と鉱山の設定を持って、別のものを実行しています。値として400を実行すると、両方から '[0、0、1、3、100]'を取得します。 – Jim

関連する問題