私はExcelに精通していますが、Excelのすべての機能とデータツールに精通しているわけではありません。私の問題は、リスト上の多くの異なる番号の組み合わせであるスプレッドシート上の番号があることです。
例えば:
リストには、100、200、250、500、および1000が含まれ、説明する必要のある数は800です。
答えは500、200、100になります。
単純な数字の短いリストを頭の中で行うのは難しいことではありませんが、合計(になり、すべてが使用されるわけではない1500を超える通貨セル($ xxxx.xx)を扱っています。 、したがって、SUM
は役に立たない)-その合計を作成するために使用された数値を理解する必要があります(これは数式ではありません、ハードコードされた番号です)。
質問:合計を作成するためにどの数値を加算できるかを決定するまで、特定の範囲の数値を体系的に結合する関数またはVBAはありますか?
掘り下げてブルートフォースアルゴリズムを自分で書き始める前に知りたいだけです。
========
これを行うために作成したファイルへのリンク: https://drive.google.com/file/d/0B8nE67gSOkewWXR2WnRuQTc2MEU/view?usp=sharing
貢献してくださった皆様、ありがとうございました!
さて、私にとって最も効果的な解決策を見つけました:
最初、(Excelに組み込まれている9ビットではなく)バイナリの無限の文字列を作成できるvbaをいくつか見つけました。次に、このコードを使用して、この目的のためにUDFを作成しました... 20〜40「ビット」のチャンクで作業していたため、これは絶対に必要でした。
2番目、1ずつ増加するカウンターループを作成し、新しい数値を反映するようにバイナリ文字列を変更しました。 (1,10,11,100,101,110,111など)
第3、バイナリ文字列を分解し、その隣のセルの対応する番号に各1または0を割り当てる数式を作成しました。 (LEN()
、RIGHT()
、およびMID()
関数を使用して1と0を認識するだけです)。
第4、各値にその横の1または0を掛けてから、掛け算したすべての数値の合計を、探していた目標値と比較しました。
100%の確率で、クリーンなデータが与えられれば、解決策があればそれが見つかります。 (ただし、これは指数関数であるため、ほとんどの場合、時間が要因になります。したがって、ビットが多いほど、それらを循環するのに時間がかかります)
これは4分間で約300万の組み合わせで実行され、いくつかの要因に応じて与えるか取るか
ワークシートをやり直し、速度を2倍にしました。 5 それぞれが1ずつインクリメントされ、カウンターが1ではなく5ずつインクリメントされる列。
ExcelでSOLVER
を使用して結果を取得できます。
ADD-INS
でアクティブ化でき、DATA
タブに表示されます。
スプレッドシートを次のように設定します。
1つの列にチェックしたい数値のリストがあります次の列はすべてゼロ(0)3番目の列はFirst * Second(たとえば、100 * 0)なので、最初はすべての行のゼロです
3番目の列の要約を追加すると、ゼロになるはずです。このデータがどのように見えるかの例:
100 0 0
200 0 0
500 0 0
50 0 0
60 0 0
80 0 0
120 0 0
90 0 0
TOTAL 0
ここで、solver
form data
tabを実行すると、パラメーターを入力する必要があるインターフェイスが表示されます。
目標値は、すべての乗算の合計を含むCELLです。正確な値を探しています(800と入力)
セルを変更する:2番目の列でゼロの範囲を選択します
追加の制限を追加します(add
ボタン):ゼロの範囲は>= than 0
と<= 1
とint
である必要があるため、可能な結果は0と1のみです(あなた別の制限を追加するたびに範囲を再選択する必要があります)
solve
を押すと、しばらくすると(数秒から数分までのデータセットのスケールに応じて)、ゼロの一部が1に変わり、結果を生成するために使用された数値が示されます。
考えられる結果が多数ある場合は、それ以上あることを示さずに彼が見つけたものを選択しますが、再度実行すると異なる結果が生じる可能性があります。
これが私が得た結果です:
100 1 100
200 0 0
500 1 500
50 0 0
60 0 0
80 1 80
120 1 120
90 0 0
TOTAL 800
すぐ助けに行くからね。
この関数をモジュールに貼り付けて、必要に応じて調整できます。
Function GetCombination(CoinsRange As Range, SumCellId As Range) As String
Dim Nb As Integer
Dim Com As String
Dim Sum As Double
Dim r As Range
Set r = CoinsRange
Sum = SumCellId.Value
For Each cell In r.Cells
If Sum / cell.Value >= 1 Then
Com = Com & Int(Sum / cell.Value) & " of " & cell.Value & " "
Sum = Sum - (Int(Sum / cell.Value)) * cell.Value
End If
Next
GetCombination = Com
End Function
前提条件:
私の最終結果:
私はこれを行うためにWindowsアプリケーションに取り組んできました。私はほとんどの人のニーズを満たすと思う解決策に近づいています。
ほとんどのアルゴリズムでは組み合わせの数が問題になるため、実行不可能な組み合わせをできるだけ多く無視することが重要です。
リスト内の25の数字は、約3,300万の組み合わせです。リスト内の50の数字は、数百万の組み合わせです。したがって、vbaでこれを行うことは、ほとんどの人にとっておそらく実行可能なオプションではなく、ソルバーもこれをうまく処理しません。
2〜3ダースを超える数のリストを作成している場合、組み合わせが多すぎるため、ブルートフォースは機能しません。