Test değerlerini üretmek için şöyle bir fonksiyon yazdım:
def test_cases(n: int, r: int, stop: int = 0):
if not r:
yield []
return
for v in test_cases(n, r - 1, stop + 1):
for i in range(n + 1):
if (k := [i, *v]) and len(k) != r + stop or max(k) <= sum(sorted(k)[:-1]) and all(k):
yield k
Bu fonksiyon ile test durumlarını oluşturuyoruz.
Bir örnek yapalım:
for test_case in test_cases(n=10, r=3):
print(test_case)
[1, 1, 1]
[2, 1, 1]
[1, 2, 1]
[2, 2, 1]
[3, 2, 1]
[2, 3, 1]
[3, 3, 1]
[4, 3, 1]
[3, 4, 1]
[4, 4, 1]
[5, 4, 1]
[4, 5, 1]
[5, 5, 1]
[6, 5, 1]
[5, 6, 1]
[6, 6, 1]
[7, 6, 1]
[6, 7, 1]
[7, 7, 1]
[8, 7, 1]
[7, 8, 1]
[8, 8, 1]
[9, 8, 1]
[8, 9, 1]
[9, 9, 1]
[10, 9, 1]
[9, 10, 1]
[10, 10, 1]
[1, 1, 2]
[2, 1, 2]
[3, 1, 2]
[1, 2, 2]
[2, 2, 2]
[3, 2, 2]
[4, 2, 2]
[1, 3, 2]
[2, 3, 2]
[3, 3, 2]
[4, 3, 2]
[5, 3, 2]
[2, 4, 2]
[3, 4, 2]
[4, 4, 2]
[5, 4, 2]
[6, 4, 2]
[3, 5, 2]
[4, 5, 2]
[5, 5, 2]
[6, 5, 2]
[7, 5, 2]
[4, 6, 2]
[5, 6, 2]
[6, 6, 2]
[7, 6, 2]
[8, 6, 2]
[5, 7, 2]
[6, 7, 2]
[7, 7, 2]
[8, 7, 2]
[9, 7, 2]
[6, 8, 2]
[7, 8, 2]
[8, 8, 2]
[9, 8, 2]
[10, 8, 2]
[7, 9, 2]
[8, 9, 2]
[9, 9, 2]
[10, 9, 2]
[8, 10, 2]
[9, 10, 2]
[10, 10, 2]
[2, 1, 3]
[3, 1, 3]
[4, 1, 3]
[1, 2, 3]
[2, 2, 3]
[3, 2, 3]
[4, 2, 3]
[5, 2, 3]
[1, 3, 3]
[2, 3, 3]
[3, 3, 3]
[4, 3, 3]
[5, 3, 3]
[6, 3, 3]
[1, 4, 3]
[2, 4, 3]
[3, 4, 3]
[4, 4, 3]
[5, 4, 3]
[6, 4, 3]
[7, 4, 3]
[2, 5, 3]
[3, 5, 3]
[4, 5, 3]
[5, 5, 3]
[6, 5, 3]
[7, 5, 3]
[8, 5, 3]
[3, 6, 3]
[4, 6, 3]
[5, 6, 3]
[6, 6, 3]
[7, 6, 3]
[8, 6, 3]
[9, 6, 3]
[4, 7, 3]
[5, 7, 3]
[6, 7, 3]
[7, 7, 3]
[8, 7, 3]
[9, 7, 3]
[10, 7, 3]
[5, 8, 3]
[6, 8, 3]
[7, 8, 3]
[8, 8, 3]
[9, 8, 3]
[10, 8, 3]
[6, 9, 3]
[7, 9, 3]
[8, 9, 3]
[9, 9, 3]
[10, 9, 3]
[7, 10, 3]
[8, 10, 3]
[9, 10, 3]
[10, 10, 3]
[3, 1, 4]
[4, 1, 4]
[5, 1, 4]
[2, 2, 4]
[3, 2, 4]
[4, 2, 4]
[5, 2, 4]
[6, 2, 4]
[1, 3, 4]
[2, 3, 4]
[3, 3, 4]
[4, 3, 4]
[5, 3, 4]
[6, 3, 4]
[7, 3, 4]
[1, 4, 4]
[2, 4, 4]
[3, 4, 4]
[4, 4, 4]
[5, 4, 4]
[6, 4, 4]
[7, 4, 4]
[8, 4, 4]
[1, 5, 4]
[2, 5, 4]
[3, 5, 4]
[4, 5, 4]
[5, 5, 4]
[6, 5, 4]
[7, 5, 4]
[8, 5, 4]
[9, 5, 4]
[2, 6, 4]
[3, 6, 4]
[4, 6, 4]
[5, 6, 4]
[6, 6, 4]
[7, 6, 4]
[8, 6, 4]
[9, 6, 4]
[10, 6, 4]
[3, 7, 4]
[4, 7, 4]
[5, 7, 4]
[6, 7, 4]
[7, 7, 4]
[8, 7, 4]
[9, 7, 4]
[10, 7, 4]
[4, 8, 4]
[5, 8, 4]
[6, 8, 4]
[7, 8, 4]
[8, 8, 4]
[9, 8, 4]
[10, 8, 4]
[5, 9, 4]
[6, 9, 4]
[7, 9, 4]
[8, 9, 4]
[9, 9, 4]
[10, 9, 4]
[6, 10, 4]
[7, 10, 4]
[8, 10, 4]
[9, 10, 4]
[10, 10, 4]
[4, 1, 5]
[5, 1, 5]
[6, 1, 5]
[3, 2, 5]
[4, 2, 5]
[5, 2, 5]
[6, 2, 5]
[7, 2, 5]
[2, 3, 5]
[3, 3, 5]
[4, 3, 5]
[5, 3, 5]
[6, 3, 5]
[7, 3, 5]
[8, 3, 5]
[1, 4, 5]
[2, 4, 5]
[3, 4, 5]
[4, 4, 5]
[5, 4, 5]
[6, 4, 5]
[7, 4, 5]
[8, 4, 5]
[9, 4, 5]
[1, 5, 5]
[2, 5, 5]
[3, 5, 5]
[4, 5, 5]
[5, 5, 5]
[6, 5, 5]
[7, 5, 5]
[8, 5, 5]
[9, 5, 5]
[10, 5, 5]
[1, 6, 5]
[2, 6, 5]
[3, 6, 5]
[4, 6, 5]
[5, 6, 5]
[6, 6, 5]
[7, 6, 5]
[8, 6, 5]
[9, 6, 5]
[10, 6, 5]
[2, 7, 5]
[3, 7, 5]
[4, 7, 5]
[5, 7, 5]
[6, 7, 5]
[7, 7, 5]
[8, 7, 5]
[9, 7, 5]
[10, 7, 5]
[3, 8, 5]
[4, 8, 5]
[5, 8, 5]
[6, 8, 5]
[7, 8, 5]
[8, 8, 5]
[9, 8, 5]
[10, 8, 5]
[4, 9, 5]
[5, 9, 5]
[6, 9, 5]
[7, 9, 5]
[8, 9, 5]
[9, 9, 5]
[10, 9, 5]
[5, 10, 5]
[6, 10, 5]
[7, 10, 5]
[8, 10, 5]
[9, 10, 5]
[10, 10, 5]
[5, 1, 6]
[6, 1, 6]
[7, 1, 6]
[4, 2, 6]
[5, 2, 6]
[6, 2, 6]
[7, 2, 6]
[8, 2, 6]
[3, 3, 6]
[4, 3, 6]
[5, 3, 6]
[6, 3, 6]
[7, 3, 6]
[8, 3, 6]
[9, 3, 6]
[2, 4, 6]
[3, 4, 6]
[4, 4, 6]
[5, 4, 6]
[6, 4, 6]
[7, 4, 6]
[8, 4, 6]
[9, 4, 6]
[10, 4, 6]
[1, 5, 6]
[2, 5, 6]
[3, 5, 6]
[4, 5, 6]
[5, 5, 6]
[6, 5, 6]
[7, 5, 6]
[8, 5, 6]
[9, 5, 6]
[10, 5, 6]
[1, 6, 6]
[2, 6, 6]
[3, 6, 6]
[4, 6, 6]
[5, 6, 6]
[6, 6, 6]
[7, 6, 6]
[8, 6, 6]
[9, 6, 6]
[10, 6, 6]
[1, 7, 6]
[2, 7, 6]
[3, 7, 6]
[4, 7, 6]
[5, 7, 6]
[6, 7, 6]
[7, 7, 6]
[8, 7, 6]
[9, 7, 6]
[10, 7, 6]
[2, 8, 6]
[3, 8, 6]
[4, 8, 6]
[5, 8, 6]
[6, 8, 6]
[7, 8, 6]
[8, 8, 6]
[9, 8, 6]
[10, 8, 6]
[3, 9, 6]
[4, 9, 6]
[5, 9, 6]
[6, 9, 6]
[7, 9, 6]
[8, 9, 6]
[9, 9, 6]
[10, 9, 6]
[4, 10, 6]
[5, 10, 6]
[6, 10, 6]
[7, 10, 6]
[8, 10, 6]
[9, 10, 6]
[10, 10, 6]
[6, 1, 7]
[7, 1, 7]
[8, 1, 7]
[5, 2, 7]
[6, 2, 7]
[7, 2, 7]
[8, 2, 7]
[9, 2, 7]
[4, 3, 7]
[5, 3, 7]
[6, 3, 7]
[7, 3, 7]
[8, 3, 7]
[9, 3, 7]
[10, 3, 7]
[3, 4, 7]
[4, 4, 7]
[5, 4, 7]
[6, 4, 7]
[7, 4, 7]
[8, 4, 7]
[9, 4, 7]
[10, 4, 7]
[2, 5, 7]
[3, 5, 7]
[4, 5, 7]
[5, 5, 7]
[6, 5, 7]
[7, 5, 7]
[8, 5, 7]
[9, 5, 7]
[10, 5, 7]
[1, 6, 7]
[2, 6, 7]
[3, 6, 7]
[4, 6, 7]
[5, 6, 7]
[6, 6, 7]
[7, 6, 7]
[8, 6, 7]
[9, 6, 7]
[10, 6, 7]
[1, 7, 7]
[2, 7, 7]
[3, 7, 7]
[4, 7, 7]
[5, 7, 7]
[6, 7, 7]
[7, 7, 7]
[8, 7, 7]
[9, 7, 7]
[10, 7, 7]
[1, 8, 7]
[2, 8, 7]
[3, 8, 7]
[4, 8, 7]
[5, 8, 7]
[6, 8, 7]
[7, 8, 7]
[8, 8, 7]
[9, 8, 7]
[10, 8, 7]
[2, 9, 7]
[3, 9, 7]
[4, 9, 7]
[5, 9, 7]
[6, 9, 7]
[7, 9, 7]
[8, 9, 7]
[9, 9, 7]
[10, 9, 7]
[3, 10, 7]
[4, 10, 7]
[5, 10, 7]
[6, 10, 7]
[7, 10, 7]
[8, 10, 7]
[9, 10, 7]
[10, 10, 7]
[7, 1, 8]
[8, 1, 8]
[9, 1, 8]
[6, 2, 8]
[7, 2, 8]
[8, 2, 8]
[9, 2, 8]
[10, 2, 8]
[5, 3, 8]
[6, 3, 8]
[7, 3, 8]
[8, 3, 8]
[9, 3, 8]
[10, 3, 8]
[4, 4, 8]
[5, 4, 8]
[6, 4, 8]
[7, 4, 8]
[8, 4, 8]
[9, 4, 8]
[10, 4, 8]
[3, 5, 8]
[4, 5, 8]
[5, 5, 8]
[6, 5, 8]
[7, 5, 8]
[8, 5, 8]
[9, 5, 8]
[10, 5, 8]
[2, 6, 8]
[3, 6, 8]
[4, 6, 8]
[5, 6, 8]
[6, 6, 8]
[7, 6, 8]
[8, 6, 8]
[9, 6, 8]
[10, 6, 8]
[1, 7, 8]
[2, 7, 8]
[3, 7, 8]
[4, 7, 8]
[5, 7, 8]
[6, 7, 8]
[7, 7, 8]
[8, 7, 8]
[9, 7, 8]
[10, 7, 8]
[1, 8, 8]
[2, 8, 8]
[3, 8, 8]
[4, 8, 8]
[5, 8, 8]
[6, 8, 8]
[7, 8, 8]
[8, 8, 8]
[9, 8, 8]
[10, 8, 8]
[1, 9, 8]
[2, 9, 8]
[3, 9, 8]
[4, 9, 8]
[5, 9, 8]
[6, 9, 8]
[7, 9, 8]
[8, 9, 8]
[9, 9, 8]
[10, 9, 8]
[2, 10, 8]
[3, 10, 8]
[4, 10, 8]
[5, 10, 8]
[6, 10, 8]
[7, 10, 8]
[8, 10, 8]
[9, 10, 8]
[10, 10, 8]
[8, 1, 9]
[9, 1, 9]
[10, 1, 9]
[7, 2, 9]
[8, 2, 9]
[9, 2, 9]
[10, 2, 9]
[6, 3, 9]
[7, 3, 9]
[8, 3, 9]
[9, 3, 9]
[10, 3, 9]
[5, 4, 9]
[6, 4, 9]
[7, 4, 9]
[8, 4, 9]
[9, 4, 9]
[10, 4, 9]
[4, 5, 9]
[5, 5, 9]
[6, 5, 9]
[7, 5, 9]
[8, 5, 9]
[9, 5, 9]
[10, 5, 9]
[3, 6, 9]
[4, 6, 9]
[5, 6, 9]
[6, 6, 9]
[7, 6, 9]
[8, 6, 9]
[9, 6, 9]
[10, 6, 9]
[2, 7, 9]
[3, 7, 9]
[4, 7, 9]
[5, 7, 9]
[6, 7, 9]
[7, 7, 9]
[8, 7, 9]
[9, 7, 9]
[10, 7, 9]
[1, 8, 9]
[2, 8, 9]
[3, 8, 9]
[4, 8, 9]
[5, 8, 9]
[6, 8, 9]
[7, 8, 9]
[8, 8, 9]
[9, 8, 9]
[10, 8, 9]
[1, 9, 9]
[2, 9, 9]
[3, 9, 9]
[4, 9, 9]
[5, 9, 9]
[6, 9, 9]
[7, 9, 9]
[8, 9, 9]
[9, 9, 9]
[10, 9, 9]
[1, 10, 9]
[2, 10, 9]
[3, 10, 9]
[4, 10, 9]
[5, 10, 9]
[6, 10, 9]
[7, 10, 9]
[8, 10, 9]
[9, 10, 9]
[10, 10, 9]
[9, 1, 10]
[10, 1, 10]
[8, 2, 10]
[9, 2, 10]
[10, 2, 10]
[7, 3, 10]
[8, 3, 10]
[9, 3, 10]
[10, 3, 10]
[6, 4, 10]
[7, 4, 10]
[8, 4, 10]
[9, 4, 10]
[10, 4, 10]
[5, 5, 10]
[6, 5, 10]
[7, 5, 10]
[8, 5, 10]
[9, 5, 10]
[10, 5, 10]
[4, 6, 10]
[5, 6, 10]
[6, 6, 10]
[7, 6, 10]
[8, 6, 10]
[9, 6, 10]
[10, 6, 10]
[3, 7, 10]
[4, 7, 10]
[5, 7, 10]
[6, 7, 10]
[7, 7, 10]
[8, 7, 10]
[9, 7, 10]
[10, 7, 10]
[2, 8, 10]
[3, 8, 10]
[4, 8, 10]
[5, 8, 10]
[6, 8, 10]
[7, 8, 10]
[8, 8, 10]
[9, 8, 10]
[10, 8, 10]
[1, 9, 10]
[2, 9, 10]
[3, 9, 10]
[4, 9, 10]
[5, 9, 10]
[6, 9, 10]
[7, 9, 10]
[8, 9, 10]
[9, 9, 10]
[10, 9, 10]
[1, 10, 10]
[2, 10, 10]
[3, 10, 10]
[4, 10, 10]
[5, 10, 10]
[6, 10, 10]
[7, 10, 10]
[8, 10, 10]
[9, 10, 10]
[10, 10, 10]
Test durumları şu mantığa göre oluşturuluyor: Maksimum değeri, diğer elemanların toplamından büyük olmayan her türlü durum bizim test durumumuzdur.
Kontrol mekanizmasını da uygulayalım:
def check(original, distributed, n, r, test_case, func):
info = f"Func: {func}, n = {n}, r = {r}, test_case = {test_case}"
if any(distributed[i] == distributed[i + 1] for i in range(len(distributed) - 1)):
raise ValueError(f"{info} - Two consecutive items are same!")
if any(distributed.count(k) != v for k, v in original.items()):
raise ValueError(f"{info} - There's a missing item.")
print(f"{info} - OK")
distribute_members
fonksiyonunun ismini dist1
, senin yazdığın fonksiyonların isimlerini de sırasıyla dist2
ve dist3
olarak değiştiriyorum:
def dist1(d: dict, x: str = "", order: list = None, d_copy: dict = None):
if not order:
order = []
if not d_copy:
d_copy = d.copy()
if not x:
x = max(d_copy, key=d_copy.get)
if d_copy[x] > sum({k: d_copy[k] for k in d_copy if k != x}.values()):
raise ValueError("The desired distributing cannot be made according to the given values.")
if without_x := {k: d_copy[k] for k in d_copy if k != x}:
y = max(without_x, key=without_x.get)
x, y = (x, y) if d_copy[x] > d_copy[y] else(y, x)
order += [x, y] * d_copy[y]
d_copy[x] -= d_copy[y]
d_copy.pop(y)
return dist1(d_copy, x, order)
else:
for i in range(d_copy[x]):
order = order[:i * 2] + [x] + order[i * 2:]
return order
def dist2(d):
d = d.copy()
ans = []
while True:
d = {k: v for k, v in d.items() if v > 0}
groups = list(d.keys())
if len(groups) == 0:
break
if len(groups) >= 2:
x, y = groups[0], groups[1]
if len(ans) > 0 and ans[-1] == x:
x, y = y, x
ans.append(x)
ans.append(y)
d[x] -= 1
d[y] -= 1
else:
x = groups[0]
def ins():
for i in range(len(ans)):
if (True if i == 0 else ans[i - 1] != x) and (True if i == len(ans) - 1 else ans[i] != x):
ans.insert(i, x)
d[x] -= 1
return
raise ValueError("Impossible")
ins()
return ans
def dist3(d):
d = d.copy()
ans = []
while True:
ds = sorted(d.items(), key=lambda kv: -kv[1])
if all(map(lambda kv: kv[1] == ds[0][1], ds)):
break
ans.append(ds[0][0])
d[ds[0][0]] -= 1
if ds[1][1] > 0:
ans.append(ds[1][0])
d[ds[1][0]] -= 1
return ans
Şimdi test
fonksiyonunu oluşturuyorum:
from string import ascii_lowercase
def test():
# Test, 3 elemanlı bir sözlük ile başlayacak...
for r in range(3, 11):
# Sözlükteki r sayıdaki elemanların sayısal değerinin toplamını 10 ile başlatalım.
for n in range(10, 100):
# Yukardaki duruma göre kaç tane test durumumuz varsa hepsini deneyelim:
for test_case in test_cases(n=n, r=r):
d = {ascii_lowercase[index]: k for index, k in enumerate(test_case)}
check(d, dist1(d), n, r, test_case, func="dist1")
check(d, dist2(d), n, r, test_case, func="dist2")
check(d, dist3(d), n, r, test_case, func="dist3")
Sonra da test
’i çağırıyorum ve şu sonucu aldım:
Func: dist1, n = 10, r = 3, test_case = [1, 1, 1] - OK
Func: dist2, n = 10, r = 3, test_case = [1, 1, 1] - OK
Traceback (most recent call last):
File "C:\Users\tanberk\Desktop\Python\v1.py", line 103, in <module>
test()
File "C:\Users\tanberk\Desktop\Python\v1.py", line 100, in test
check(d, dist3(d), n, r, test_case, func="dist3")
File "C:\Users\tanberk\Desktop\Python\v1.py", line 76, in check
raise ValueError(f"{info} - There's a missing item.")
ValueError: Func: dist3, n = 10, r = 3, test_case = [1, 1, 1] - There's a missing item.
Şöyle yapıyorum şimdi:
from string import ascii_lowercase
def test():
# Test, 3 elemanlı bir sözlük ile başlayacak...
c = 0
for r in range(3, 11):
# Sözlükteki i sayıdaki elemanların sayısal değerinin toplamı 10 ile başlatalım.
for n in range(10, 100):
# Yukardaki duruma göre kaç tane test durumumuz varsa hepsini deneyelim:
for test_case in test_cases(n=n, r=r):
d = {ascii_lowercase[index]: k for index, k in enumerate(test_case)}
check(d, dist1(d), n, r, test_case, func="dist1")
check(d, dist2(d), n, r, test_case, func="dist2")
try:
check(d, dist3(d), n, r, test_case, func="dist3")
except ValueError:
c += 1
print(f"dist3 hata sayısı: {c}")
Şöyle göstereyim:
[...]
dist3 hata sayısı: 101278
Func: dist1, n = 30, r = 3, test_case = [21, 9, 20] - OK
Func: dist2, n = 30, r = 3, test_case = [21, 9, 20] - OK
dist3 hata sayısı: 101279
Func: dist1, n = 30, r = 3, test_case = [22, 9, 20] - OK
Func: dist2, n = 30, r = 3, test_case = [22, 9, 20] - OK
dist3 hata sayısı: 101280
Func: dist1, n = 30, r = 3, test_case = [23, 9, 20] - OK
Func: dist2, n = 30, r = 3, test_case = [23, 9, 20] - OK
[...]
Gözlemlediğim kadarıyla, dist1
ve dist2
fonksiyonları, n=50 ve r=3 test koşulundaki bütün durumlara kadar hatasız gittiler.