BLT: Difference between revisions

678 bytes added ,  2 years ago
m
no edit summary
mNo edit summary
mNo edit summary
Line 2:
 
''NB: Unfortunately, some of the asterisks display as bullet-points below; this artifacting is due to the way MediaWiki processes free text. I'll try to fix it at some point.'' -S [[User:Ftwm|Ftwm]] ([[User talk:Ftwm|talk]]) 11:18, 17 December 2021 (GMT)
 
<code>
 
/** This program is (C) E M Drayton 2021. Modification is prohibited.
*** You are free to compile and run it for non-commercial purposes.
**/
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
 
/**
#include <math.h>
**/
 
#include <assert.h>
static void (die)(const int line);
#define die() die(__LINE__);
 
#define C 20
#define C_ 32
#define H_(X) (#X)
#define H(X) H_(X)
 
/*\ \*/ /*\ \*/ /*\ \*/
 
static long lines(const char *const t_, FILE *const e) {
const char *t= t_, *u;
long l= 0;
 
for (; (u= strchr(t, '\n')) != 0; t= u+1) ++l;
 
!e || fprintf(e, " %ld lines in %ld octets\n", l, (long)strlen(t_));
 
return l;
}
 
/*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/
 
struct rec; typedef struct rec rec; struct rec {
unsigned char *p;
int c;
long d;
short *v;
unsigned char **w;
short a[1][C_][C_];
};
 
#define p_ (r->p)
#define c_ (r->c)
#define d_ (r->d)
#define v_ (r->v)
#define w_ (r->w)
#define a_ (r->a)
 
/*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/
 
static void eliminate(const rec *const r, const int c) {
unsigned char **p= w_, *q;
const int k= tolower(c);
long l= d_+1;
 
while (--l) if ((q= *++p) == 0 || (q= strchr(q, c)) == 0); else *q= k;
}
 
/*\ \*/ /*\ \*/ /*\ \*/
 
