2022 day 11 final (C)
This commit is contained in:
@@ -239,7 +239,15 @@ aoc.bash: res=54253
|
|||||||
time: 0:00.05 real, 0.04 user, 0.00 sys
|
time: 0:00.05 real, 0.04 user, 0.00 sys
|
||||||
context-switch: 1+1, page-faults: 0+268
|
context-switch: 1+1, page-faults: 0+268
|
||||||
|
|
||||||
|
aoc-c: res=54253
|
||||||
|
time: 0:00.00 real, 0.00 user, 0.00 sys
|
||||||
|
context-switch: 0+1, page-faults: 0+87
|
||||||
|
|
||||||
+++++++++++++++++ part 2
|
+++++++++++++++++ part 2
|
||||||
aoc.bash: res=13119526120
|
aoc.bash: res=13119526120
|
||||||
time: 0:16.49 real, 16.48 user, 0.00 sys
|
time: 0:16.49 real, 16.48 user, 0.00 sys
|
||||||
context-switch: 106+1, page-faults: 0+270
|
context-switch: 106+1, page-faults: 0+270
|
||||||
|
|
||||||
|
aoc-c: res=13119526120
|
||||||
|
time: 0:00.01 real, 0.01 user, 0.00 sys
|
||||||
|
context-switch: 13+1, page-faults: 0+87
|
||||||
|
@@ -71,11 +71,11 @@ assembly: aoc-c.s
|
|||||||
|
|
||||||
part1: aoc-c
|
part1: aoc-c
|
||||||
@$(TIME) aoc.bash -p 1 < $(INPUT) 2>&1
|
@$(TIME) aoc.bash -p 1 < $(INPUT) 2>&1
|
||||||
@#$(TIME) aoc-c -p 1 < $(INPUT)
|
@$(TIME) aoc-c -p 1 < $(INPUT)
|
||||||
|
|
||||||
part2: aoc-c
|
part2: aoc-c
|
||||||
@#$(TIME) aoc.bash -p 2 < $(INPUT) 2>&1
|
@$(TIME) aoc.bash -p 2 < $(INPUT) 2>&1
|
||||||
@#$(TIME) aoc-c -p 2 < $(INPUT)
|
@$(TIME) aoc-c -p 2 < $(INPUT)
|
||||||
|
|
||||||
ccls: $(CCLSFILE)
|
ccls: $(CCLSFILE)
|
||||||
|
|
||||||
|
@@ -23,110 +23,33 @@
|
|||||||
|
|
||||||
#define MAXMONKEYS 8
|
#define MAXMONKEYS 8
|
||||||
|
|
||||||
static int part1()
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int part2()
|
|
||||||
{
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct monkey {
|
typedef struct monkey {
|
||||||
char op; /* '+' or '*' */
|
char op; /* '+' or '*' */
|
||||||
long values[2]; /* formula operands */
|
long values[2]; /* formula operands */
|
||||||
|
uint visits; /* total visits */
|
||||||
int div; /* divisor */
|
int div; /* divisor */
|
||||||
struct list_head *dest[2]; /* destination monkey */
|
struct list_head *dest[2]; /* destination monkey */
|
||||||
uint visits; /* total visits */
|
|
||||||
struct list_head items; /* monkey items */
|
struct list_head items; /* monkey items */
|
||||||
} monkey_t;
|
} monkey_t;
|
||||||
|
|
||||||
typedef struct item {
|
typedef struct item {
|
||||||
int item;
|
long item;
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
} item_t;
|
} item_t;
|
||||||
|
|
||||||
static monkey_t monkeys[MAXMONKEYS];
|
|
||||||
static int nmonkeys;
|
|
||||||
static u64 lcm = 1, divide = 3;
|
|
||||||
static pool_t *pool_item;
|
static pool_t *pool_item;
|
||||||
|
|
||||||
|
/* TODO: the following 3 variables should not be global
|
||||||
|
*/
|
||||||
|
static monkey_t monkeys[MAXMONKEYS];
|
||||||
|
static int nmonkeys;
|
||||||
|
static u64 lcm = 1;
|
||||||
|
|
||||||
static void print_monkeys()
|
static char *getnth(char *buf, int n)
|
||||||
{
|
|
||||||
monkey_t *m = monkeys;
|
|
||||||
item_t *item;
|
|
||||||
|
|
||||||
for (int i = 0; i < nmonkeys; ++i, m++) {
|
|
||||||
printf("Monkey %d visits:%u\n\titems: ", i, m->visits);
|
|
||||||
list_for_each_entry(item, &m->items, list) {
|
|
||||||
printf("%d ", item->item);
|
|
||||||
}
|
|
||||||
putchar('\n');
|
|
||||||
printf("\ttrue=%ld false=%ld\n",
|
|
||||||
container_of(&m->dest[0], monkey_t, dest[0]) - monkeys,
|
|
||||||
container_of(&m->dest[0], monkey_t, dest[1]) - monkeys);
|
|
||||||
|
|
||||||
//printf("\top: %ld %c %ld\n", m->values[0], m->op, m->values[1]);
|
|
||||||
//printf("\tdiv = %d\n", m->div);
|
|
||||||
//printf("\ttrue:%ld false:%ld\n", m->dest[1]-monkeys, m->dest[0]-monkeys);
|
|
||||||
}
|
|
||||||
//putchar('\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
static u64 result()
|
|
||||||
{
|
|
||||||
u64 max1 = 0, max2 = 0;
|
|
||||||
monkey_t *m = monkeys;
|
|
||||||
for (int i = 0; i < nmonkeys; ++i, m++) {
|
|
||||||
if (m->visits > max1) {
|
|
||||||
max2 = max1;
|
|
||||||
max1 = m->visits;
|
|
||||||
} else if (m->visits > max2) {
|
|
||||||
max2 = m->visits;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("max1=%lu max2=%lu res=%lu", max1, max2, max1*max2);
|
|
||||||
return max1 * max2;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void inspect(monkey_t *m)
|
|
||||||
{
|
|
||||||
item_t *item, *tmp;
|
|
||||||
long op1, op2, res;
|
|
||||||
|
|
||||||
list_for_each_entry_safe(item, tmp, &m->items, list) {
|
|
||||||
list_del(&item->list);
|
|
||||||
//printf("Monkey %ld inspects %d\n", m - monkeys, item->item);
|
|
||||||
m->visits++;
|
|
||||||
printf("Monkey %ld inspect=%d visits=%d ", m - monkeys,
|
|
||||||
item->item, m->visits);
|
|
||||||
op1 = m->values[0] < 0 ? item->item: m->values[0];
|
|
||||||
op2 = m->values[1] < 0 ? item->item: m->values[1];
|
|
||||||
if (m->op == '+') {
|
|
||||||
res = op1 + op2;
|
|
||||||
} else {
|
|
||||||
res = op1 * op2;
|
|
||||||
}
|
|
||||||
printf("op1=%ld op2=%ld op=%c res=%ld ", op1, op2, m->op, res);
|
|
||||||
res = (res / divide) % lcm;
|
|
||||||
//printf("final=%ld div=%d dest=%ld\n", res, m->div,
|
|
||||||
// m->dest[!!(res % m->div)] - monkeys);
|
|
||||||
item->item = res;
|
|
||||||
//if (res % m->div) {
|
|
||||||
list_add_tail(&item->list, m->dest[!!(res % m->div)]);
|
|
||||||
//}
|
|
||||||
//print_monkeys();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *skip(char *buf, int n)
|
|
||||||
{
|
{
|
||||||
char *ret;
|
char *ret;
|
||||||
for (; n >= 0; n--) {
|
for (; n >= 0; n--) {
|
||||||
ret = strtok(buf, " ,\n");
|
ret = strtok(buf, " ,\n");
|
||||||
//printf("skip %d=%s\n", n, ret);
|
|
||||||
buf = NULL;
|
buf = NULL;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
@@ -141,86 +64,101 @@ static int parse()
|
|||||||
{
|
{
|
||||||
size_t alloc = 0;
|
size_t alloc = 0;
|
||||||
char *buf = NULL, *tok;
|
char *buf = NULL, *tok;
|
||||||
//ssize_t buflen;
|
|
||||||
monkey_t *m = monkeys;
|
monkey_t *m = monkeys;
|
||||||
|
|
||||||
while (getline(&buf, &alloc, stdin) > 0) {
|
while (getline(&buf, &alloc, stdin) > 0) {
|
||||||
printf("monkey %d\n", nmonkeys);
|
|
||||||
INIT_LIST_HEAD(&m->items);
|
INIT_LIST_HEAD(&m->items);
|
||||||
|
|
||||||
getline(&buf, &alloc, stdin); /* starting items */
|
getline(&buf, &alloc, stdin); /* starting items */
|
||||||
tok = skip(buf, 2);
|
tok = getnth(buf, 2);
|
||||||
printf("skip=%s\n", tok);
|
|
||||||
while (tok) {
|
while (tok) {
|
||||||
item_t *item = pool_get(pool_item);
|
item_t *item = pool_get(pool_item);
|
||||||
item->item = atoi(tok);
|
item->item = atoi(tok);
|
||||||
list_add_tail(&item->list, &m->items);
|
list_add_tail(&item->list, &m->items);
|
||||||
printf("val = %d\n", item->item);
|
|
||||||
tok = getnext();
|
tok = getnext();
|
||||||
}
|
}
|
||||||
|
|
||||||
getline(&buf, &alloc, stdin); /* operation */
|
getline(&buf, &alloc, stdin); /* operation */
|
||||||
tok = skip(buf, 3);
|
tok = getnth(buf, 3);
|
||||||
printf("skip=%s\n", tok);
|
|
||||||
//tok = getnext();
|
|
||||||
//printf("tok=%p %c\n", tok, *tok);
|
|
||||||
m->values[0] = (*tok == 'o') ? -1: atoi(tok); /* first operand */
|
m->values[0] = (*tok == 'o') ? -1: atoi(tok); /* first operand */
|
||||||
printf("val1 = %ld\n", m->values[0]);
|
|
||||||
//tok = getnext();
|
|
||||||
m->op = *getnext(); /* operator */
|
m->op = *getnext(); /* operator */
|
||||||
tok = getnext();
|
tok = getnext();
|
||||||
m->values[1] = *tok == 'o' ? -1: atoi(tok); /* second operand */
|
m->values[1] = *tok == 'o' ? -1: atoi(tok); /* second operand */
|
||||||
printf("val2 = %ld\n", m->values[1]);
|
|
||||||
|
|
||||||
getline(&buf, &alloc, stdin); /* divisible */
|
getline(&buf, &alloc, stdin); /* divisible */
|
||||||
tok=skip(buf, 3);
|
m->div = atoi(getnth(buf, 3));
|
||||||
//printf("skip div=%s\n", tok);
|
|
||||||
m->div = atoi(tok);
|
|
||||||
lcm *= m->div;
|
lcm *= m->div;
|
||||||
|
|
||||||
getline(&buf, &alloc, stdin); /* true */
|
getline(&buf, &alloc, stdin); /* true */
|
||||||
//puts(buf);
|
m->dest[0] = &(monkeys + atoi(getnth(buf, 5)))->items;
|
||||||
tok = skip(buf, 5);
|
|
||||||
//printf("skip true=%s\n", tok);
|
|
||||||
m->dest[0] = &(monkeys + atoi(tok))->items;
|
|
||||||
//printf("true = %ld\n", m->dest[0] - monkeys);
|
|
||||||
|
|
||||||
getline(&buf, &alloc, stdin); /* false */
|
getline(&buf, &alloc, stdin); /* false */
|
||||||
tok = skip(buf, 5);
|
m->dest[1] = &(monkeys + atoi(getnth(buf, 5)))->items;
|
||||||
//printf("skip false=%s\n", tok);
|
|
||||||
m->dest[1] = &(monkeys + atoi(tok))->items;
|
|
||||||
//printf("false = %ld\n", m->dest[1] - monkeys);
|
|
||||||
|
|
||||||
getline(&buf, &alloc, stdin); /* skip empty line */
|
getline(&buf, &alloc, stdin); /* skip empty line */
|
||||||
|
|
||||||
nmonkeys++;
|
nmonkeys++;
|
||||||
m++;
|
m++;
|
||||||
printf("\n");
|
|
||||||
//print_monkeys();
|
|
||||||
//exit(0);
|
|
||||||
}
|
}
|
||||||
printf("lcm = %ld\n", lcm);
|
|
||||||
print_monkeys();
|
|
||||||
free(buf);
|
free(buf);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static __always_inline void inspect(monkey_t *m, int divide)
|
||||||
|
{
|
||||||
|
item_t *item, *tmp;
|
||||||
|
long op1, op2;
|
||||||
|
|
||||||
|
list_for_each_entry_safe(item, tmp, &m->items, list) {
|
||||||
|
m->visits++;
|
||||||
|
/* I wonder if we could not find some mathematical properties to
|
||||||
|
* simplify the following three lines
|
||||||
|
*/
|
||||||
|
op1 = m->values[0] < 0 ? item->item: m->values[0];
|
||||||
|
op2 = m->values[1] < 0 ? item->item: m->values[1];
|
||||||
|
item->item = (((m->op == '+')? op1 + op2: op1 * op2) / divide ) % lcm;
|
||||||
|
list_move_tail(&item->list, m->dest[!!(item->item % m->div)]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static u64 doit(int rounds, int divide)
|
||||||
|
{
|
||||||
|
u64 max1 = 0, max2 = 0;
|
||||||
|
monkey_t *m = monkeys;
|
||||||
|
|
||||||
|
for (int r = 0; r < rounds; ++r)
|
||||||
|
for (int i = 0; i < nmonkeys; ++i)
|
||||||
|
inspect(monkeys + i, divide);
|
||||||
|
|
||||||
|
for (int i = 0; i < nmonkeys; ++i, m++) {
|
||||||
|
if (m->visits > max1) {
|
||||||
|
max2 = max1;
|
||||||
|
max1 = m->visits;
|
||||||
|
} else if (m->visits > max2) {
|
||||||
|
max2 = m->visits;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return max1 * max2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u64 part1()
|
||||||
|
{
|
||||||
|
return doit(20, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u64 part2()
|
||||||
|
{
|
||||||
|
return doit(10000, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int ac, char **av)
|
int main(int ac, char **av)
|
||||||
{
|
{
|
||||||
int part = parseargs(ac, av);
|
int part = parseargs(ac, av);
|
||||||
int rounds = part == 1? 20: 10000;
|
|
||||||
if (part == 2)
|
|
||||||
divide = 1;
|
|
||||||
pool_item = pool_create("item", 64, sizeof(item_t));
|
pool_item = pool_create("item", 64, sizeof(item_t));
|
||||||
|
|
||||||
parse();
|
parse();
|
||||||
for (int r = 0; r < rounds; ++r) {
|
printf("%s: res=%lu\n", *av, part == 1? part1(): part2());
|
||||||
for (int i = 0; i < nmonkeys; ++i) {
|
pool_destroy(pool_item);
|
||||||
inspect(monkeys + i);
|
|
||||||
}
|
|
||||||
printf("+++++++ after round %d\n", r + 1);
|
|
||||||
print_monkeys();
|
|
||||||
}
|
|
||||||
printf("%s: res=%lu\n", *av, result());
|
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user