Compare commits
4 Commits
f54479189b
...
c949c64da2
Author | SHA1 | Date | |
---|---|---|---|
c949c64da2 | |||
357e8ce087 | |||
5cde9051ec | |||
111fde4fbd |
@@ -273,3 +273,17 @@ aoc.bash: res=399
|
|||||||
aoc-c: res=399
|
aoc-c: res=399
|
||||||
time: 0:00.00 real, 0.00 user, 0.00 sys
|
time: 0:00.00 real, 0.00 user, 0.00 sys
|
||||||
context-switch: 0+1, page-faults: 0+171
|
context-switch: 0+1, page-faults: 0+171
|
||||||
|
|
||||||
|
=========================================
|
||||||
|
================= day13 =================
|
||||||
|
=========================================
|
||||||
|
|
||||||
|
+++++++++++++++++ part 1
|
||||||
|
aoc-c: res=5843
|
||||||
|
time: 0:00.00 real, 0.00 user, 0.00 sys
|
||||||
|
context-switch: 0+1, page-faults: 0+192
|
||||||
|
|
||||||
|
+++++++++++++++++ part 2
|
||||||
|
aoc-c: res=26289
|
||||||
|
time: 0:00.00 real, 0.00 user, 0.00 sys
|
||||||
|
context-switch: 1+1, page-faults: 0+190
|
||||||
|
@@ -144,8 +144,6 @@ is the sum of the indices of those pairs?/
|
|||||||
|
|
||||||
Your puzzle answer was =5843=.
|
Your puzzle answer was =5843=.
|
||||||
|
|
||||||
The first half of this puzzle is complete! It provides one gold star: *
|
|
||||||
|
|
||||||
** --- Part Two ---
|
** --- Part Two ---
|
||||||
Now, you just need to put /all/ of the packets in the right order.
|
Now, you just need to put /all/ of the packets in the right order.
|
||||||
Disregard the blank lines in your list of received packets.
|
Disregard the blank lines in your list of received packets.
|
||||||
@@ -195,3 +193,5 @@ the divider packets are /10th/ and /14th/, and so the decoder key is
|
|||||||
|
|
||||||
Organize all of the packets into the correct order. /What is the decoder
|
Organize all of the packets into the correct order. /What is the decoder
|
||||||
key for the distress signal?/
|
key for the distress signal?/
|
||||||
|
|
||||||
|
Your puzzle answer was =26289=.
|
||||||
|
@@ -14,234 +14,157 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "br.h"
|
#include "br.h"
|
||||||
#include "debug.h"
|
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "pool.h"
|
#include "pool.h"
|
||||||
|
|
||||||
#include "aoc.h"
|
#include "aoc.h"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum { SUBLIST, INT } type_t;
|
||||||
NIL,
|
|
||||||
LIST,
|
|
||||||
//SUBLIST,
|
|
||||||
INT
|
|
||||||
} type_t;
|
|
||||||
|
|
||||||
char *types[] = {
|
typedef struct node { /* node */
|
||||||
"NIL",
|
|
||||||
"LIST",
|
|
||||||
//"SUBLIST",
|
|
||||||
"INT"
|
|
||||||
};
|
|
||||||
|
|
||||||
struct node;
|
|
||||||
typedef struct cons {
|
|
||||||
type_t type;
|
|
||||||
union {
|
|
||||||
//struct list_head node; /* same level node */
|
|
||||||
struct node *sub;
|
|
||||||
int value;
|
|
||||||
};
|
|
||||||
} cons_t;
|
|
||||||
|
|
||||||
#define CAR 0 /* always NUM or SUBLIST */
|
|
||||||
#define CDR 1 /* always LIST */
|
|
||||||
|
|
||||||
typedef struct node {
|
|
||||||
type_t car_t;
|
type_t car_t;
|
||||||
union {
|
union { /* CAR */
|
||||||
struct list_head sub;
|
struct list_head sub; /* sublist */
|
||||||
int value;
|
int value; /* value */
|
||||||
} car;
|
};
|
||||||
struct list_head cdr;
|
struct list_head cdr; /* CDR */
|
||||||
//cons_t cons[2];
|
|
||||||
} node_t;
|
} node_t;
|
||||||
|
|
||||||
typedef struct line {
|
typedef struct { /* packets ordered list */
|
||||||
int pos; /* position to parse */
|
struct list_head node; /* packet head */
|
||||||
char *s;
|
struct list_head list; /* packets lists */
|
||||||
} line_t;
|
} packets_t;
|
||||||
|
LIST_HEAD(packets);
|
||||||
|
|
||||||
pool_t *pool_nodes;
|
/* dummy node for integer vs list */
|
||||||
|
static struct list_head dummy_list; /* tentative definition */
|
||||||
|
static node_t dummy = {
|
||||||
|
.car_t = INT, .value = 0, .cdr = LIST_HEAD_INIT(dummy_list)
|
||||||
|
};
|
||||||
|
static struct list_head dummy_list = LIST_HEAD_INIT(dummy.cdr);
|
||||||
|
|
||||||
static node_t *getnode()
|
pool_t *pool_node, *pool_packets;
|
||||||
|
|
||||||
|
/* int getnode - allocate and initialize a new node
|
||||||
|
* @type: The node type_t (INT/LIST)
|
||||||
|
* @val: The value if @type is INT
|
||||||
|
*
|
||||||
|
* Return: The new node.
|
||||||
|
*/
|
||||||
|
static node_t *getnode(type_t type, int val)
|
||||||
{
|
{
|
||||||
node_t *node = pool_get(pool_nodes);
|
node_t *node = pool_get(pool_node);
|
||||||
node->car_t = NIL;
|
node->car_t = type;
|
||||||
INIT_LIST_HEAD(&node->cdr);
|
INIT_LIST_HEAD(&node->cdr);
|
||||||
log_f(4, "\n");
|
if (type == INT)
|
||||||
|
node->value = val;
|
||||||
|
else
|
||||||
|
INIT_LIST_HEAD(&node->sub);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_tree(struct list_head *head, int level)
|
/* int compare tree - compare two packets trees
|
||||||
{
|
* @h1: The first packet list head
|
||||||
struct node *cur;
|
* @h2: The second packet list head
|
||||||
log_f(4, "head=%p lev=%d\n", head, level);
|
*
|
||||||
printf("( ");
|
* Return: 1 if h1 and h2 are ordered, -1 if not ordered, 0 if undecided
|
||||||
//if (!list_empty(&node->cdr)) {
|
*/
|
||||||
list_for_each_entry(cur, head, cdr) {
|
|
||||||
if (cur->car_t == INT)
|
|
||||||
printf("%d ", cur->car.value);
|
|
||||||
else if (cur->car_t == NIL)
|
|
||||||
printf("ERROR ");
|
|
||||||
else
|
|
||||||
print_tree(&cur->car.sub, level + 2);
|
|
||||||
}
|
|
||||||
//} else {
|
|
||||||
//printf("nil ");
|
|
||||||
//}
|
|
||||||
printf(") ");
|
|
||||||
if (!level)
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static int compare_tree(struct list_head *h1, struct list_head *h2)
|
static int compare_tree(struct list_head *h1, struct list_head *h2)
|
||||||
{
|
{
|
||||||
struct list_head *cur1, *cur2;
|
struct list_head *cur1, *cur2;
|
||||||
//struct list_head *h1, *h2;
|
node_t *n1, *n2;
|
||||||
node_t *tmp, *n1, *n2;
|
|
||||||
int res;
|
int res;
|
||||||
log_f(3, "h1=%p h2=%p\n", h1, h2);
|
|
||||||
|
|
||||||
/* check for NIL */
|
|
||||||
/*
|
|
||||||
* if (n1->car_t == NIL) {
|
|
||||||
* log(3, "n1 is NIL\n");
|
|
||||||
* return n2->car_t == NIL? 0: 1;
|
|
||||||
* }
|
|
||||||
* if (n2->car_t == NIL) {
|
|
||||||
* log(3, "n2 is NIL\n");
|
|
||||||
* return -1;
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
|
|
||||||
//h1 = &n1->cdr;
|
|
||||||
//h2 = &n2->cdr;
|
|
||||||
/* get lists first entries */
|
/* get lists first entries */
|
||||||
cur1 = h1->next;
|
cur1 = h1->next;
|
||||||
cur2 = h2->next;
|
cur2 = h2->next;
|
||||||
|
|
||||||
//if (!list_empty(h1) && !list_empty(h2)) {
|
while (cur1 != h1 && cur2 != h2) {
|
||||||
while (cur1 != h1 && cur2 != h2) {
|
|
||||||
n1 = container_of(cur1, node_t, cdr);
|
n1 = container_of(cur1, node_t, cdr);
|
||||||
n2 = container_of(cur2, node_t, cdr);
|
n2 = container_of(cur2, node_t, cdr);
|
||||||
|
|
||||||
if (n1->car_t == n2->car_t) {
|
if (n1->car_t == n2->car_t) {
|
||||||
if (n1->car_t == INT) {
|
if (n1->car_t == INT) {
|
||||||
if (n1->car.value < n2->car.value) {
|
if (n1->value < n2->value) {
|
||||||
log(3, "car1=%d < car2=%d, returning 1\n", n1->car.value,
|
|
||||||
n2->car.value);
|
|
||||||
return 1;
|
return 1;
|
||||||
} else if (n1->car.value > n2->car.value) {
|
} else if (n1->value > n2->value) {
|
||||||
log(3, "car1=%d > car2=%d, returning -1\n", n1->car.value,
|
|
||||||
n2->car.value);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
log(3, "car1 == car2 == %d, skipping\n", n1->car.value);
|
|
||||||
} else { /* both sublists */
|
} else { /* both sublists */
|
||||||
res = compare_tree(&n1->car.sub, &n2->car.sub);
|
if ((res = compare_tree(&n1->sub, &n2->sub)))
|
||||||
if (res)
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
} else { /* one number, one list */
|
} else { /* one number, one list */
|
||||||
tmp = getnode();
|
|
||||||
//INIT_LIST_HEAD(&tmp->car.sub);
|
|
||||||
tmp->car_t = INT;
|
|
||||||
if (n1->car_t == INT) {
|
if (n1->car_t == INT) {
|
||||||
log(3, "car1 == INT, adding a node\n");
|
dummy.value = n1->value;
|
||||||
tmp->car.value = n1->car.value;
|
res = compare_tree(&dummy_list, &n2->sub);
|
||||||
n1->car_t = LIST;
|
|
||||||
INIT_LIST_HEAD(&n1->car.sub);
|
|
||||||
list_add(&tmp->cdr, &n1->car.sub);
|
|
||||||
//n1->car.sub = tmp;
|
|
||||||
//print_tree()
|
|
||||||
} else {
|
} else {
|
||||||
log(3, "car2 == INT, adding a node\n");
|
dummy.value = n2->value;
|
||||||
tmp->car.value = n2->car.value;
|
res = compare_tree(&n1->sub, &dummy_list);
|
||||||
n2->car_t = LIST;
|
|
||||||
INIT_LIST_HEAD(&n2->car.sub);
|
|
||||||
list_add(&tmp->cdr, &n2->car.sub);
|
|
||||||
//n2->car.sub = tmp;
|
|
||||||
}
|
}
|
||||||
res = compare_tree(&n1->car.sub, &n2->car.sub);
|
|
||||||
if (res)
|
if (res)
|
||||||
return res;
|
return res;
|
||||||
//continue;
|
|
||||||
}
|
}
|
||||||
//next:
|
|
||||||
cur1 = cur1->next;
|
cur1 = cur1->next;
|
||||||
cur2 = cur2->next;
|
cur2 = cur2->next;
|
||||||
}
|
}
|
||||||
//} else {
|
|
||||||
// log(3, "some list empty\n");
|
|
||||||
//}
|
|
||||||
/* at least one list came to end */
|
/* at least one list came to end */
|
||||||
if (cur1 == h1 && cur2 == h2) { /* both are ending */
|
if (cur1 == h1 && cur2 == h2) /* both are ending */
|
||||||
log(3, "Both sides Left side ran out of items, undecided\n");
|
|
||||||
return 0;
|
return 0;
|
||||||
} else if (cur1 == h1) { /* first list did end */
|
else if (cur1 == h1) /* first list did end */
|
||||||
log(3, "Left side ran out of items, so inputs are in the right order\n");
|
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
else
|
||||||
log(3, "Right side ran out of items, so inputs are not in the right order\n");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct list_head *create_tree(char *s, int *consumed, int level, struct list_head *head)
|
/* int add_node - add a packet to the sorted packets list
|
||||||
|
* @new: The new packets list head
|
||||||
|
*
|
||||||
|
* Return: The new packet position in list (first is 1)
|
||||||
|
*/
|
||||||
|
static int add_node(packets_t *new)
|
||||||
|
{
|
||||||
|
packets_t *first, *iter;
|
||||||
|
struct list_head *node_next = &packets;
|
||||||
|
int num = 1;
|
||||||
|
|
||||||
|
if (list_empty(&packets))
|
||||||
|
goto ins_node;
|
||||||
|
first = iter = list_first_entry(&packets, packets_t, list);
|
||||||
|
do {
|
||||||
|
if (compare_tree(&new->node, &iter->node) > 0) {
|
||||||
|
node_next = &iter->list;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
iter = list_entry(iter->list.next, packets_t, list);
|
||||||
|
num++;
|
||||||
|
} while (iter != first);
|
||||||
|
ins_node:
|
||||||
|
list_add_tail(&new->list, node_next);
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct list_head *create_tree(char *s, int *consumed, struct list_head *head)
|
||||||
{
|
{
|
||||||
node_t *node = NULL;
|
node_t *node = NULL;
|
||||||
LIST_HEAD(sub);
|
LIST_HEAD(sub);
|
||||||
int num = 0, val, depth = 0, subconsumed;
|
int val, depth = 0, subconsumed;
|
||||||
//LIST_HEAD(head);
|
|
||||||
*consumed = 1;
|
*consumed = 1;
|
||||||
if (*s != '[') {
|
|
||||||
printf("error 0\n");
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
INIT_LIST_HEAD(head);
|
INIT_LIST_HEAD(head);
|
||||||
//head = getnode();
|
|
||||||
log_f(3, "create_tree(%s)\n", s);
|
|
||||||
for (; *s; s++, (*consumed)++) {
|
for (; *s; s++, (*consumed)++) {
|
||||||
log(4, "L=%d examining %c num=%d depth=%d\n", level, *s, num, depth);
|
|
||||||
val = 0;
|
|
||||||
switch (*s) {
|
switch (*s) {
|
||||||
case '[':
|
case '[':
|
||||||
switch (++depth) {
|
if (++depth == 2) { /* we skip first depth level */
|
||||||
case 1: /* first level */
|
node = getnode(SUBLIST, 0);
|
||||||
break;
|
list_add_tail(&node->cdr, head);
|
||||||
case 2: /* second level (nested list) */
|
create_tree(s, &subconsumed, &node->sub);
|
||||||
node = getnode();
|
s += subconsumed - 1;
|
||||||
node->car_t = LIST;
|
*consumed += subconsumed - 1;
|
||||||
INIT_LIST_HEAD(&node->car.sub);
|
depth--;
|
||||||
create_tree(s, &subconsumed, level + 1, &node->car.sub);
|
|
||||||
s += subconsumed - 1;
|
|
||||||
*consumed += subconsumed - 1;
|
|
||||||
log(4, "after create_tree: cons=%d s=%s\n", subconsumed, s);
|
|
||||||
//if (num == 0) {
|
|
||||||
// head->car_t = SUBLIST;
|
|
||||||
// head->car.sub = sub;
|
|
||||||
//} else {
|
|
||||||
//list_add(&sub, &node->car.sub); /* add sublist to new node */
|
|
||||||
list_add_tail(&node->cdr, head); /* add node to current level */
|
|
||||||
puts("ZOBI");
|
|
||||||
print_tree(&node->car.sub, 0);
|
|
||||||
puts("ZOBa");
|
|
||||||
//sleep(1);
|
|
||||||
print_tree(head, 0);
|
|
||||||
//}
|
|
||||||
depth--;
|
|
||||||
num++;
|
|
||||||
break;
|
|
||||||
default: /* should not happen */
|
|
||||||
printf("error 1\n");
|
|
||||||
exit(0);
|
|
||||||
break; /* not reached */
|
|
||||||
}
|
}
|
||||||
//num++;
|
|
||||||
break;
|
break;
|
||||||
case ',':
|
case ',':
|
||||||
break;
|
break;
|
||||||
@@ -253,23 +176,12 @@ static struct list_head *create_tree(char *s, int *consumed, int level, struct l
|
|||||||
sscanf(s, "%d%n", &val, &subconsumed);
|
sscanf(s, "%d%n", &val, &subconsumed);
|
||||||
*consumed += subconsumed - 1;
|
*consumed += subconsumed - 1;
|
||||||
s += subconsumed - 1;
|
s += subconsumed - 1;
|
||||||
log(4, "got integer=%d num=%d depth=%d chars=%d\n", val, num, depth, subconsumed);
|
node = getnode(INT, val);
|
||||||
//if (num == 0) {
|
|
||||||
// head->car_t = INT;
|
|
||||||
// head->car.value = val;
|
|
||||||
//} else {
|
|
||||||
node = getnode();
|
|
||||||
node->car_t = INT;
|
|
||||||
node->car.value = val;
|
|
||||||
list_add_tail(&node->cdr, head);
|
list_add_tail(&node->cdr, head);
|
||||||
//}
|
|
||||||
//print_tree(head, 0);
|
|
||||||
num++;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end:
|
end:
|
||||||
log(4, "returning from create_tree, consumed=%d head=%p\n", *consumed, head);
|
|
||||||
return head;
|
return head;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,77 +190,51 @@ static int parse()
|
|||||||
size_t alloc = 0;
|
size_t alloc = 0;
|
||||||
ssize_t buflen;
|
ssize_t buflen;
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
int i = 0;
|
packets_t *head[2];
|
||||||
struct list_head head[2];
|
int i = 0, dummy, res = 0;
|
||||||
int consumed;
|
|
||||||
int group = 1, res = 0, tmp;
|
|
||||||
//line_t line;
|
|
||||||
|
|
||||||
while ((buflen = getline(&buf, &alloc, stdin)) > 0) {
|
while ((buflen = getline(&buf, &alloc, stdin)) > 0) {
|
||||||
buf[--buflen] = 0;
|
buf[--buflen] = 0;
|
||||||
if (!buflen) {
|
if (buflen > 0) { /* non empty line */
|
||||||
//i = 0;
|
head[i % 2] = pool_get(pool_packets);
|
||||||
//printf("++++ node 1 = %p\n", node[1]);
|
create_tree(buf, &dummy, &head[i % 2]->node);
|
||||||
printf("++++ node 0 = %p\n", &head[0]);
|
add_node(head[i % 2]);
|
||||||
print_tree(&head[0], 0);
|
}
|
||||||
printf("++++ node 1 = %p\n", &head[1]);
|
if (buflen != 0) { /* non empty line or EOF */
|
||||||
print_tree(&head[1], 0);
|
if (i % 2 && compare_tree(&head[0]->node, &head[1]->node) == 1)
|
||||||
tmp = compare_tree(&head[0], &head[1]);
|
res += (i >> 1) + 1; /* (i / 2) + 1 */
|
||||||
printf("group = %d compare_tree() = %d\n", group, tmp);
|
|
||||||
if (tmp == 1) {
|
|
||||||
res += group;
|
|
||||||
printf("group = %d: right order res:%d -> %d\n", group, res - group, res);
|
|
||||||
}
|
|
||||||
group++;
|
|
||||||
printf("\n\n");
|
|
||||||
//pool_add(pool_nodes, node[0]);
|
|
||||||
//pool_add(pool_nodes, node[1]);
|
|
||||||
//node[0] = node[1] = NULL;
|
|
||||||
//exit(0);
|
|
||||||
} else {
|
|
||||||
//node[i % 2] = getnode();
|
|
||||||
create_tree(buf, &consumed, 0, &head[i % 2]);
|
|
||||||
printf("setting node %d\n\n", i%2);
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("++++ node 0 = %p\n", &head[0]);
|
return res;
|
||||||
print_tree(&head[0], 0);
|
}
|
||||||
printf("++++ node 1 = %p\n", &head[1]);
|
|
||||||
print_tree(&head[1], 0);
|
static int part1()
|
||||||
tmp = compare_tree(&head[0], &head[1]);
|
{
|
||||||
printf("group = %d compare_tree() = %d\n", group, tmp);
|
return parse();
|
||||||
if (tmp == 1) {
|
}
|
||||||
res += group;
|
|
||||||
printf("group = %d: right order res:%d -> %d\n", group, res - group, res);
|
static int part2()
|
||||||
|
{
|
||||||
|
char *dividers[] = { "[[2]]", "[[6]]" };
|
||||||
|
int dummy, res = 1;
|
||||||
|
parse();
|
||||||
|
for (ulong i = 0; i < ARRAY_SIZE(dividers); ++i) {
|
||||||
|
packets_t *h = pool_get(pool_packets);
|
||||||
|
create_tree(dividers[i], &dummy, &h->node);
|
||||||
|
res *= add_node(h);
|
||||||
}
|
}
|
||||||
printf("\n\n");
|
return res;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static u64 doit()
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static u64 part1()
|
|
||||||
{
|
|
||||||
return doit();
|
|
||||||
}
|
|
||||||
|
|
||||||
static u64 part2()
|
|
||||||
{
|
|
||||||
return doit();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main(int ac, char **av)
|
int main(int ac, char **av)
|
||||||
{
|
{
|
||||||
int part = parseargs(ac, av);
|
int part = parseargs(ac, av);
|
||||||
pool_nodes = pool_create("nodes", 512, sizeof(node_t));
|
pool_node = pool_create("node", 512, sizeof(node_t));
|
||||||
//u32 foo=0x12345678;
|
pool_packets = pool_create("packets", 512, sizeof(packets_t));
|
||||||
parse();
|
|
||||||
printf("%s: res=%lu\n", *av, part == 1? part1(): part2());
|
printf("%s: res=%d\n", *av, part == 1? part1(): part2());
|
||||||
pool_destroy(pool_nodes);
|
pool_destroy(pool_node);
|
||||||
|
pool_destroy(pool_packets);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user