これは、重複がなければ非常に簡単です。. . 為に
{ 1, 1, 2, 3, 4, 5, 6, 7, 8, 9 }
(元の問題の 10 とは対照的に) 9 つの異なる選択肢しかないため、答えは 9 になるはずです。/ (9 - 4)!
(ちなみに、繰り返しを許可すれば、実際にはもっと異なる 4 桁の数字を持つことができます。つまり 4456 です。すると、答えは 9^4 の 4 桁の数字になります。)
同様に、{1, 1, 2, 2, 3, 4, 5, 6, 7, 8 } には 8 つの異なる選択肢があるため、答えは 8 になります。/ (8 - 4)! あなたの元の数学によって。
編集と実際の回答: セット内で 1 が重複している場合、回答に 2 つの 1 を使用できるということでしょうか?
編集2:動作し、テストされたpythonモジュールが提供されました
その場合、次の python コードが示唆するように、可能性の異なる数を計算してから、結果を重複して追加してみてください)。
import math
def set_exclude(a, b):
result = []
for i in a:
if not i in b:
result.append(i)
return result
def cnt_unique(aset, choices_picked, count_left, count_total):
# Sanity check
if count_left < 0:
return 0
if count_left == 0:
return math.factorial(count_total)
# Do non-duplicate combinations first
# Set unprocessed = (set without any elements in choices_picked)
unprocessed = set_exclude(aset, choices_picked)
temp = len(set(unprocessed))
# If we have no more valid items to choose from, this is impossible
if temp >= count_left:
result = math.factorial(temp) / math.factorial(temp - count_left) / \
math.factorial(count_left) * math.factorial(count_total)
else:
result = 0
# Now find duplicate-involving combinations
for member in set(unprocessed):
valid = True
for contest in choices_picked:
if contest >= member:
valid = False
break
if valid:
count = unprocessed.count(member)
new_choices = choices_picked + [ member ]
for i in range(2, count+1):
result_temp = cnt_unique(aset, new_choices, \
count_left - i, count_total)
if result_temp != 0:
result_temp //= math.factorial(i)
result += result_temp
return result
aset = [ 1, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
result_size = 4
combinations = cnt_unique(aset, [], result_size, result_size)
OK、上記のすべてのケースでアルゴリズムが機能することを手作業で確認しました。より一般的なケースでは機能すると確信していますが、現時点では追加のテスト ケースを実行する時間がありません (たとえば、1 が 3 つ、または重複のグループが 3 つあった場合)。また、choices_picked に含まれていない数字がセットに含まれていない場合にも爆発することに注意してください (つまり、1 つの一意の数字が 10 回重複しています)。
編集 3: 大規模なセットに対してこのアルゴリズムで関数呼び出しがいくつ行われるかに関して、次の関数呼び出しでテストし、重要な (count_left >= 0) cnt_unique への呼び出しごとに変数を 1 回インクリメントします。
>>> def test():
b = [0]
c = time.time()
result = cnt_unique(range(1,51) + range(1,51), [], 4, 4, b)
c = time.time() - c
print("Result: " + str(result))
print("Time: " + str(c))
print("Calls: " + str(b[0]))
>>> test()
Result: 6240150
Time: 0.0150001049042
Calls: 1276
したがって、1 ~ 50 の番号ごとに 2 つのエントリを持つ 100 要素セットの場合、1276 回の呼び出しがありました。そして、それは非常に高速に実行されます。time.time() の 1 ティックは 15 ミリ秒であるため、通常は 15 ミリ秒未満で実行されます。