164 lines
3.1 KiB
C
164 lines
3.1 KiB
C
/* ex2-c: Advent2020 game, day 14/game 2
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
struct memcell {
|
|
unsigned long long num;
|
|
unsigned long long val;
|
|
struct memcell *next; /* if collision */
|
|
};
|
|
struct hashtable {
|
|
struct memcell *first;
|
|
};
|
|
|
|
#define HASHSIZE 1024
|
|
#define HASH(i) ((i)%HASHSIZE)
|
|
|
|
static struct hashtable mem[HASHSIZE];
|
|
static char maskstr[128];
|
|
static unsigned long long exp[128];
|
|
|
|
struct memcell *get_cell(cell)
|
|
unsigned long long cell;
|
|
{
|
|
struct memcell *p=mem[HASH(cell)].first;
|
|
|
|
while (p && p->num != cell)
|
|
p=p->next;
|
|
return p;
|
|
}
|
|
|
|
struct memcell *set_cell(cell, val)
|
|
unsigned long long cell;
|
|
unsigned long long val;
|
|
{
|
|
struct memcell *p=get_cell(cell);
|
|
unsigned hash=HASH(cell);
|
|
|
|
if (!p) {
|
|
p=malloc(sizeof (struct memcell));
|
|
p->next=mem[hash].first;
|
|
mem[hash].first=p;
|
|
}
|
|
p->num=cell;
|
|
p->val=val;
|
|
return p;
|
|
}
|
|
|
|
unsigned long long print_cells()
|
|
{
|
|
unsigned i;
|
|
unsigned long long res=0;
|
|
struct memcell *p;
|
|
|
|
puts("CELLS :");
|
|
for (i=0; i<HASHSIZE; ++i) {
|
|
p=mem[i].first;
|
|
while (p) {
|
|
printf("[%llu]=%llu\n", p->num, p->val);
|
|
res+=p->val;
|
|
p=p->next;
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
unsigned long long calc_cells()
|
|
{
|
|
unsigned i;
|
|
unsigned long long res=0;
|
|
struct memcell *p;
|
|
|
|
for (i=0; i<HASHSIZE; ++i) {
|
|
p=mem[i].first;
|
|
while (p) {
|
|
res+=p->val;
|
|
p=p->next;
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
unsigned long long ormask(str)
|
|
char *str;
|
|
{
|
|
char *p;
|
|
unsigned long long mask=0, exp=1;
|
|
|
|
for (p=str+strlen(str)-1; p>=str; p--, exp<<=1)
|
|
if (*p == '1')
|
|
mask+=exp;
|
|
return mask;
|
|
}
|
|
|
|
unsigned long long andmask(str)
|
|
char *str;
|
|
{
|
|
char *p;
|
|
unsigned long long mask=0, exp=1;
|
|
|
|
for (p=str+strlen(str)-1; p>=str; p--, exp<<=1)
|
|
if (*p != 'X')
|
|
mask+=exp;
|
|
return mask;
|
|
}
|
|
|
|
void print_exp()
|
|
{
|
|
int i;
|
|
for (i=0; exp[i]; ++i) {
|
|
printf("%2d: %llu", i, exp[i]);
|
|
}
|
|
|
|
}
|
|
|
|
void calc_masks(mempos, val, cur)
|
|
unsigned long mempos, val;
|
|
int cur;
|
|
{
|
|
unsigned long long mask=exp[cur];
|
|
|
|
if (mask == 0) {
|
|
set_cell(mempos, val);
|
|
return;
|
|
}
|
|
calc_masks(mempos, val, cur+1);
|
|
calc_masks(mempos+mask, val, cur+1);
|
|
}
|
|
|
|
int main(ac, av)
|
|
int ac;
|
|
char **av;
|
|
{
|
|
char line[1024];
|
|
unsigned long long val, mempos, or, and;
|
|
int i=0, j;
|
|
|
|
while (fgets(line, sizeof line, stdin)) {
|
|
if (!strncmp(line, "mask", 4)) {
|
|
sscanf(line, "%*[^01X]%s", maskstr);
|
|
or=ormask(maskstr);
|
|
and=andmask(maskstr);
|
|
val=1; j=0;
|
|
for (i=strlen(maskstr)-1; i>=0; --i) {
|
|
if (maskstr[i]=='X') {
|
|
exp[j]=val;
|
|
j++;
|
|
}
|
|
|
|
val<<=1;
|
|
}
|
|
exp[j]=0;
|
|
} else {
|
|
sscanf(line, "%*[^0-9]%llu] = %llu", &mempos, &val);
|
|
mempos=(mempos|or)∧
|
|
calc_masks(mempos, val, 0);
|
|
}
|
|
}
|
|
printf("%s : res=%llu\n", *av, calc_cells());
|
|
exit (0);
|
|
}
|