🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
アルゴリズム

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

Python

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

Q&A

解決済

4回答

1553閲覧

上限がバラバラなリストでのnまでの総数の組み合わせ

mermer

総合スコア16

アルゴリズム

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

Python

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

0グッド

2クリップ

投稿2019/11/10 08:32

編集2019/11/11 01:58

pythonで例えば
リストの各要素の上限が決まっており,その中にnを振り分ける方法はどのようにすればよいのでしょうか.

例:

python

1max = [0,5,4,3,4,1] 2n = 10
#リストの要素の総和がnになるような組み合わせ [0,5,4,1,0,0] [0,5,4,0,1,0] [0,5,4,0,0,1] … [0,0,2,3,4,1]

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

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

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

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

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

quickquip

2019/11/10 23:47

[0,0,2,3,4,1] の 2 はなんですか?
mermer

2019/11/11 01:56

記述不足で申し訳ありません. リスト内の総和がnになる組み合わせです.
quickquip

2019/11/11 02:05 編集

max = [0,5,4,3,4,1] が誤誘導ですか? ここに2がないわけですが、この中から選びたいわけではなくとにかく10になればいいのですか?
mermer

2019/11/11 02:09 編集

リスト内の要素それぞれの上限がmax=[0,5,4,3,4,1]で その中からリスト内の要素の総和がnになるようなリストを作り出したいわけです. ですので[0,0,2,3,4,1]はリストの要素の総和が10かつリスト内の要素はmaxの値を超えてないという例でございます.
quickquip

2019/11/11 02:14

了解しました。なるほど
guest

回答4

0

ベストアンサー

データサイズにもよりますが再起呼び出しを使えばいいんではないでしょうか

Python

1def f(res, max_array, n, work_array): 2 3 i = len(work_array) 4 s = sum(work_array) 5 6 # 組み合わせ配列の長さが最大値配列の長さに達したか? 7 if (i == len(max_array)): 8 # 組み合わせ配列の合計は目的の値か? 9 if s == n: 10 # 組み合わせ配列を結果用配列に追加 11 res.append(work_array) 12 else: 13 # 残りの数値または対象要素の数値の小さいほうでループ 14 for v in range(min(max_array[i], n-s)+1): 15 w = work_array[:] 16 # 選択した値を組み合わせ配列に追加する 17 w.append(v) 18 # 再起呼び出し 19 f(res, max_array, n, w) 20 21 22max_array = [0,5,4,3,4,1] 23n = 10 24 25res = [] 26work_array = [] 27 28f(res, max_array, n, work_array) 29 30 31for _ in res: 32 print(_)

投稿2019/11/10 11:10

nomuken

総合スコア1627

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

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

mermer

2019/11/12 07:42

quiquiさんの方法もよかったですが,こちらが私のマシンで実行速度が速かったためにベストアンサーにさせていただきました.
guest

0

この程度のループなら、全組み合わせ(product)を生成してから、合計10のものだけにする(filter)という方針でもいいような気がします。
参考程度にどうぞ。

python

1m = [0,5,4,3,4,1] # max は変数名として使うべきではないので 2n = 10 3 4from itertools import product 5 6range_argments = [x + 1 for x in m] # => [1, 6, 5, 4, 5, 2] 7answer = list(filter(lambda x: sum(x) == 10, product(*map(range, range_argments)))) 8 9print(answer)

plain