static unsigned long losers_(const short (*p)[C_], const int c, unsigned long v) {
unsigned long u= (1ul<<c)-1, t;
unsigned n= 0u-1;
int i= C_-c;
 
++p;
while (u) {
u>>= 1; t= u+1;
if (!(v&t)) ++i; else {
unsigned f= (*p)[-++i];
 
if (f>n) v^= t; else if (f<n) { v&= t|u; n= f; } else;
}
}
assert(i==C_); /* fprintf(stderr, " %0*loo", (c+2)/3+1, v); /**/
/*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/
 
return v;
struct rec; typedef struct rec rec; struct rec {
}
unsigned char *p;
 
static unsigned long losers(const rec *const r, unsigned long v) {
const short (*p)[C_]= a_[1];
unsigned long w= v;
 
while (w && p > *a_) {
v= w; w= losers_(--p, c_, v);
}
 
return v;
}
 
/*\ \*/ /*\ \*/ /*\ \*/
 
static void count(rec *const r, FILE *e) {
long l;
 
memset(a_, 0, sizeof *a_);
 
for (l= d_+1; --l;) {
short (*f)[C_]= a_[1];
unsigned h= v_[l];
const unsigned char *s= w_[l];
int c;
long d;
 
short *v;
assert(h); /* fprintf(stderr, " %u: '%s' ", h, s); /**/
unsigned char **w;
 
short a[1][C_][C_];
while ((c= *++s)!=0) if (!isupper(c)); else (*--f)[c-'A']+= h;
};
#define p_ (r->p)
#define c_ (r->c)
#define d_ (r->d)
#define v_ (r->v)
#define w_ (r->w)
#define a_ (r->a)
/*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/
static void eliminate(const rec *const r, const int c) {
unsigned char **p= w_, *q;
const int k= tolower(c);
long l= d_+1;
while (--l) if ((q= *++p) == 0 || (q= strchr(q, c)) == 0); else *q= k;
}
/* putc('\n', stderr); /**/
/*\ \*/ /*\ \*/ /*\ \*/
 
if (!e); else { int i, j; const int c= c_;
static unsigned long losers_(const short (*p)[C_], const int c, unsigned long v) {
 
!eunsigned ||long u= fputs("PREFS:1ul<<c)-\n"1, e)t;
unsigned n= 0u-1;
for (j= -1+C_-c; ++j < C_; !e || putc('\n', e))
forint (i= C_-1; ++i < c; !e || putc(',', e))
if (!(*a_)[j][i]); else { static char a[9];
++p;
sprintf(a, "%d", (*a_)[j][i]);
while (u) {
!e || fprintf(e, "%5s", a);
u>>= 1; t= u+1;
if (!(v&t)) ++i; else {
unsigned f= (*p)[-++i];
if (f>n) v^= t; else if (f<n) { v&= t|u; n= f; } else;
}
}
!eassert(i==C_); ||/* fputsfprintf(stderr, "END %0*loo", (OKc+2)\n\n"/3+1, ev); /**/
return v;
}
}
static unsigned long losers(const rec *const r, unsigned long v) {
#define recount count
const short (*p)[C_]= a_[1];
 
unsigned long w= v;
/*\ \*/ /*\ \*/ /*\ \*/
 
while (w && p > *a_) {
#undef NDEBUG
v= w; w= losers_(--p, c_, v);
/** Using assert() to report runtime errors is, admittedly, very fckg lazy. -EMD
}
**/
#include <assert.h>
return v;
 
static void (die)(int line) {
 
if (line); else {
fprintf(stderr, "\n\nThe C program '%s' reads generic STV files but it only knows how to work out who won AV (ie single-seat) elections with a maximum of %s candidates, unfortunately. Try asking EMD for an upgraded version.\n", __FILE__, C==20? "twenty": H(C)); fflush(0);
assert(!"I'm too stupid to work this out, sorry.");
}
 
fprintf(stderr, "\n\nYour crappy wee computer doesn't have enough memory to run the C program '%s', which is why it gave up trying somewhere around line %d.\n", __FILE__, line); fflush(0);
assert(!"I'm shit out of memory, sorry.");
}
 
/*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/
 
/**
*** fscanf() first line and validate it completely
*** (basically a sanity check for the file)
*** fseek to the end and measure it
*** (sanity check the length???)
*** allocate and load
*** count the lines
*** allocate an Iliffe (or not?)
*** (no more allocs now!)
*** find the first non-digit/SP/CR/LF
*** count the lines from there and validate totals
**/
 
#ifdef E
#else
#define E stdout
#endif
#define E_ (!(E))
 
extern int main(int ac, const char *const *av) {
static rec r[1];
const char *s= av[ac-1];
FILE *f;
int c, e;
long d, l;
size_t z;
unsigned char *p;
 
for(e= 50; --e;) fputc('\n', stderr); /**/
 
errno= 0;
assert(ac >= 2);
f= fopen(s, "rb");
if (f); else { perror(s); return 0; }
assert(f && !ferror(f));
 
{ static int a[3]= { 0 }; int b;
 
fscanf(f, "%2d%*1[ ]%d%*1[\r]%*1[\n]%n", a+1, a+2, a);
 
c= a[1]; b= a[2]; e= *a; assert(e);
if (c<=C && c>=1 && b==1); else (die)(0);
assert(c<=C && c>=1 && b==1);
}
 
/*\ \*/ /*\ \*/ /*\ \*/
fseek(f, 0, SEEK_END); assert(!ferror(f));
z= ftell(f); assert(!ferror(f));
static void count(rec *const r, FILE *e) {
 
long l;
#define V 2
p= malloc(z+V); if (p); else die(); assert(p);
memset(a_, 0, sizeof *a_);
p+= V-(V>>1); p[-1]= '0'; p[z]= 0;
E_ || fprintf(E, "\nAllocated %ld octets OK\n", (long)z+V);
for (l= d_+1; --l;) {
#undef V
short (*f)[C_]= a_[1];
 
unsigned h= v_[l];
rewind(f); assert(!ferror(f));
const unsigned char *s= w_[l];
 
int c;
#define P ((const char *)(void *)p)
 
assert(h); /* fprintf(stderr, " %u: '%s' ", h, s); /**/
{ static const char k[]= " 0\r\n0\r\n";
size_t r= fread(p, z, 1, f);
while ((c= *++s)!=0) if (!isupper(c)); else (*--f)[c-'A']+= h;
 
}
if (!errno); else { perror(s); fflush(0); }
/* putc('\n', stderr); /**/
assert(!ferror(f)); assert(!feof(f)); assert(!errno); assert(r);
 
if (!e); else { int i, j; const int c= c_;
r= fgetc(f)-EOF; assert(!ferror(f)); assert(feof(f)); assert(!r);
fclose(f); assert(!errno);
!e || fputs("PREFS:-\n", e);
assert(!p[z]); assert(p[z-1]=='\n'); r= strlen(P); assert(r==z);
for (j= -1+C_-c; ++j < C_; !e || putc('\n', e))
 
for (i= -1; ++i < c; !e || putc(',', e))
#define K ((sizeof k) - 1)
if (!(*a_)[j][i]); else { static char a[9];
r= strspn(P, "01234567890 \r\n"); assert(isupper(p[r+(p[r]=='\"')]));
assert(r>K && !strncmp sprintf(P+(r-K)a, k"%d", K(*a_)[j][i]);
!e || fprintf(e, "%5s", a);
#undef K
}
 
d= lines !e || fputs(p+r,"END E(OK);\n\n", assert(d==c+1le);
}
l= lines(p, E)-d; d= l-2l; l+= c+3l;
}
#define recount count
 
/* assert(c==7); assert(d==516); assert(l==528); assert(e==5); /**/
/*\ \*/ /*\ \*/ /*\ \*/
 
{ short *v; unsigned char **w; ptrdiff_t y= sizeof(void *)+sizeof(short);
#undef NDEBUG
 
/** Using assert() to report runtime errors is, admittedly, very fckg lazy. -EMD
w= calloc(l, y); if (w); else die(); assert(w);
**/
v= (short *)(void *)(w+l);
#include p+= e; <assert(p[-1]=='\n');.h>
p_= p; c_= c; d_= d; v_= v; w_= w;
static void (die)(int line) {
E_ || fprintf(E, "\nAllocated %ld octets OK\n", l*y);
if (line); else {
fprintf(stderr, "\n\nThe C program '%s' reads generic STV files but it only knows how to work out who won AV (ie single-seat) elections with a maximum of %s candidates, unfortunately. Try asking EMD for an upgraded version.\n", __FILE__, C==20? "twenty": H(C)); fflush(0);
assert(!"I'm too stupid to work this out, sorry.");
}
 
fprintf(stderr, "\n\nYour crappy wee computer doesn't have enough memory to run the C program '%s', which is why it gave up trying somewhere around line %d.\n", __FILE__, line); fflush(0);
if (!errno); else { perror(s); fflush(0); }
assert(!errno"I'm shit out of memory, sorry.");
}
 
/*\ \*/ /*\ \*/ /*\ \*/
/*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/ /*\ \*/
 
E_ || fprintf(E, "\nProcessing %ld octets from file '%s'\n", (long)z, s);
/**
 
*** fscanf() first line and validate it completely
{ static int n[2]= { 0, 0 };
*** (basically a sanity check for the file)
int *q= n; const char *t= P; char *u; unsigned phase= 2u;
*** fseek to the end and measure it
char **p= (char **)(void *)w_;
*** (sanity check the length???)
short *v= v_;
*** allocate and load
 
*p=** 0;count *v=the 0;lines
*** allocate an Iliffe (or not?)
 
*** (no more allocs now!)
for (; (u= strchr(t, '\n')) != 0; t= u+1) {
*** find the first non-digit/SP/CR/LF
assert(u[-1]=='\r');
*** count the lines from there and validate totals
assert(u[-2]=='0' || phase==1u && u[-2]=='\"');
**/
if (u-t >= 3) ++*q;
else { phase>>= 1; assert(phase); assert(*q==d); ++q; }
#ifdef E
assert(u[-3]==' ' || phase==1u && (u[-2]==(u-t >= 3? '\"': '0')));
#else
assert(isdigit(u[-4]) || phase==1u);
#define E stdout
 
#endif
*u= 0; u[-1]= 0;
#define ifE_ (phase==1u!(E)) {
if (u[1]=='\"'); else { assert(!u[1]); assert(*q==c+1l); }
extern int main(int ac, const char *const *av) {
} else { assert(isdigit(u[1]));
static rec r[1];
 
const char *s= av[ac-1];
#if 0
FILE *f;
u[-2]= 0; /* u[-3]= 0; /**/ }
int c, e;
#else
long d, l;
{ char *const cp= (char *)((long)u-3ul|1ul);
size_t z;
unsigned short *const hp= (unsigned short *)(cp+1);
unsigned char *p;
 
*u= '0'; *cp= 0; *hp= 257;
for(e= 50; --e;) fputc('\n', stderr); /**/
/* TODO= assert something about all this (or get rid of it?) */
}}
errno= 0;
#endif
assert(ac >= 2);
 
f= fopen(s, "rb");
l= strtol(t, ++p, 10); assert(l>0 || !l && phase==1u);
if (f); else { perror(s); return 0; }
assert(l<=1999); /* sanity; 11 bits (lose?) */
assert(f && *++v= !ferror(shortf)l; assert(*v==l);
 
{ static ifint (**pa[3]==' ');{ else0 { assert(!l)}; continueint b; }
 
{fscanf(f, static char"%2d%*1[ ]%d%*e1[\r]%*1[\n]%n", a[101]+1, a+2, a);
int k= *++*p;
c= a[1]; charb= *qa[2]; e= *a; assert(e);
if (c<=C && c>=1 && b==1); else (die)(0);
 
assert(isdigit(k)c<=C && k!c>=1 && b=='0'1);
}
*q= ' '; *e= *p;
 
fseek(f, 0, SEEK_END); assert(!ferror(f));
do {
lz= strtolftell(*e,f); e, 10assert(!ferror(f));
if (l>0) {
#define V 2
assert(l<=C);
p= malloc(z+V); if (p); else die(); assert(p);
*++q= 'A'+c-(int)l;
p+= V-(V>>1); p[-1]= '0'; p[z]= 0;
} else assert(!l);
E_ || fprintf(E, "\nAllocated %ld }octets whileOK\n", (llong)z+V);
#undef V
 
*++q= 0; l= strlen(*p);
rewind(f); assert(!ferror(f));
sprintf(*p, "%*s", (int)l, a); *p+= l-(q-a);
#define P ((const char *)(void *)p)
{ static const char k[]= " 0\r\n0\r\n";
size_t r= fread(p, z, 1, f);
if (!errno); else { perror(s); fflush(0); }
assert(!ferror(f)); assert(!feof(f)); assert(!errno); assert(r);
r= fgetc(f)-EOF; assert(!ferror(f)); assert(feof(f)); assert(!r);
fclose(f); assert(!errno);
assert(!p[z]); assert(p[z-1]=='\n'); r= strlen(P); assert(r==z);
#define K ((sizeof k) - 1)
r= strspn(P, "01234567890 \r\n"); assert(isupper(p[r+(p[r]=='\"')]));
assert(r>K && !strncmp(P+(r-K), k, K));
#undef K
d= lines(p+r, E); assert(d==c+1l);
l= lines(p, E)-d; d= l-2l; l+= c+3l;
}
/* assert(c==7); assert(d==516); assert(l==528); assert(e==5); /**/
{ short *v; unsigned char **w; ptrdiff_t y= sizeof(void *)+sizeof(short);
w= calloc(l, y); if (w); else die(); assert(w);
v= (short *)(void *)(w+l);
p+= e; assert(p[-1]=='\n');
p_= p; c_= c; d_= d; v_= v; w_= w;
E_ || fprintf(E, "\nAllocated %ld octets OK\n", l*y);
}
if (!errno); else { perror(s); fflush(0); }
assert(!errno);
/*\ \*/ /*\ \*/ /*\ \*/
E_ || fprintf(E, "\nProcessing %ld octets from file '%s'\n", (long)z, s);
{ static int n[2]= { 0, 0 };
int *q= n; const char *t= P; char *u; unsigned phase= 2u;
char **p= (char **)(void *)w_;
short *v= v_;
*p= 0; *v= 0;
for (; (u= strchr(t, '\n')) != 0; t= u+1) {
assert(u[-1]=='\r');
assert(u[-2]=='0' || phase==1u && u[-2]=='\"');
if (u-t >= 3) ++*q;
else { phase>>= 1; assert(phase); assert(*q==d); ++q; }
assert(u[-3]==' ' || phase==1u && (u[-2]==(u-t >= 3? '\"': '0')));
assert(isdigit(u[-4]) || phase==1u);
*u= 0; u[-1]= 0;
if (phase==1u) {
if (u[1]=='\"'); else { assert(!u[1]); assert(*q==c+1l); }
} else { assert(isdigit(u[1]));
#if 0
u[-2]= 0; /* u[-3]= 0; /**/ }
#else
{ char *const cp= (char *)((long)u-3ul|1ul);
unsigned short *const hp= (unsigned short *)(cp+1);
*u= '0'; *cp= 0; *hp= 257;
/* TODO= assert something about all this (or get rid of it?) */
}}
#endif
l= strtol(t, ++p, 10); assert(l>0 || !l && phase==1u);
assert(l<=1999); /* sanity; 11 bits (lose?) */
*++v= (short)l; assert(*v==l);
if (**p==' '); else { assert(!l); continue; }
{ static char *e[1], a[101];
int k= *++*p;
char *q= a;
assert(isdigit(k) && k!='0');
*q= ' '; *e= *p;
do {
l= strtol(*e, e, 10);
if (l>0) {
assert(l<=C);
*++q= 'A'+c-(int)l;
} else assert(!l);
} while (l);
*++q= 0; l= strlen(*p);
sprintf(*p, "%*s", (int)l, a); *p+= l-(q-a);
}
}
E_ || fprintf(E, "\n%ld profiles, %ld strings\n", (long)n[0], (long)n[1]);
}
#undef P
E_ || fprintf(E, "\n%ld profiles, %ld strings\n", (long)n[0], (long)n[1]);
}
/*\ \*/ /*\ \*/ /*\ \*/
#undef P
 
{ unsigned long v= (1ul<<c)-1ul, w= 0; int k; unsigned once= 2u;
/*\ \*/ /*\ \*/ /*\ \*/
unsigned char *const *const s_= w_+d_+c_+1;
 
{ unsigned long v= (1ul<<c)-1ul, w= 0; int k; unsigned once= 2u;
puts("\n--\n\nRESULTS:\n"); /**/
unsigned char *const *const s_= w_+d_+c_+1;
 
do {
puts("\n--\n\nRESULTS:\n"); /**/
for (k= 'A'; w>>= 1; ++k)
 
if (~(unsigned)w&1u);
do {
for (k= 'A'; w>>= 1;else ++k){
printf(" #%d('%c') lost ('%s')\n", 'A'+c_-k, k, s_['A'-k]);
if (~(unsigned)w&1u);
else { eliminate(r, k);
}
printf(" #%d('%c') lost ('%s')\n", 'A'+c_-k, k, s_['A'-k]);
if (!(once>>= 1)) recount(r, 0); else eliminatecount(r, kE);
}w= losers(r, v); v^= w; w<<= 1;
} while (v);
if (!(once>>= 1)) recount(r, 0); else count(r, E);
w= losers(r, v); v^= w; w<<= 1;
printf("\nResult (%0*loo) in '%s':\n\n", (c+2)/3+1, w>>1, s_[1]); /**/
} while (v);
 
printf("\nResult for (%0*loo) ink= '%sA':\n\n", (c+2)/3+1,; w>>1,= s_[1]); /**/++k)
if (~(unsigned)w&1u);
 
else { printf(" #%d('%c') won ('%s')\n", 'A'+c_-k, k, s_['A'-k]); }
for (k= 'A'; w>>= 1; ++k)
}
if (~(unsigned)w&1u);
else { printf(" #%d('%c') won ('%s')\n", 'A'+c_-k, k, s_['A'-k]); }
return EXIT_SUCCESS;
}
 
#undef E
return EXIT_SUCCESS;
#undef C
}
#undef C_
 
#undef EH
#undef CH_
#undef C_
#undef H
#undef H_
</code>