質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

ソート

複数のデータを、順序性に従って並べ替えること。 データ処理を行う際に頻繁に用いられ、多くのアルゴリズムが存在します。速度、容量、複雑さなどに違いがあり、高速性に特化したものにクイックソートがあります。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

1935閲覧

複数の値から、合計が1000以上になるような組み合わせを複数作成するロジック

y_y_y

総合スコア1

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

ソート

複数のデータを、順序性に従って並べ替えること。 データ処理を行う際に頻繁に用いられ、多くのアルゴリズムが存在します。速度、容量、複雑さなどに違いがあり、高速性に特化したものにクイックソートがあります。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2020/10/15 09:19

編集2020/10/15 12:46

前提・実現したいこと

個人的に作成しようと思っているプログラムで以下のようなロジックを考えていますが、あまりいい方法が思いつきません。
皆様のお力をお借りできればと思い質問いたしました。

複数の値から、合計が1000以上になるような組み合わせを複数作成する。
出来る限り1000に近い組み合わせを出来る限り多く作成できる組み合わせを作成する。

ここに質問の内容を詳しく書いてください。
例えば以下の数字が与えられたときに、結果のような値を出力するプログラムを書きたいと思っています。
【与えられた数字】
211,543,1200,365,911,89,21,460,799

【結果】
1200(1200)
911,89(1000)
543,460(1003)
799,211(1010)
あまり
365,21

以下私の考えたロジックです。
1000を超える全組み合わせを探索したのち、
そこから「与えられた数字」が被らない組み合わせを全パターン探索する。
その後、そのパターンの中から「与えられた数字」を多く使っているものを選択する。

ただ、あまりにも計算量も多く、きれいなロジックではないと思っています。
またこの方法では出来るだけ1000に近い数字を出すというロジックにはならないのではないかと思っています。

もしいい方法があればご教授のほどよろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2020/10/15 09:46

3点確認させてください。1) 200+300+500など、3個以上の数字を組み合わせて1000以上にするケースを想定する必要はありますか? 2) [150, 200, 850, 900]のような数字があった場合、1050(150+900), 1050(200+850)と1000(150+850), 1100(200+900)ではどちらが望ましい答えですか? 3) 与えられる数字は何個くらいまでを想定していますか?
y_y_y

2020/10/15 10:25 編集

ご質問ありがとうございます。 1)3つ以上の組み合わせも想定しております。 2)確かにこのパターンだと困りますね… 合計金額が同じで、かつ使用している数字の数も同じなので内部的には特に優劣ありませんが、 付けたほうがロジックを組みやすいようでしたら1000により近い組み合わせがある方の1000(150+850), 1100(200+900)が望ましい答えだとしてください。 3)10~100くらいを想定しています。
m.ts10806

2020/10/15 11:17

>個人的に作成しようと思っているプログラムで 想定する言語があるのでしたらタグに追加しておくとその言語にそったアドバイスも得やすくなるかもしれません。
y_y_y

2020/10/15 12:47

ありがとうございます。 これから作成しようと思っていたのでまだ言語を決めていなかったのですが、書きなれているのでpythonにしました。 タグにも追加しました。
guest

回答1

0

ベストアンサー

数字の数が100個程度であれば、力技で十分ではないでしょうか。
私の考えたロジックは以下の通りです。

  1. 与えられた候補の数字を使用して1,000以上となるベストな組み合わせを選ぶ
  2. 前ステップで選んだ数字を候補から取り除く
  3. 最初のステップに戻る

ベストな組み合わせは以下の基準で選択

  • できるだけ1,000に近いこと
  • 使用している数値の数が少ないこと
  • 使用している数値の最小値ができるだけ小さいこと

数字100個でpythonで書いても1,2秒で処理できるので、c++とかで書けば一瞬で終わると思います。

python

