Task 10 exercise a
This commit is contained in:
59
Uebung-03/find.py
Normal file
59
Uebung-03/find.py
Normal file
@@ -0,0 +1,59 @@
|
||||
import math
|
||||
import random
|
||||
from multiprocessing import Pool
|
||||
from typing import Optional, Iterable, Tuple
|
||||
|
||||
def gen_nums(n: int) -> list[int]:
|
||||
assert n > 0
|
||||
nums = list(range(2 ** n))
|
||||
random.shuffle(nums)
|
||||
return nums
|
||||
|
||||
def chunks(n: int, p: int) -> Iterable[Tuple[int, int]]:
|
||||
base, rem = divmod(n, p)
|
||||
start = 0
|
||||
for i in range(p):
|
||||
size = base + (1 if i < rem else 0)
|
||||
end = start + size
|
||||
yield start, end
|
||||
start = end
|
||||
|
||||
def t_find(args: Tuple[int, int, list[int], int]) -> Optional[int]:
|
||||
s, e, haystack, needle = args
|
||||
for i in range(s, e):
|
||||
if haystack[i] == needle:
|
||||
return i
|
||||
return None
|
||||
|
||||
def find(needle: int, haystack: list[int]) -> Optional[int]:
|
||||
size = len(haystack)
|
||||
assert size >= 1
|
||||
|
||||
procs = int(math.log2(size))
|
||||
ranges = list(chunks(size, procs))
|
||||
with Pool(processes=procs) as pool:
|
||||
res = pool.map(t_find, [(s, e, haystack, needle) for (s, e) in ranges])
|
||||
|
||||
for idx in res:
|
||||
if idx is not None:
|
||||
return idx
|
||||
return None
|
||||
|
||||
def fuzz_test(trials: int = 200, max_n: int = 16, seed: Optional[int] = None) -> None:
|
||||
if seed is not None:
|
||||
random.seed(seed)
|
||||
|
||||
for t in range(1, trials + 1):
|
||||
n = random.randint(1, max_n)
|
||||
arr = gen_nums(n)
|
||||
|
||||
idx_true = random.randrange(len(arr))
|
||||
needle = arr[idx_true]
|
||||
expected = idx_true
|
||||
|
||||
got = find(needle, arr)
|
||||
assert got == expected, f"[t={t}] Expected {expected}, got {got}; n={n}"
|
||||
|
||||
print(f"Fuzz OK: {trials} trials, max_n={max_n}")
|
||||
|
||||
fuzz_test(trials=1000, max_n=16)
|
||||
Reference in New Issue
Block a user