docs: add teaching examples and video project
This commit is contained in:
parent
e93bc20b0a
commit
7a06f94577
42 changed files with 8022 additions and 0 deletions
85
show/video/check_lower35.py
Normal file
85
show/video/check_lower35.py
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
"""Check the narrated identities against direct first Java Random outputs.
|
||||
|
||||
This checks first-output arithmetic, not exhaustive rejection/redraw coverage.
|
||||
Run with: uv run python check_lower35.py
|
||||
"""
|
||||
import random
|
||||
|
||||
A = 0x5DEECE66D
|
||||
C = A ^ 987234911
|
||||
MASK48 = (1 << 48) - 1
|
||||
M = 8192
|
||||
|
||||
|
||||
def first_output(seed, term):
|
||||
# Keep the two original initialization XORs separate from the derivation.
|
||||
raw_seed = (seed + term) & MASK48
|
||||
state = ((raw_seed ^ 987234911) ^ A) & MASK48
|
||||
return ((A * state + 11) & MASK48) >> 17
|
||||
|
||||
|
||||
def j32(value):
|
||||
return ((value + (1 << 31)) % (1 << 32)) - (1 << 31)
|
||||
|
||||
|
||||
def coordinate_term(x, z):
|
||||
return j32(4987142*x*x) + j32(5947611*x) + 4392871*j32(z*z) + j32(389711*z)
|
||||
|
||||
|
||||
def check_case(lower, term):
|
||||
q0 = first_output(lower, term)
|
||||
r, b = q0 % (1 << 18), q0 >> 18
|
||||
for h in range(M):
|
||||
t = A*h % M
|
||||
direct = first_output(lower + (h << 35), term)
|
||||
derived = r + (1 << 18)*((b+t) % M)
|
||||
assert direct == derived, (lower, term, h)
|
||||
residue = (r-b + (2 if t >= M-b else 0)) % 5
|
||||
allowed = (r % 2 == 0 and t % 5 == residue)
|
||||
assert allowed == (direct % 10 == 0), (lower, term, h)
|
||||
assert 4965*t % M == h
|
||||
return r, b
|
||||
|
||||
|
||||
def main():
|
||||
assert C.bit_length() == 35
|
||||
assert A*4965 % M == 1
|
||||
# At a 34-bit boundary C still flips an unknown bit: simple translation fails.
|
||||
assert (((1 << 34) ^ C) & MASK48) != ((C+(1 << 34)) & MASK48)
|
||||
rng = random.Random(35013)
|
||||
cases = [(0, 0), ((1 << 35)-1, -1), (0, MASK48),
|
||||
((1 << 35)-1, (1 << 35)+1)]
|
||||
# Real Java-wrapped terms, including signed int limits and negative offsets.
|
||||
for x, z in [(51069, 419124), (-1, -1), (2**31-1, -2**31), (0, 0)]:
|
||||
cases.append((rng.randrange(1 << 35), coordinate_term(x, z)))
|
||||
relative = coordinate_term(x+1 if x < 2**31-1 else x-1, z)-coordinate_term(x, z)
|
||||
cases.append((rng.randrange(1 << 35), relative))
|
||||
cases += [(rng.randrange(1 << 35), rng.randrange(-2**63, 2**63)) for _ in range(20)]
|
||||
for lower, term in cases:
|
||||
check_case(lower, term)
|
||||
# Find and verify a whole 25-cell intersection, with an actual planted seed.
|
||||
lower = 10565146255
|
||||
terms = [coordinate_term(51069+dx, 419124+dz)-coordinate_term(51069, 419124)
|
||||
for dx in range(5) for dz in range(5)]
|
||||
profiles = [(first_output(lower, d) % (1 << 18), first_output(lower, d) >> 18)
|
||||
for d in terms]
|
||||
points = sorted({0, M, *(M-b for _, b in profiles)})
|
||||
ts = []
|
||||
if all(r % 2 == 0 for r, _ in profiles):
|
||||
for start, stop in zip(points, points[1:]):
|
||||
residues = {(r-b+(2 if start >= M-b else 0)) % 5 for r, b in profiles}
|
||||
if len(residues) == 1:
|
||||
residue = residues.pop()
|
||||
ts.extend(range(start+(residue-start) % 5, stop, 5))
|
||||
analytic = {4965*t % M for t in ts}
|
||||
direct = {h for h in range(M)
|
||||
if all(first_output(lower+(h << 35), d) % 10 == 0 for d in terms)}
|
||||
assert analytic == direct and direct
|
||||
assert 2 + (1 << 18)*((8190+4) % M) == 524290
|
||||
assert 4965*4 % M == 3476
|
||||
print(f'OK: {len(cases)*M} single-cell identities; '
|
||||
f'25-cell interval intersection equals all {M} high-bit trials ({len(direct)} candidates).')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue