2
1
Fork 0

Day 14/C: Add bignum version

This commit is contained in:
Mia Herkt 2021-12-15 02:17:07 +01:00
parent 4a6bfff4c0
commit e753594336
Signed by: mia
GPG Key ID: 72E154B8622EC191
1 changed files with 108 additions and 0 deletions

108
14/solution_bignum.c Normal file
View File

@ -0,0 +1,108 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <gmp.h>
/* we can pack the pairs into integers… */
#define P(a,b) (( (a-'A')<<6 )| (b-'A'))
/* …and use them as keys for a lookup table */
enum {maxk=P('Z'+1,'Z')};
MP_INT counts[maxk], tcounts[maxk];
void pcounts(int c) {
int i,k;
MP_INT min,max,n;
mpz_init(&min);
mpz_init(&max);
mpz_init(&n);
for(i='A';i<='Z';i++) {
k=P(i,'z');
mpz_set(&n, &counts[k]);
if (mpz_cmp_ui(&n,0)){
if (!mpz_cmp_ui(&min,0))
mpz_set(&min,&n);
if (mpz_cmp(&n, &min) < 0) mpz_set(&min,&n);
else if (mpz_cmp(&n, &max) > 0) mpz_set(&max,&n);
}
}
mpz_sub(&n, &max, &min);
char *r = mpz_get_str(NULL, 10, &n);
size_t rlen = strlen(r);
if (rlen > 20)
printf("%d iterations: %lu digits %.10s...%s\n", c, rlen, r, r+(rlen-10));
else
printf("%d iterations: %s\n", c, r);
free(r);
mpz_clear(&min);
mpz_clear(&max);
mpz_clear(&n);
}
int main(int argc, char **argv) {
char tmpl[128], rules[128][3]={0};
int i,j,k, maxiter=40;
MP_INT n;
if (argc > 1)
sscanf(argv[1], "%d",&maxiter);
mpz_init(&n);
for(i=0;i<maxk;i++){
mpz_init(&counts[i]);
mpz_init(&tcounts[i]);
}
scanf("%127[A-Z]\n", tmpl);
for(i=0;tmpl[i];i++){
/* set initial counts for pairs and single chars */
if(i)
mpz_add_ui(&counts[P(tmpl[i-1],tmpl[i])],&counts[P(tmpl[i-1],tmpl[i])], 1);
/* use the same LUT for both */
mpz_add_ui(&counts[P(tmpl[i],'z')],&counts[P(tmpl[i],'z')], 1);
}
for(i=0;scanf("%c%c -> %c\n",
&rules[i][0], &rules[i][1], &rules[i][2])==3;i++);
for(i=0;i<maxiter;i++) {
/* reset temp LUT */
for(j=0;j<maxk;j++){
mpz_set_ui(&tcounts[j],0);
}
/* apply each rule */
for(j=0;rules[j][0];j++) {
k=P(rules[j][0],rules[j][1]);
mpz_set(&n, &counts[k]);
if (mpz_cmp_ui(&n,0)) {
mpz_set_ui(&counts[k],0);
/* single chars can be updated here */
k=P(rules[j][2],'z');
mpz_add(&counts[k],&counts[k], &n);
/* pairs must be counted independently */
k=P(rules[j][0],rules[j][2]);
mpz_add(&tcounts[k],&tcounts[k],&n);
k=P(rules[j][2],rules[j][1]);
mpz_add(&tcounts[k],&tcounts[k],&n);
}
}
/* commit temp results */
for(j=0;rules[j][0];j++) {
k=P(rules[j][0],rules[j][2]);
mpz_set(&counts[k], &tcounts[k]);
k=P(rules[j][2],rules[j][1]);
mpz_set(&counts[k], &tcounts[k]);
}
if (i==maxiter-1) {
pcounts(i+1);
} else if (!((i+1)%500)) {
printf("\033[G%.0f%\033[G",((i+1.0)/maxiter)*100);
fflush(stdout);
}
}
mpz_clear(&n);
}