[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『複数の数字の合計』(MATT)
はじめまして。早速ですが以下の内容よろしくお願いします。 近所のガソリンスタンドでこのような特典があります。 「ガソリン150リットル分のレシートで500円の商品券プレゼント」 そこで質問ですが、たまりにたまったレシートの給油量を入力し、150リットル以上で なおかつ、150リットルに限りなく近くなるレシートの組み合わせを計算式または関数 で簡単に出来ないでしょうか? 例えば、A**リットル、B**リットル、C**リットル、D**リットル、E**リットル、F**リットルの場合、 A+C=151リットル、B+D=151.5リットルみたいな計算を簡単にしたいのです。 うまく説明できませんが、よろしくお願いします。
EXCEL2002 WIN XPです。
こんな関数はどうでっか?
Alt+F11でVBEを開く
「挿入」→「標準モジュール」を選択
真新しいモジュールに下のコードをコピペ
エクセルに戻り
A B C D E
1 85リットル 98リットル 69.5リットル 92リットル 70リットル
2
3
と、まあ、こんな具合にデータを配置し、F1あたりに=matt(a1:e1)と入力してみて
おくんなはれ。
どうでっか、こんな塩梅で?
(弥太郎)
Function matt(adrs As Range)
Dim x As Double, i As Integer, n As Integer
Dim data As Double, s_data As Double, tbl As Range, y(2)
Set tbl = adrs
x = 500
For i = 1 To tbl.Columns.Count
data = Val(StrConv(tbl(1, i), vbNarrow))
For n = i + 1 To tbl.Columns.Count
s_data = Val(StrConv(tbl(1, n), vbNarrow))
If data + s_data >= 150 Then
If data + s_data - 150 < x Then
x = data + s_data - 150
y(0) = tbl(1, i).Address(0, 0)
y(1) = tbl(1, n).Address(0, 0)
End If
End If
Next n
Next i
matt = x + 150 & "," & y(0) & "と" & y(1)
End Function
2回給油分の組み合わせですか??? 3回分4回分等の組み合わせも有るのでしょうか??? (JJ)
A B 3回分4回分等の組み合わせも有るのでしょうか? 1 1 70 2 2 75 3 3 83 4 4 90 5 5 76 6 6 88 7 7 84 8 8 92 9 9 68 10 10 70 11 11 77 12 12 56 13 13 68 14 14 91 15 15 87 16 17 15回給油したとして 18 =COMBIN(15,2)=105の内一番近い数字を選ぶ(2回のみの組み合わせ)
19 =COMBIN(15,3)=455の内一番近い数字を選ぶ(3回のみの組み合わせ)
20 =COMBIN(15,4)=1365の内一番近い数字を選ぶ(4回のみの組み合わせ)
の内一番近い数字を選ぶになりますが
jj
質問内容からすると n枚のレシートからm(1≦m≦n)枚取り出してその合計が150以上で 最小値になる組み合わせを求めるということでしょうか。 実際は、求めた組み合わせのデータを除いた中から同じように 抽出を繰り返すのでしょう。 (やっちん)
な〜るほろ〜。
いかにもありそうでんなぁ。
ほならこないな事でっしゃろか?
=mattaku(a1:j1,3) っちゅう塩梅に入力。抽出されたセルのデータを消去していく。
組合せ4までですけど、それ以上あるばやいはコードの規則性に従って書き加えてく
らはい。
=mattaku(a1:j1)と引数を省略したら2回の組合せで抽出します。
(弥太郎)
Function mattaku(adrs As Range, Optional mai = 2)
Dim x As Double, i As Integer, n As Integer, t As Integer, j As Integer
Dim data1 As Double, data2 As Double, data3 As Double, data4 As Double, tbl As Range, y(3)
Set tbl = adrs
x = 1000
With tbl
Select Case mai
Case 4
For i = 1 To .Columns.Count - 3
If tbl(1, i) <> "" Then
data1 = Val(StrConv(tbl(1, i), vbNarrow))
For n = i + 1 To .Columns.Count - 2
If tbl(1, n) <> "" Then
data2 = data1 + Val(StrConv(tbl(1, n), vbNarrow))
For j = n + 1 To tbl.Columns.Count - 1
If tbl(1, j) <> "" Then
data3 = data2 + Val(StrConv(tbl(1, j), vbNarrow))
For t = j + 1 To tbl.Columns.Count
If tbl(1, t) <> "" Then
data4 = data3 + Val(StrConv(tbl(1, t), vbNarrow))
If data4 >= 150 Then
If data4 - 150 < x Then
x = data4 - 150
y(0) = tbl(1, i).Address(0, 0)
y(1) = tbl(1, n).Address(0, 0)
y(2) = tbl(1, j).Address(0, 0)
y(3) = tbl(1, t).Address(0, 0)
End If
End If
End If
Next t
End If
Next j
End If
Next n
End If
Next i
mattaku = x + 150 & "は" & Join(y, ",")
Exit Function
Case 3
For i = 1 To .Columns.Count - 2
If tbl(1, i) <> "" Then
data1 = Val(StrConv(tbl(1, i), vbNarrow))
For n = i + 1 To .Columns.Count - 1
If tbl(1, n) <> "" Then
data2 = data1 + Val(StrConv(tbl(1, n), vbNarrow))
For j = n + 1 To .Columns.Count
If tbl(1, j) <> "" Then
data3 = data2 + Val(StrConv(tbl(1, j), vbNarrow))
If data3 >= 150 Then
If data3 - 150 < x Then
x = data3 - 150
y(0) = tbl(1, i).Address(0, 0)
y(1) = tbl(1, n).Address(0, 0)
y(2) = tbl(1, j).Address(0, 0)
End If
End If
End If
Next j
End If
Next n
End If
Next i
mattaku = x + 150 & "," & y(0) & "と" & y(1) & "と" & y(2)
Exit Function
Case 2
For i = 1 To .Columns.Count - 1
If tbl(1, i) <> "" Then
data1 = Val(StrConv(tbl(1, i), vbNarrow))
For n = i + 1 To .Columns.Count
If tbl(1, n) <> "" Then
data2 = data1 + Val(StrConv(tbl(1, n), vbNarrow))
If data2 >= 150 Then
If data2 - 150 < x Then
x = data2 - 150
y(0) = tbl(1, i).Address(0, 0)
y(1) = tbl(1, n).Address(0, 0)
End If
End If
End If
Next n
End If
Next i
End Select
If y(0) = "" Then Exit Function
mattaku = x + 150 & "," & y(0) & "と" & y(1)
End With
End Function
A1:A15 の範囲に(上から順に間を明かさず}リットル数を書き込んで、 下記のマクロを実行してみて下さい。 (純丸)(o^-')b もっと配列の扱いがすっきり出来るんだろうなぁw
Sub test2()
Dim tbl1, tbl2
Dim i As Long
Dim ii As Integer
Dim datacnt As Long
Dim myans As Single
Dim myans2 As Single
Dim myans3 As Long
datacnt = Application.WorksheetFunction.Count(Range("A1:A15"))
Range("A1:A15").Font.ColorIndex = 0
ReDim tbl1(1 To datacnt)
ReDim tbl2(1 To datacnt)
myans = 150
For i = 1 To datacnt
tbl1(i) = Cells(i, 1).Value
Next i
For i = 1 To 2 ^ datacnt
For ii = 1 To datacnt
tbl2(ii) = Int(i / (2 ^ (ii - 1))) Mod 2
myans2 = myans2 + tbl1(ii) * tbl2(ii)
Next ii
myans2 = myans2 - 150
If myans2 < 0 Then GoTo mynext
If myans > myans2 Then
myans = myans2
myans3 = i
End If
mynext:
myans2 = 0
Next i
For ii = 1 To datacnt
If Int(myans3 / (2 ^ (ii - 1))) Mod 2 = 1 Then
Cells(ii, 1).Font.ColorIndex = 3
End If
Next ii
Range("A17").Value = Application.WorksheetFunction.RoundDown(myans, 1) + 150
End Sub
本当に正しいのか怪しいのですが(^^; 無駄な動きをしている部分もありますが、とりあえず。 A列に連番、B列に数値だけのデータを入力。C列は必ずクリアしておいてください。 A列とB列をB列昇順に並び替えます。 ここでTestを実行してください。 D列に合計、E列に組み合わせの番号が出ます。
Dim Min_Pt As String Dim Min_Sm As Double Dim MyArray As Variant Dim MaxRow As Long Const LMT150 = 150#
Sub Test()
Dim Cnt As Long
Dim MyArray2 As Variant
Dim j As Long
Cnt = 0
MyArray = Range(Range("A1"), Range("B" & Rows.Count).End(xlUp).Offset(, 1))
MaxRow = UBound(MyArray, 1)
Do
Cnt = Cnt + 1
Min_Sm = 9999999999999#
Min_Pt = ""
Call Kumiawase(0, 0, "", False)
If Min_Pt <> "" Then
Cells(Cnt, 4).Value = Min_Sm
Cells(Cnt, 5).Value = Mid(Min_Pt, 2)
MyArray2 = Split(Mid(Min_Pt, 2), ",")
For j = 0 To UBound(MyArray2, 1)
MyArray(Application.Match(Val(MyArray2(j)), Columns(1), 0), 3) = 1
Next
End If
Loop Until Min_Pt = ""
End Sub
Sub Kumiawase(ByVal i As Long, ByVal Sm As Double, ByVal Pt As String, ByRef Flg As Boolean)
Dim wk As Long
If Sm >= LMT150 Then
If Min_Sm > Sm Then
Min_Pt = Pt
Min_Sm = Sm
End If
Flg = True
Exit Sub
End If
Do While i < MaxRow
wk = ix(i + 1)
If wk <= MaxRow Then
Call Kumiawase(wk, Sm + MyArray(wk, 2), Pt & "," & MyArray(wk, 1), Flg)
If Flg = True Then
Flg = False
Exit Sub
End If
End If
i = ix(i + 1)
Loop
End Sub
Function ix(ByVal i As Long) As Long
ix = i
Do While ix <= MaxRow
If MyArray(ix, 3) <> 1 Then
Exit Function
End If
ix = ix + 1
Loop
End Function
(やっちん)
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.