[[20030816230207]] 『組み合わせを選ぶ』(みすたーびーん) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『組み合わせを選ぶ』(みすたーびーん)

ちょっと複雑ですが、20個の数字(整数)があります。その中の数字の和がある数未満になる組み合わせ方を知る方法を知りたいのですが、教えていただけますか?組み合わせる個数は決まっていません。2個でもいいし、15個でもいいんです。
よろしくお願いいたします。
追記ですが、未満というのは、できるだけ近い{未満}です。


ちょっと、質問が漠然過ぎませんか?

マクロでないと難しそうですが、まず、『組み合わせ方を知る』ってのは、どういうことですか。何通りかあれば、条件に見合った、選択した数字すべてを列挙させるわけですか?それとも、出来るだけ近い未満の数字を求めるのですか?それか、何通りあるかを求めるわけですか?

次に、『ある数未満』とありますが、これは決まった数字なのですか?それとも、可変ですか?

ちょっと、これでは、達人である先生方も、お分かりにならないのではないでしょうか。ちなみに、私には、かなり難しい質問に思われます。    (ピョン)


要するに何をしたいかというと、4mのパイプを必要な長さに切りたいのですが、その必要な長さが、いろいろな長さがあって、1.5mもあれば、1.325mもある。もちろん1.325mが複数あったりする。
なるべく無駄のないようにしたいということです。
だから、できるだけ4mにちかい数をもとめたく、そして、その組み合わせ方(たとえば、1.25mと1.335mと・・・・で、4m未満)を知りたいのです。よろしくお願いします。(みすたーびーん)

 材料から部品を作るとすると普通、長いものから取ったりしないの?
 短い部品は比較的たくさんとれるわけだし。
 切るわけだから未満というのはわかるけど、
 たとえば4mから10本、計算上余り1mmです〜 というんじゃ、実際
 9本しかとれないだろうし。
 何本取るかにもよって余りを変化させなければいけないだろうから、
 VBAで総当りっぽいね。

 20個の数字は固定なのかな?
 数字が全てでないことには、自分なんかにはさっぱりですね。
 (ramrun)

 なにかキマリがあるなら、こんなの参考になるのでは?
[[20030724233943]]『金種表』(ゆーか)

この質問、ちょっと気にはなっていたのですが、ramrun さんがおっしゃるように、何m、何本などによって答えが変わりますよね。優先的に、何mを取りたいとかないのでしょうかね。たとえば、取れるなら2m、無理なら1.75m、それも無理なら1.5mにするとか・・・みすたーびーん さんの質問なら、答えが果てしなく思えるのですが。           (ピョン)

 そうですね、明快な解答がもしかしたら有るのかな、と興味持ってたんですが。
 私の脳みそでは ∞ しか浮かばず。
 >その必要な長さが、いろいろな長さがあって
 が一番ポイントですよね。
 (みすたーびーん) さん、見てらしたら返信下さいね。
 きっと解決してくれますよ。  (jun53)


たくさんのかたがたの回答ありがとうございました。
具体的に書きます。

実際に欲しい長さのパイプは、160mm×2本、276mm×6本、293mm×3本、360mm×4本
563mm×2本、610mm×3本、650mm×10本です。パイプは4m、2m、1m、60cm、があります。4mを1本買った方が、2m2本買うよりも安いので、なるべく長いのを買って、切って使いたいと思います。しかし、切ると切り幅がでてしまうので、たとえば10mのパイプから1mのパイプは9本しか取れません。切り幅は1mmです。

