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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Python

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

Q&A

解決済

3回答

561閲覧

Pythonの組み合わせについて

babbleman

総合スコア107

Python

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

1グッド

1クリップ

投稿2018/10/28 10:36

数字4つからなるリストにおいて数字2つの組み合わせ、そして残りの2つの組み合わせを全て選ぶにはどうしたらいいでしょうか?
一度選んだものは戻さないというやり方がわからないです。
余談ですが、pycharmを使ってグラハム数の計算をしてしまいました。ファンが強い勢いで回り始めてしまったので急いでスタートボタンからシャットダウンしました。
何か物理的なダメージはあるでしょうか?
再起動したら他のプログラムは問題なく実行できています。

calcium_neco👍を押しています

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

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

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

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

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

tiitoi

2018/10/28 13:50

過去の解決した質問は解決済みにしてください。
babbleman

2018/10/28 22:36

すみません、丸投げしたつもりはありませんでした。組み合わせのやり方は調べてわかったのですが、重複しないで取り出す方法がわかりませんでした。
guest

回答3

0

練習の例としてライブラリーを使わずに思いついたまま書いてみました。

最初に前提として以下を想定してみます

  • 選ばれなかったものは選んだものから容易に計算できるので選ぶべきものだけに注目する
  • n C 2 (n個から2つを取り出す組み合わせ)に限定した論理でよいことにする

特に後者の前提は例2以降に比べコードを大変単純にできます。ただジェネレーターを使っているのでそれを知っていないと理解が難しいと思います。

例1

Python

1def comb_n_2(n): 2 for i in range(n): 3 for j in range(i + 1, n): 4 yield [i, j] 5 6for c in comb_n_2(4): 7 print(c) 8 9結果==> 10[0, 1] 11[0, 2] 12[0, 3] 13[1, 2] 14[1, 3] 15[2, 3]

次に少し汎用的な論理「n個の中からm個取り出す」にしてみました。考え方はcomb_4_2comb_n_2と同様なのですが for文の入れ子の深さがmに従って深くなるため、comb_4_2comb_n_2のような単純なfor文の入れ子では書けません。そこでコーディングテクニックとして再帰呼び出しを使っています。再帰やジェネレータに慣れてないとわかりにくいだろうと思います。

例2

Python

1def comb(n, m): 2 if m == 1: 3 for i in range(n): 4 yield [i] 5 else: 6 # n個からm-1個取り出す組み合わせを求め、その末尾にm個目の選択要素をくっつける 7 for c in comb(n, m - 1): 8 for i in range(c[-1] + 1, n): 9 yield c + [i] 10 11for c in comb(5, 3): 12 print(c) 13 14結果==> 15[0, 1, 2] 16[0, 1, 3] 17[0, 1, 4] 18[0, 2, 3] 19[0, 2, 4] 20[0, 3, 4] 21[1, 2, 3] 22[1, 2, 4] 23[1, 3, 4] 24[2, 3, 4]

次は選んだものに基づき選ばなかったものも計算してみます。ついでに求めた組み合わせを個々に印字するのではなく、全ての組み合わせをlistにまとめそれを印字してみました。(印字結果を見やすくするため__repr__, replaceで整形を施してます)

例3

Python

1def comb_both(n, m): 2 all_numbers = set(range(n)) 3 for selected in comb(n, m): # combは例2参照 4 not_selected = sorted(list(all_numbers.difference(set(selected)))) 5 yield selected, not_selected 6 7all_c = [*comb_both(4, 2)] 8print(all_c.__repr__().replace('),', '),\n')) 9 10結果==> 11[([0, 1], [2, 3]), 12 ([0, 2], [1, 3]), 13 ([0, 3], [1, 2]), 14 ([1, 2], [0, 3]), 15 ([1, 3], [0, 2]), 16 ([2, 3], [0, 1])]

最後に選んだものと選ばなかったものを同時に計算する方法も考えてみました。多少高速にならないかと思って書いたのですが実際の効率は検証してません。効率はともかくとしてわりあいわかりやすい気がします。でもあまりPythonらしくない(ちまちました)論理かも知れません。やはり再帰やジェネレーターに慣れてないとわかりにくいだろうと思います。

例4

Python

1def comb_both_2(n, m, i, selected, not_selected): 2 if i >= n: 3 # 最後まで計算しつくした 4 yield selected, not_selected 5 elif len(selected) >= m: 6 # 選択すべき個数に達した。 7 yield selected, not_selected + [*range(i, n)] 8 elif n - i == m - len(selected): 9 # 残った数字(n - i)個を全て選択しないと選択すべき個数に達しない。 10 yield selected + [*range(i, n)], not_selected 11 else: 12 # iを選ぶ場合、選ばない場合の両方の選択肢がある。 13 yield from comb_both_2(n, m, i + 1, selected + [i], not_selected) 14 yield from comb_both_2(n, m, i + 1, selected, not_selected + [i]) 15 16for c in comb_both_2(4, 2, 0, [], []): 17 print(c) 18 19結果==> 20([0, 1], [2, 3]) 21([0, 2], [1, 3]) 22([0, 3], [1, 2]) 23([1, 2], [0, 3]) 24([1, 3], [0, 2]) 25([2, 3], [0, 1])