1from random import randint, seed 2 3def total_to(numbers, target=1000): 4 """ 5 numbersの中の数字をいくつか組み合わせてtarget以上になる組み合わせのうちベストな組み合わせを返す 6 ベストの基準: targetに近いこと、使用している数字の数が少ないこと、より小さい数字を使用していること 7 該当無しの場合はNoneを返す 8 """ 9 if sum(numbers) < target: 10 return None 11 res = [] 12 status = {0: (0, [])} 13 for n in numbers: 14 u = dict() 15 for k, v in status.items(): 16 if k + n >= target: 17 res.append((k+n, len(v[1])+1, sorted(v[1]+[n]))) 18 elif k+n not in status or status[k+n] > (v[0]+1, v[1]+[n]): 19 u[k+n] = (v[0]+1, sorted(v[1]+[n])) 20 status.update(u) 21 return sorted(res)[0][2] 22 23 24#numbers = [211, 543, 1200, 365, 911, 89, 21, 460, 799] 25seed(3) # 乱数の固定用 26numbers = [randint(10, 1100) for _ in range(100)] # 10~1100の乱数を100個生成 27print(numbers) 28 29while True: 30 picks = total_to(numbers) 31 if picks: 32 print(f'{picks}, ({sum(picks)})') 33 for p in picks: 34 numbers.remove(p) 35 else: 36 print(f'残り:{numbers}') 37 break

実行結果のイメージ

text

1[497, 277, 767, 980, 144, 36, 970, 541, 489, 402, 973, 985, 823, 318, 484, 320, 21081, 808, 41, 141, 336, 97, 626, 73, 561, 978, 803, 884, 818, 920, 284, 758, 20 39, 83, 288, 1023, 454, 538, 903, 626, 872, 1048, 800, 728, 844, 485, 699, 68, 58 42, 344, 678, 223, 442, 556, 593, 264, 139, 997, 1000, 191, 714, 146, 850, 318, 5 51, 611, 884, 860, 253, 100, 102, 783, 687, 581, 1045, 493, 83, 644, 24, 167, 231 6, 74, 414, 845, 607, 549, 329, 96, 705, 652, 747, 293, 783, 781, 952, 1075, 800, 7 220, 1048, 565] 8 9[1000], (1000) 10[97, 903], (1000) 11[253, 747], (1000) 12[24, 209, 767], (1000) 13[36, 141, 823], (1000) 14[41, 231, 728], (1000) 15[51, 191, 758], (1000) 16[68, 288, 644], (1000) 17[73, 83, 844], (1000) 18[74, 344, 582], (1000) 19[83, 336, 581], (1000) 20[100, 293, 607], (1000) 21[102, 220, 678], (1000) 22[139, 320, 541], (1000) 23[144, 318, 538], (1000) 24[146, 167, 687], (1000) 25[223, 284, 493], (1000) 26[442, 561], (1003) 27[454, 549], (1003) 28[414, 593], (1007) 29[96, 264, 318, 329], (1007) 30[402, 611], (1013) 31[1023], (1023) 32[484, 556], (1040) 33[1045], (1045) 34[1048], (1048) 35[1048], (1048) 36[485, 565], (1050) 37[277, 781], (1058) 38[1075], (1075) 39[1081], (1081) 40[489, 626], (1115) 41[497, 626], (1123) 42[652, 699], (1351) 43[705, 714], (1419) 44[783, 783], (1566) 45[800, 800], (1600) 46[803, 808], (1611) 47[818, 845], (1663) 48[850, 860], (1710) 49[872, 884], (1756) 50[884, 920], (1804) 51[952, 970], (1922) 52[973, 978], (1951) 53[980, 985], (1965) 54残り:[997], (997)

投稿2020/10/15 13:00

編集2020/10/15 23:34
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_y_y

2020/10/18 11:59

返信が遅くなり申し訳ありません。 やりたかったことにかなり近い回答です。 ありがとうございます。参考にさせていただきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問