1[(0, 0, 2, 3, 4, 1), (0, 0, 3, 2, 4, 1), (0, 0, 3, 3, 3, 1), (0, 0, 3, 3, 4, 0), (0, 0, 4, 1, 4, 1), (0, 0, 4, 2, 3, 1), 2 (0, 0, 4, 2, 4, 0), (0, 0, 4, 3, 2, 1), (0, 0, 4, 3, 3, 0), (0, 1, 1, 3, 4, 1), (0, 1, 2, 2, 4, 1), (0, 1, 2, 3, 3, 1), 3 (0, 1, 2, 3, 4, 0), (0, 1, 3, 1, 4, 1), (0, 1, 3, 2, 3, 1), (0, 1, 3, 2, 4, 0), (0, 1, 3, 3, 2, 1), (0, 1, 3, 3, 3, 0), 4 (0, 1, 4, 0, 4, 1), (0, 1, 4, 1, 3, 1), (0, 1, 4, 1, 4, 0), (0, 1, 4, 2, 2, 1), (0, 1, 4, 2, 3, 0), (0, 1, 4, 3, 1, 1), 5 (0, 1, 4, 3, 2, 0), (0, 2, 0, 3, 4, 1), (0, 2, 1, 2, 4, 1), (0, 2, 1, 3, 3, 1), (0, 2, 1, 3, 4, 0), (0, 2, 2, 1, 4, 1), 6 (0, 2, 2, 2, 3, 1), (0, 2, 2, 2, 4, 0), (0, 2, 2, 3, 2, 1), (0, 2, 2, 3, 3, 0), (0, 2, 3, 0, 4, 1), (0, 2, 3, 1, 3, 1), 7 (0, 2, 3, 1, 4, 0), (0, 2, 3, 2, 2, 1), (0, 2, 3, 2, 3, 0), (0, 2, 3, 3, 1, 1), (0, 2, 3, 3, 2, 0), (0, 2, 4, 0, 3, 1), 8 (0, 2, 4, 0, 4, 0), (0, 2, 4, 1, 2, 1), (0, 2, 4, 1, 3, 0), (0, 2, 4, 2, 1, 1), (0, 2, 4, 2, 2, 0), (0, 2, 4, 3, 0, 1), 9 (0, 2, 4, 3, 1, 0), (0, 3, 0, 2, 4, 1), (0, 3, 0, 3, 3, 1), (0, 3, 0, 3, 4, 0), (0, 3, 1, 1, 4, 1), (0, 3, 1, 2, 3, 1), 10 (0, 3, 1, 2, 4, 0), (0, 3, 1, 3, 2, 1), (0, 3, 1, 3, 3, 0), (0, 3, 2, 0, 4, 1), (0, 3, 2, 1, 3, 1), (0, 3, 2, 1, 4, 0), 11 (0, 3, 2, 2, 2, 1), (0, 3, 2, 2, 3, 0), (0, 3, 2, 3, 1, 1), (0, 3, 2, 3, 2, 0), (0, 3, 3, 0, 3, 1), (0, 3, 3, 0, 4, 0), 12 (0, 3, 3, 1, 2, 1), (0, 3, 3, 1, 3, 0), (0, 3, 3, 2, 1, 1), (0, 3, 3, 2, 2, 0), (0, 3, 3, 3, 0, 1), (0, 3, 3, 3, 1, 0), 13 (0, 3, 4, 0, 2, 1), (0, 3, 4, 0, 3, 0), (0, 3, 4, 1, 1, 1), (0, 3, 4, 1, 2, 0), (0, 3, 4, 2, 0, 1), (0, 3, 4, 2, 1, 0), 14 (0, 3, 4, 3, 0, 0), (0, 4, 0, 1, 4, 1), (0, 4, 0, 2, 3, 1), (0, 4, 0, 2, 4, 0), (0, 4, 0, 3, 2, 1), (0, 4, 0, 3, 3, 0), 15 (0, 4, 1, 0, 4, 1), (0, 4, 1, 1, 3, 1), (0, 4, 1, 1, 4, 0), (0, 4, 1, 2, 2, 1), (0, 4, 1, 2, 3, 0), (0, 4, 1, 3, 1, 1), 16 (0, 4, 1, 3, 2, 0), (0, 4, 2, 0, 3, 1), (0, 4, 2, 0, 4, 0), (0, 4, 2, 1, 2, 1), (0, 4, 2, 1, 3, 0), (0, 4, 2, 2, 1, 1), 17 (0, 4, 2, 2, 2, 0), (0, 4, 2, 3, 0, 1), (0, 4, 2, 3, 1, 0), (0, 4, 3, 0, 2, 1), (0, 4, 3, 0, 3, 0), (0, 4, 3, 1, 1, 1), 18 (0, 4, 3, 1, 2, 0), (0, 4, 3, 2, 0, 1), (0, 4, 3, 2, 1, 0), (0, 4, 3, 3, 0, 0), (0, 4, 4, 0, 1, 1), (0, 4, 4, 0, 2, 0), 19 (0, 4, 4, 1, 0, 1), (0, 4, 4, 1, 1, 0), (0, 4, 4, 2, 0, 0), (0, 5, 0, 0, 4, 1), (0, 5, 0, 1, 3, 1), (0, 5, 0, 1, 4, 0), 20 (0, 5, 0, 2, 2, 1), (0, 5, 0, 2, 3, 0), (0, 5, 0, 3, 1, 1), (0, 5, 0, 3, 2, 0), (0, 5, 1, 0, 3, 1), (0, 5, 1, 0, 4, 0), 21 (0, 5, 1, 1, 2, 1), (0, 5, 1, 1, 3, 0), (0, 5, 1, 2, 1, 1), (0, 5, 1, 2, 2, 0), (0, 5, 1, 3, 0, 1), (0, 5, 1, 3, 1, 0), 22 (0, 5, 2, 0, 2, 1), (0, 5, 2, 0, 3, 0), (0, 5, 2, 1, 1, 1), (0, 5, 2, 1, 2, 0), (0, 5, 2, 2, 0, 1), (0, 5, 2, 2, 1, 0), 23 (0, 5, 2, 3, 0, 0), (0, 5, 3, 0, 1, 1), (0, 5, 3, 0, 2, 0), (0, 5, 3, 1, 0, 1), (0, 5, 3, 1, 1, 0), (0, 5, 3, 2, 0, 0), 24 (0, 5, 4, 0, 0, 1), (0, 5, 4, 0, 1, 0), (0, 5, 4, 1, 0, 0)]

投稿2019/11/11 02:28

編集2019/11/11 03:40
quickquip

総合スコア11231

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

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

退会済みユーザー

退会済みユーザー

2019/11/11 03:17

answer = list... の行、閉じカッコが一つ不足しています。
quickquip

2019/11/11 03:41

ありがとうございます。助かります。
guest

0

リストの先頭要素から順に1つずつ計算する方式で作ってみました。
n=10くらいであれば、十分高速に動作すると思います。

python

1def solve(n, limits): 2 stack = [(n, sum(limits), [])] 3 ans = [] 4 while stack: 5 rem, t, picks = stack.pop() # 合計でnにするために必要な残り、 実現可能な最大値、 これまで選択した数値のリスト 6 if len(picks) == len(limits) - 1: 7 if 0 <= rem <= limits[-1]: 8 ans.append(picks + [rem]) 9 else: 10 for i in range(max(rem-t, 0), min(rem+1, limits[len(picks)]+1)): 11 stack.append((rem-i, t-limits[len(picks)], picks + [i])) 12 return ans 13 14 15limits = [0, 5, 4, 3, 4, 1] 16n = 10 17 18ans = solve(n, limits) 19print(*ans, sep='\n') 20print(len(ans)) # 141通り

投稿2019/11/10 12:16

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

0

1. 配列a[]の要素数をsとして 2. N > 0 である間: 3. i=0~s-1の乱数 3. a[i] が上限に満たなければ:   a[i] += 1 N -= 1

...と、こんなんでいかがでしょ。

投稿2019/11/10 11:27

編集2019/11/10 11:30
episteme

総合スコア16612

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問