数字4つからなるリストにおいて数字2つの組み合わせ、そして残りの2つの組み合わせを全て選ぶにはどうしたらいいでしょうか?
一度選んだものは戻さないというやり方がわからないです。
余談ですが、pycharmを使ってグラハム数の計算をしてしまいました。ファンが強い勢いで回り始めてしまったので急いでスタートボタンからシャットダウンしました。
何か物理的なダメージはあるでしょうか?
再起動したら他のプログラムは問題なく実行できています。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/10/28 22:36
回答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総合スコア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
総合スコア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総合スコア284
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/10/28 12:47
2018/10/28 12:58
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。