以上のようなことです。これを計算して、できるだけ無駄のでないようにしたいということです。こんなことエクセルでできるのでしょうか?


  横から割り込んでスンマヘン。
 コレはあくまで私個人の愚見でおまして、みすたーびーんさんの問いかけのお答えには
 なってえしまへんさかい、軽く読み流しておくんなはれや。

 例えば990mmの注文が一本有ったとしまへんか。みすたーびーんさんやったら9mmのロス
 で済む1mモンを仕入れてそれに当てまっか?そやおまへんわなぁ。当然割安の4mモンか
 cutして残りの3009mmをストックにして次の受注を待ちますわなぁ。その3009mmを切り
 落としていって27mmのロスが出てもロスの度合いは一緒ですさかい、割安な4mモンを使
 うた方が有利な事は明白ですわいな。
  こうした案配に突き詰めていくとcutする手間賃と切り幅ロス1mmの出えへん、2m,1m
 600mmのそれぞれジャストの注文の時だけそれを使って、後は全て割安な4mモンから切
 り落としていった方が長い目で見てコストダウンに繋がると思いまんねんけどどうでっ
 しゃろ?

 よしんば百歩譲って、例えばこの注文の場合の結果が、エクセル(多分マクロやなかっ
 たら無理)で拾って4m,2 2m,1 600mm,1 が最適やと出たとしても、どのm数からどのサ
 イズを何本cutするんが分からんかったら、なんの意味も持ちまへんわなぁ。
 (160+1) (160+1)*2 
 (276+1) (276+1)*2 (276+1)*3 (.....
 (293+1) (293+1)*2 (293+1)*3
 っちゅう案配に全て式を展開して、その中で最適な数値をマクロに捜ささなあきまへん
 (ちょっとやそっとの回数やおまへん)からマクロを組む言うたかて相当骨折れまっせ
 え、えぇ。

 まあ、そら、前段のお三方は、なんちゅうたってマクロの権化みたいな方達ですさかい
 造作もなく組んでしまいまっしゃろけど、私やったら手ぇつけまへんわ、えぇ。
 手ぇ付けへんちゅうより、手が付けられへんのが本音ですけどな。
  あれですわ、各サイズが同等の仕入れ値で、且つ最もロスの少ないサイズの組合せを
 求めなさい、と言う数学の問題なら結構面白いんでっしゃろけど...
   ほな、(おいぼれ弥太郎)

みすたーびんさん、おっしゃることは分かりましたが、私にも難しいです。弥太郎さんがこのようにおっしゃるのであれば、やはり相当難しいのではないかと思います。

ちょっと考えてはみましたが、やはり、答えが果てしない方向に進んでしまいます。力不足で申し訳ありません。             (ピョン)


 30本の組み合わせを総当たりで考えるのは、プログラムによって自動で出来たとしても
かなり難易度が高そうに思います。人力に頼り切った案ではありますが、下記の様な表を作成して、
1本ずつ足したり引いたりを手作業でやりながら最適と思われる組み合わせを考えるというのが
妥当な案ではないかと思います。

 30本全ての長さを足すと13,751mmになるので、4M×3本と2M×1本として表の例を作りました。

  |   A  |    B     |    C     |    D     |    E     |    F     |    G     |
 1|長さ  |必要な本数|  4,000 mm|  4,000 mm|  4,000 mm|  2,000 mm|残りの本数|
 2|160 mm|      2 本|          |      1 本|      1 本|          |          |
 3|276 mm|      6 本|      6 本|          |          |          |          |
 4|293 mm|      3 本|      3 本|          |          |          |          |
 5|360 mm|      4 本|      4 本|          |          |          |          |
 6|563 mm|      2 本|          |      1 本|      1 本|          |          |
 7|610 mm|      3 本|          |          |          |      3 本|          |
 8|650 mm|     10 本|          |      5 本|      5 本|          |          |
 9|      |      合計|  3,975 mm|  3,973 mm|  3,973 mm|  1,830 mm|          |
10|      |    切り幅|     12 mm|      6 mm|      6 mm|      2 mm|          |
11|      |    使用済|  3,987 mm|  3,979 mm|  3,979 mm|  1,832 mm|          |
12|      |    使用残|     13 mm|     21 mm|     21 mm|    168 mm|          |

 ・mmや本の単位はセルの表示形式で設定しておくものとします。
 ・C9に  =SUMPRODUCT($A$2:$A$8,C2:C8) として、D9からF9へコピー
 ・C10に =SUM(C2:C8)-1 として、D10からF10へコピー
 ・C11に =SUM(C9:C10) として、D11からF11へコピー
 ・C12に =C1-C11 として、D12からF12へコピー
 ・G2に  =B2-SUM(C2:F2) として、G3からG8へコピー

 ・C2からF8欄に本数を手入力して、シミュレーションを行う。(Yosh!)


すごいですね。ありがとうございます。どうしてそんな風に頭が回るのか
うらやましいです。
自分で試しにやってみます。でも、こんなこと計算している人も、建築業界の人は
この時勢、多いと思いますが、紙に書いて一つ一つやっているのでしょうか?
それとも、少しぐらいのロスは、見ないふりをして、やってしまうのでしょうか?

 この場合全て4mのパイプを購入すると、4本あれば足りることになります。
 1本目〜3本目については、なるべく余りを少なくすることによって
 結果的に4本目の余りが大きくなる(長くなる)わけです。
 4本目の余りが大きくなれば、余りから長い部品を取れるようになります。
 長い部品の在庫なら、いざという時は切って短い部品を作れます。
 逆に短い部品をたくさん作ると、どんどん在庫として残る...
 使われない部品を作ってしまうことが1番のロスになります。
 私的には650mmをなるべく作っておきたいところですが...

 ようは3本の余りをなるべく少なくすることによって、4本目の余りを増やし、
 そこから1ランクでも長い部品を1本取れるなら、頑張った甲斐があると思います。

 むかしkazuさんが作ったプログラムを少し改良して、
 4mから部品を取る組み合わせを出力するようにしてます。
 ここから更に4m、3本の組み合わせで余りが一番小さくなるものを
 総当りで調べれば望みのプログラムになると思います。
 って、それが面倒なんだけど(汗)。
 一応そういう形にしようとして、プログラム的に中途半端ですが
 気にしないでください。
 (ramrun)

 表は下記のように入力

   A     B        C         D        E        F        G        H        I
 1 10	3	2	4	3	6	2		
 2 650	610	563	360	293	276	160	4000mm	mod

 VBAはこんな感じ。

 Type Parts
    lth As Integer
    qty As Integer
    cnt As Integer
 End Type

 Const m_parts As Integer = 7
 Const b_parts As Integer = 4000

 Sub macro()
 Dim dat(m_parts) As Parts

 For x = 1 To m_parts
    If Cells(2, x) = "" Then Exit For
    dat(x).lth = Cells(2, x).Value + 1
    dat(x).qty = Cells(1, x).Value
    dat(x).cnt = Cells(1, x).Value
 Next x

 r = 3
 c = 0

 For i = 0 To dat(1).cnt
    For j = 0 To dat(2).cnt
        For k = 0 To dat(3).cnt
            For l = 0 To dat(4).cnt
                For m = 0 To dat(5).cnt
                    For n = 0 To dat(6).cnt
                        For o = 0 To dat(7).cnt
                            wans = dat(1).lth * i + dat(2).lth * j + dat(3).lth * k + dat(4).lth * l + dat(5).lth * m + dat(6).lth * n + dat(7).lth * o
                            If b_parts - wans < 50 Then
                            If wans < b_parts Then
                                ActiveSheet.Cells(r, c + 1) = i
                                ActiveSheet.Cells(r, c + 2) = j
                                ActiveSheet.Cells(r, c + 3) = k
                                ActiveSheet.Cells(r, c + 4) = l
                                ActiveSheet.Cells(r, c + 5) = m
                                ActiveSheet.Cells(r, c + 6) = n
                                ActiveSheet.Cells(r, c + 7) = o
                                ActiveSheet.Cells(r, c + 8) = wans
                                ActiveSheet.Cells(r, c + 9) = b_parts - wans
                                r = r + 1
                            End If
                            End If
                        Next o
                    Next n
                Next m
            Next l
        Next k
    Next j
 Next i

 End Sub

(ramrun)様、拝見いたしました。すばらしいですね。まだまだ勉強不足ですね。ありがとうございます。        (ピョン)

 >建築業界の人はこの時勢、多いと思いますが、紙に書いて一つ一つやっているのでし 
 ょうか
 材料の付加価値にもよりますけど、現場の職人任せが通例でっしゃろなぁ。但し、この
 職人という手合い、とんでもない目利きでして、いちいち紙上で計算せんでもどう切り
 合わせたらロスが少のうて済むか見当がつくみたいでっせ、えぇ。オソロシイくらいに

 この場合、ロスをどう扱うかによって変わってきますわなぁ。完全なロスは別にして残
 りを持ち帰ってストックにするんか、それとも全てロスとして廃棄処分にするんか...
 (養生をハズしたら製品として成り立たんモンなど)
 前者やとオール4mで問題おまへんけど後者やと1m,2mモンも不可欠になってきまっしゃ
 ろ?

 >どうしてそんな風に頭が回るのか
 全く同感でス、はい。いっぺん頭ん中覗いてみたいわ。ICがしこたま詰まってまんね
 で、きっと。

 ramrunさんやったらこれ位造作もなく組んでしまう、思うてましたから驚きに値しまへ
 んことは分かっとってもやっぱし初級者の目には驚異に写りますわ、えぇ。
 せやけど、アレ、イエローマークを追いかけるん途中で止めましたわ。時間のかかる事
 夥しいもんなぁ。カウントしてみたらなんと55000回も回ってますがな。それをあれだ
 けのコードでこなしてしまいまんのやから、マクロはエライっ!
 で、残念ながら私の教材にはなりまへん。まあ、飾りもんにでもしときまっさぁ。
      ほな(おいぼれ弥太郎)

 もとはエクセル事務局長が作ったものですので、私的には何も凄くないです(汗)。
 一応、4本の組み合わせをシート2へ出力します。
 どれが良いかは自分で決めてください(汗)。
 きれいにまとめようと思ったけど、面倒なのでスミマセン。

 こちらが元。
[[20020510124352]]『エクセルの計算式』(momo)
 正直「できましたァ。」には笑いましたァ。

 (ramrun)今日はお金にならない残業7時間コース

 Type Parts
    lth As Integer
    qty As Integer
    cnt As Integer
 End Type

 Const m_parts As Integer = 7
 Const b_parts As Integer = 4000

 Sub macro()
 Dim dat(m_parts) As Parts

 Worksheets(1).Range("a3:i65536").Clear
 Worksheets(2).Range("a3:i65536").Clear

 For n = 1 To m_parts
    dat(n).lth = Cells(2, n).Value + 1
    dat(n).qty = Cells(1, n).Value
    dat(n).cnt = Cells(1, n).Value
 Next n

 r = 3: c = 0
 For i = 0 To dat(1).qty
    For j = 0 To dat(2).qty
        For k = 0 To dat(3).qty
            For l = 0 To dat(4).qty
                For m = 0 To dat(5).qty
                    For n = 0 To dat(6).qty
                        For o = 0 To dat(7).qty
                            wans = _
                                dat(1).lth * i + dat(2).lth * j + _
                                dat(3).lth * k + dat(4).lth * l + _
                                dat(5).lth * m + dat(6).lth * n + _
                                dat(7).lth * o
                            If b_parts - wans < 50 Then
                                With Worksheets(1)
                                    If wans < b_parts Then
                                        .Cells(r, c + 1) = i
                                        .Cells(r, c + 2) = j
                                        .Cells(r, c + 3) = k
                                        .Cells(r, c + 4) = l
                                        .Cells(r, c + 5) = m
                                        .Cells(r, c + 6) = n
                                        .Cells(r, c + 7) = o
                                        .Cells(r, c + 8) = wans
                                        .Cells(r, c + 9) = b_parts - wans
                                        r = r + 1
                                    End If
                                End With
                            End If
                        Next o
                    Next n
                Next m
            Next l
        Next k
    Next j
 Next i

 With Worksheets(1)
    .Range("A3:I65536").Sort Key1:=.Range("I3"), Order1:=xlAscending, Header:= _
        xlGuess, OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom, _
        SortMethod:=xlPinYin, DataOption1:=xlSortNormal
 End With

 ro = 3
 For ri = 3 To 65536
    If Worksheets(1).Cells(ri, 1).Value = "" Then Exit For
    rt = ro
    For c = 1 To m_parts
        dat(c).cnt = dat(c).qty
    Next c

    For c = 1 To 9
        If c <= m_parts Then
            dat(c).cnt = dat(c).cnt - Worksheets(1).Cells(ri, c).Value
        End If
        Worksheets(2).Cells(ro, c).Value = Worksheets(1).Cells(ri, c).Value
    Next c

    For rx = 3 To 65536
        If Worksheets(1).Cells(rx, 1).Value = "" Then Exit For
        If dat(1).cnt >= Worksheets(1).Cells(rx, 1).Value Then
            If dat(2).cnt >= Worksheets(1).Cells(rx, 2).Value Then
                If dat(3).cnt >= Worksheets(1).Cells(rx, 3).Value Then
                    If dat(4).cnt >= Worksheets(1).Cells(rx, 4).Value Then
                        If dat(5).cnt >= Worksheets(1).Cells(rx, 5).Value Then
                            If dat(6).cnt >= Worksheets(1).Cells(rx, 6).Value Then
                                If dat(7).cnt >= Worksheets(1).Cells(rx, 7).Value Then
                                    ro = ro + 1
                                    For c = 1 To 9
                                        If c <= m_parts Then
                                            dat(c).cnt = dat(c).cnt - Worksheets(1).Cells(rx, c).Value
                                        End If
                                        Worksheets(2).Cells(ro, c).Value = Worksheets(1).Cells(rx, c).Value
                                    Next c
                                End If
                            End If
                        End If
                    End If
                End If
            End If
        End If
    Next rx
    ro = ro + 1
    For c = 1 To m_parts
        Worksheets(2).Cells(ro, c).Value = dat(c).cnt
    Next c
    Worksheets(2).Cells(ro, 8).Value = _
        dat(1).lth * dat(1).cnt + _
        dat(2).lth * dat(2).cnt + _
        dat(3).lth * dat(3).cnt + _
        dat(4).lth * dat(4).cnt + _
        dat(5).lth * dat(5).cnt + _
        dat(6).lth * dat(6).cnt + _
        dat(7).lth * dat(7).cnt
    Worksheets(2).Cells(ro, 9).Value = b_parts - Worksheets(2).Cells(ro, 8).Value
    ro = ro + 2
    If ro - rt < 5 Then ro = rt
 Next ri

 End Sub

 コレ、コピースルケド、イエローマーク、オワナイ
 サッキモ ニタヨウナヒト ミツケタ atamaokasii zettai
       Seijouna sekaini iru Yatarou

ありがとうございます。早速やってみます。まさしく「怪物」ですね。
上に書いてあること、私には何のことだかさっぱりわからないです。


 すんごいコードですねぇ。
 『解決してくれますよ』 なんて無責任なこと言って、気になってたんですが良かったです。
 ありがとうございます。

 と、書きましたけど、正直私には理解不可能、当分使い道もないようです。
 でも、しっかりとコピペだけはさせて頂き、床の間に飾っておきます。  (jun53)


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.