なお上記はPython3.7で動作確認しました。古いバージョンでは使えない機能がいくつかあります。例えばyield fromは3.3より前のバージョンでは使えません。

投稿2018/10/29 04:06

編集2018/10/29 13:52
KSwordOfHaste

総合スコア18394

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

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

0

ベストアンサー

数字4つからなるリストにおいて数字2つの組み合わせ、そして残りの2つの組み合わせを全て選ぶにはどうしたらいいでしょうか?
一度選んだものは戻さないというやり方がわからないです。

順列を作って、np.array_split() で2個ずつに分割するやり方を書きました。
要素数が8個ぐらいまでのリストならすぐ計算できますが、それ以上になってくると、以下のやり方だと計算時間がかかってしまいます。

python

1import itertools 2import numpy as np 3 4def possible_pairs(iterable, r): 5 num_pairs = int(np.ceil(len(iterable) / r)) # ペアの数 6 possible_pairs = [] 7 8 for p in itertools.permutations(iterable): 9 # 順列を num_pairs 分割し、ソートしておく。 10 pairs = sorted([sorted(p) for p in np.array_split(p, num_pairs)]) 11 # 重複していなければ、追加 12 if pairs not in possible_pairs: 13 possible_pairs.append(pairs) 14 15 return possible_pairs 16 17lst = [1, 2, 3, 4] 18r = 2 # 1つのペアの数 19 20possible_pairs = possible_pairs(lst, r) 21for pairs in possible_pairs: 22 print(pairs)

output

1# lst=[1, 2, 3, 4], r=2 2[[1, 2], [3, 4]] 3[[1, 3], [2, 4]] 4[[1, 4], [2, 3]]

output

1# lst=[1, 2, 3, 4, 5], r=2 2[[1, 2], [3, 4], [5]] 3[[1, 2], [3, 5], [4]] 4[[1, 2], [3], [4, 5]] 5[[1, 3], [2, 4], [5]] 6[[1, 3], [2, 5], [4]] 7[[1, 3], [2], [4, 5]] 8[[1, 4], [2, 3], [5]] 9[[1, 4], [2, 5], [3]] 10[[1, 4], [2], [3, 5]] 11[[1, 5], [2, 3], [4]] 12[[1, 5], [2, 4], [3]] 13[[1, 5], [2], [3, 4]] 14[[1], [2, 3], [4, 5]] 15[[1], [2, 4], [3, 5]] 16[[1], [2, 5], [3, 4]]

output

1# lst=[1, 2, 3, 4, 5, 6], r=2 2[[1, 2], [3, 4], [5, 6]] 3[[1, 2], [3, 5], [4, 6]] 4[[1, 2], [3, 6], [4, 5]] 5[[1, 3], [2, 4], [5, 6]] 6[[1, 3], [2, 5], [4, 6]] 7[[1, 3], [2, 6], [4, 5]] 8[[1, 4], [2, 3], [5, 6]] 9[[1, 4], [2, 5], [3, 6]] 10[[1, 4], [2, 6], [3, 5]] 11[[1, 5], [2, 3], [4, 6]] 12[[1, 5], [2, 4], [3, 6]] 13[[1, 5], [2, 6], [3, 4]] 14[[1, 6], [2, 3], [4, 5]] 15[[1, 6], [2, 4], [3, 5]] 16[[1, 6], [2, 5], [3, 4]]

余談ですが、pycharmを使ってグラハム数の計算をしてしまいました。ファンが強い勢いで回り始めてしまったので急いでスタートボタンからシャットダウンしました。
何か物理的なダメージはあるでしょうか?

CPU の稼働率が上がり、熱が発生してファンが回っているだけだと思うので、適切に排熱されていれば大丈夫だと思います。
心配ならエアコンをつけて室温を下げましょう。

投稿2018/10/28 13:13

tiitoi

総合スコア21956

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

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

0

こうですか?

python

1arr=[ 1, 2, 3, 4] 2for i in range(4): 3 for j in range(4): 4 for k in range(4): 5 for l in range(4): 6 if(i==j or i==k or i==l or j==k or j==l or k==l): 7 continue 8 a=arr[i] 9 b=arr[j] 10 c=arr[k] 11 d=arr[l]

ファンが動き出しただけではわかりません。
無限ループしているからかもしれないし、
メモリを大きくとりすぎてswappingが頻繁に起きているからかもしれません。
プログラムを掲載しないと分かりません。

投稿2018/10/28 12:30

編集2018/10/28 12:55
ruei

総合スコア284

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

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

hayataka2049

2018/10/28 12:47

listという変数名は組み込みのlistクラスを上書きするので避けた方が良いです。continueのセミコロンは要りません そしてこの4重forは質問者のやりたいことだったのか・・・
ruei

2018/10/28 12:58

listをarrに変更し、continueのセミコロンを除去しました。listの上書きしりませんでした。すみません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問