0

私は解決策を見つけました。以下の回答および/またはより新しい最適化があるGithub Gistを参照してください。

クレジット カードの請求額とバッチの合計の配列を取得しました...金額の SUM() がバッチの金額になる場合があるため、バッチにグループ化するのは簡単で、その日の預金に貢献するトランザクションをチェックすることができます。当座預金口座。

場合によっては、適切な合計がこれらの料金のサブセットであり、1 つ以上が翌日にバッチ処理されることがあります。これをプログラムで解決するのを手伝ってくれませんか? これは私の authorize.net バッチ アカウンティング用です。

+------------+--------+
| transId    | amount |
+------------+--------+
| 2863996511 | 154.00 |
| 2863992361 | 762.20 |
| 2863898975 |  49.00 |
| 2863894564 |   5.44 |
| 2863879671 |  10.88 |
| 2863858891 | 209.00 |
| 2863856334 | 148.00 |
| 2863367273 | -25.01 |
+------------+--------+

そして、その日のバッチの合計は $1302.63 です。よくあることですが、料金はそのバッチに収まらないため、バッチは配列内の料金の合計のサブセットです。この場合、$10.88 の請求は翌日のバッチに含まれていました。この小さな疑似コードは、ネストされた 2 つの for ループを介してそれをキャッチできます。

        for( $skipdx=0; $skipdx<$size; $skipdx++){
            $total=0;
            for( $idx=0; $idx<$size; $idx++){
                if($idx!=$skipdx){
                    $total+=$charges[$idx]['amount'];
                    $thisBatch[]=$charges[$idx]['transId'];
                }
                if( abs($total-$batch['total']) < .04 ) {
                    echo "sum of charges matches $date batch total: $$total  (line: ". __LINE__ .")\n";
                    $foundIt=TRUE;
                    break;
                }
            }
            if($foundIt==TRUE)
                break;
        }

TWO が追加されていない請求を動的に検索するにはどうすればよいですか? それから3つ?$skipdx1つの電荷が省略された場合、2 つの電荷がスキップされるとskip2dxネストされたループが追加されることがわかります。それでも見つからない場合は、skip3dx3 番目のレベルのネストになります。

私は通常、再帰まではアルゴリズムが得意ですが、その後はバカになります。

4

2 に答える 2

0

それは私に来ました!再帰の「現在のレイヤー」はこれを行います:

  1. 請求額を合計します。
  2. 一度に 1 つの料金を差し引いて、料金の配列を反復処理し、ターゲット バッチ量に対してテストします。
  3. この反復で金額が一致する場合は、この料金の ID を設定解除し、結果の配列を返します。
  4. 見つからない場合は、今回は現在の電荷を削除して、電荷の配列を再度繰り返します。同じ目標金額と新しい短縮配列を使用して関数を再度呼び出し、同じ関数に再度呼び出します。

作業コード ( Github にも新しい最適化があります):

$charges=Array(
     '2863996511' => 154.00 ,'2863879671' => 10.88
    ,'2863992361' => 762.20 ,'2863858891' => 209.00
    ,'2863898975' => 49.00  ,'2863856334' => 148.00
    ,'2863894564' => 5.44   ,'2863367273' => -25.01
); print_r($charges);
$targets=Array(1302.63, 1327.64, 1322.20 );
foreach( $targets as $batch ) {
    printf( "We seek combination of transIds to = $%-7.2f\n", $batch);
    $answer=reco( $batch, $charges );
    if( is_array($answer) )
        echo eval( "return ".implode("+",$answer).";" )."\nWIN!\n";
    else
        echo "Bust!\n";
}   

function reco( $target, $arr ){
    if( count($arr) < 2 )
        return FALSE;
    $killid='';
    $sum = eval( "return ".implode("+",$arr).";" );
    foreach( $arr as $id=>$amt ){
        if( abs($sum-$target-$amt) < .01 ) {
            $killid=$id;
            break;
        }
    }
    if( strlen($killid) > 1 ) {
        echo ".  omit $killid : ".$arr[$killid]."\n";
        unset($arr[$killid]); 
        return $arr;
    }
    foreach( $arr as $id=>$amt ){
        $tmp=$arr;
        unset($tmp[$id]);
        $rtn = reco( $target, $tmp );
        if( is_array($rtn) ) {
            echo ".. omit $id : ".$arr[$id]."\n";
            return $rtn;
        }
    }
    return FALSE;
}

そして出力:

We seek combination of transIds to = $1302.63
. omit 2863879671 : 10.88
1302.63
WIN!
We seek combination of transIds to = $1327.64
. omit 2863367273 : -25.01
.. omit 2863879671 : 10.88
1327.64
WIN!
We seek combination of transIds to = $1322.20
. omit 2863367273 : -25.01
.. omit 2863879671 : 10.88
.. omit 2863894564 : 5.44
1322.2
WIN!

パフォーマンスは大きな問題ではありません。約 1 秒で処理される再帰の第 3 レベルまで。

于 2013-02-06T09:18:29.717 に答える