day 18: code cleanup, fixed valgrind errors.
This commit is contained in:
@@ -19,12 +19,8 @@
|
||||
#include "bits.h"
|
||||
#include "list.h"
|
||||
|
||||
#define POISON_VALUE -232323
|
||||
#define POISON_DEPTH 121212;
|
||||
|
||||
#define PARENT 0
|
||||
#define LEFT 1
|
||||
#define RIGHT 2
|
||||
#define LEFT 0
|
||||
#define RIGHT 1
|
||||
|
||||
static pool_t *pool_nodes;
|
||||
|
||||
@@ -34,12 +30,11 @@ static int nlines;
|
||||
|
||||
typedef struct node {
|
||||
s64 val;
|
||||
struct node *tree[3]; /* parent, left, right */
|
||||
struct node *tree[2]; /* left & right */
|
||||
struct list_head leaf_list; /* head is tree root */
|
||||
u32 depth;
|
||||
} node_t;
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
/* print leaves list
|
||||
*/
|
||||
static void leaves_print(node_t *root)
|
||||
@@ -54,117 +49,93 @@ static void leaves_print(node_t *root)
|
||||
|
||||
/* print node tree
|
||||
*/
|
||||
static void node_print(node_t *node)
|
||||
static void node_print(node_t *node, int depth)
|
||||
{
|
||||
if (!node->depth)
|
||||
if (!depth)
|
||||
log_f(1, "");
|
||||
if (!node->tree[LEFT]) { /* leaf */
|
||||
log(1, "%ld", node->val);
|
||||
} else {
|
||||
log(1, "[");
|
||||
node_print(node->tree[LEFT]);
|
||||
node_print(node->tree[LEFT], depth + 1);
|
||||
log(1, ",");
|
||||
node_print(node->tree[RIGHT]);
|
||||
node_print(node->tree[RIGHT], depth + 1);
|
||||
log(1, "]");
|
||||
}
|
||||
if (!node->depth) {
|
||||
if (!depth) {
|
||||
log(1, "\n");
|
||||
leaves_print(node);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline node_t *node_get()
|
||||
{
|
||||
node_t *node = pool_get(pool_nodes);
|
||||
|
||||
node->depth = POISON_DEPTH;
|
||||
node->val = POISON_VALUE;
|
||||
node->tree[LEFT] = NULL;
|
||||
node->tree[RIGHT] = NULL;
|
||||
node->tree[PARENT] = NULL;
|
||||
INIT_LIST_HEAD(&node->leaf_list);
|
||||
return node;
|
||||
}
|
||||
|
||||
static inline void node_free(node_t *node)
|
||||
{
|
||||
if (node->tree[LEFT]) {
|
||||
node_free(node->tree[LEFT]);
|
||||
node_free(node->tree[RIGHT]);
|
||||
}
|
||||
pool_add(pool_nodes, node);
|
||||
}
|
||||
|
||||
/* split_node - split first node with value >= 10
|
||||
* return: 1: finished
|
||||
*/
|
||||
static int node_split(node_t *node)
|
||||
{
|
||||
int depth = node->depth;
|
||||
static node_t *root;
|
||||
|
||||
if (depth == 0)
|
||||
root = node;
|
||||
//if (node->depth == 0)
|
||||
log_f(2, "entering node %p: val=%d left=%p right=%p\n", node, node->val,
|
||||
node->tree[LEFT], node->tree[RIGHT]);
|
||||
|
||||
if (node->tree[LEFT]) {
|
||||
if (node_split(node->tree[LEFT]) || node_split(node->tree[RIGHT]))
|
||||
return 1;
|
||||
} else {
|
||||
if (node->val >= 10) { /* eligible leaf */
|
||||
//node_t *leaf_left = list_prev_entry(node, leaf_list);
|
||||
node_t *left, *right;
|
||||
|
||||
log_i(2, "splitting [%ld,%ld]\n", node->val);
|
||||
|
||||
/* create and populate new nodes */
|
||||
left = node_get();
|
||||
left->depth = node->depth + 1;
|
||||
left->val = node->val / 2;
|
||||
|
||||
right = node_get();
|
||||
right->depth = node->depth + 1;
|
||||
right->val = (node->val + 1) / 2;
|
||||
|
||||
node->tree[LEFT] = left;
|
||||
node->tree[RIGHT] = right;
|
||||
node->val = POISON_VALUE;
|
||||
|
||||
/* add new nodes in leaves list, remove current one */
|
||||
list_add(&node->tree[RIGHT]->leaf_list, &node->leaf_list);
|
||||
list_add(&node->tree[LEFT]->leaf_list, &node->leaf_list);
|
||||
list_del(&node->leaf_list);
|
||||
log_i(2, "after split: \n\t");
|
||||
node_print(root);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (node->depth == 0) {
|
||||
log_f(2, "return:\n\t");
|
||||
node_print(node);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* explode node - explode first node with level == 4
|
||||
* return: 1: finished
|
||||
*/
|
||||
static int node_explode(node_t *node)
|
||||
static int node_explode(node_t *node, int depth)
|
||||
{
|
||||
int depth = node->depth;
|
||||
static node_t *root;
|
||||
|
||||
if (depth == 0) {
|
||||
if (depth == 0)
|
||||
root = node;
|
||||
|
||||
log_f(2, "entering node %p: val=%d left=%p right=%p\n", node, node->val,
|
||||
node->tree[LEFT], node->tree[RIGHT]);
|
||||
}
|
||||
if (depth == 4) {
|
||||
node_t *left = node->tree[LEFT], *right = node->tree[RIGHT];
|
||||
//struct list_head *tmp;
|
||||
|
||||
/* skip leaves */
|
||||
if (!left)
|
||||
return 0;
|
||||
|
||||
log_i(2, "exploding [%ld,%ld]\n", left->val, right->val);
|
||||
//log_i(2, "zobu: ");
|
||||
//node_print(root);
|
||||
|
||||
/* increment left leaf */
|
||||
if (!list_is_first(&left->leaf_list, &root->leaf_list)) {
|
||||
node_t *tmpnode = list_prev_entry(left, leaf_list);
|
||||
@@ -176,43 +147,23 @@ static int node_explode(node_t *node)
|
||||
tmpnode->val += right->val;
|
||||
}
|
||||
|
||||
//log_i(2, "zobi: ");
|
||||
//node_print(root);
|
||||
/* remove leaves from list, and add current one */
|
||||
//tmp = list_entry(left, node_t, leaf_list);
|
||||
node->val = 0;
|
||||
|
||||
list_add(&node->leaf_list, &left->leaf_list);
|
||||
//log_i(2, "zoba: n=%p l=%p) ", &node->leaf_list, &left->leaf_list);
|
||||
//node_print(root);
|
||||
|
||||
//list_del(&left->leaf_list);
|
||||
//list_del(left->leaf_list.prev);
|
||||
|
||||
//list_del(&node->leaf_list->prev);
|
||||
//tmp = list_prev_entry(node, leaf_list);
|
||||
//log_i(2, "zoby: n=%p l=%p) ", &node->leaf_list, &left->leaf_list);
|
||||
list_del(&left->leaf_list);
|
||||
//node->leaf_list.prev;
|
||||
//log_i(2, "zobe: ");
|
||||
//node_print(root);
|
||||
pool_add(pool_nodes, left);
|
||||
|
||||
list_del(&right->leaf_list);
|
||||
//log_i(2, "zobo: ");
|
||||
//node_print(root);
|
||||
pool_add(pool_nodes, right);
|
||||
|
||||
/* remove childs links */
|
||||
node->tree[LEFT] = NULL;
|
||||
node->tree[RIGHT] = NULL;
|
||||
|
||||
//log_i(2, "after reduce: ");
|
||||
//node_print(root);
|
||||
return 1;
|
||||
} else {
|
||||
if (node->tree[LEFT]) {
|
||||
if (node_explode(node->tree[LEFT]) || node_explode(node->tree[RIGHT]))
|
||||
if (node_explode(node->tree[LEFT], depth + 1) ||
|
||||
node_explode(node->tree[RIGHT], depth + 1))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -221,14 +172,8 @@ static int node_explode(node_t *node)
|
||||
|
||||
static node_t *node_reduce(node_t *node)
|
||||
{
|
||||
//log_f(2, "");
|
||||
//node_explode(node);
|
||||
//node_explode(node);
|
||||
//return node;
|
||||
while (1) {
|
||||
log_f(2, "\t");
|
||||
node_print(node);
|
||||
if (node_explode(node))
|
||||
if (node_explode(node, 0))
|
||||
continue;
|
||||
if (node_split(node))
|
||||
continue;
|
||||
@@ -237,101 +182,57 @@ static node_t *node_reduce(node_t *node)
|
||||
return node;
|
||||
}
|
||||
|
||||
/* promote/demode node
|
||||
*/
|
||||
static node_t *node_promote(node_t *node, int promote)
|
||||
{
|
||||
node->depth += promote;
|
||||
if (node->tree[LEFT]) {
|
||||
node_promote(node->tree[LEFT], promote);
|
||||
node_promote(node->tree[RIGHT], promote);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
/* add 2 nodes
|
||||
*/
|
||||
static node_t *node_add(node_t *n1, node_t *n2)
|
||||
{
|
||||
node_t *head = pool_get(pool_nodes);
|
||||
|
||||
log_f(2, "\n");
|
||||
node_print(n1);
|
||||
node_print(n2);
|
||||
head->depth = 0;
|
||||
INIT_LIST_HEAD(&head->leaf_list);
|
||||
|
||||
/* create new tree from the two
|
||||
*/
|
||||
head->tree[LEFT] = node_promote(n1, 1);
|
||||
head->tree[RIGHT] = node_promote(n2, 1);
|
||||
n1->tree[PARENT] = head;
|
||||
n2->tree[PARENT] = head;
|
||||
head->tree[LEFT] = n1;
|
||||
head->tree[RIGHT] = n2;
|
||||
|
||||
/* link leaves
|
||||
/* link corresponding leaves
|
||||
*/
|
||||
//head->leaf_list = n1->leaf_list;
|
||||
list_splice_tail(&n1->leaf_list, &head->leaf_list);
|
||||
list_splice_tail(&n2->leaf_list, &head->leaf_list);
|
||||
//node_print(head);
|
||||
return head;
|
||||
}
|
||||
|
||||
/* read node, from '[' to corresponding ']'
|
||||
*/
|
||||
static node_t *node_read(char **p, int depth)//, node_t *parent)
|
||||
static inline node_t *_node_read(char **p, int depth)
|
||||
{
|
||||
static node_t *root;
|
||||
node_t *node = node_get();
|
||||
|
||||
node->depth = depth;
|
||||
|
||||
if (!depth) { /* root node */
|
||||
if (!depth) { /* root node */
|
||||
root = node;
|
||||
//log_f(1, "%s\n", *p);
|
||||
INIT_LIST_HEAD(&node->leaf_list);
|
||||
}
|
||||
|
||||
//log_f(2, "str=%s depth=%d\n", *p, depth);
|
||||
switch (**p) {
|
||||
case '[':
|
||||
(*p)++;
|
||||
node->tree[LEFT] = node_read(p, depth+1);
|
||||
node->tree[LEFT]->tree[PARENT] = node;
|
||||
//log_i(2, "comma = %c\n", **p);
|
||||
node->tree[LEFT] = _node_read(p, depth + 1);
|
||||
(*p)++;
|
||||
node->tree[RIGHT] = node_read(p, depth+1);
|
||||
node->tree[RIGHT]->tree[PARENT] = node;
|
||||
//log_i(2, "closing = %c\n", **p);
|
||||
node->tree[RIGHT] = _node_read(p, depth + 1);
|
||||
break;
|
||||
default: /* number */
|
||||
//log_i(2, "number = %c\n", **p);
|
||||
node->val = **p - '0';
|
||||
list_add_tail(&node->leaf_list, &root->leaf_list);
|
||||
}
|
||||
(*p)++;
|
||||
//if (!depth) { /* root node */
|
||||
// log_f(1, "%s\n", *p);
|
||||
//}
|
||||
return node;
|
||||
}
|
||||
|
||||
/* read line, create a tree
|
||||
*/
|
||||
static node_t *read_line()
|
||||
static inline node_t *node_read(char *p)
|
||||
{
|
||||
node_t *head = NULL;
|
||||
size_t alloc = 0;
|
||||
char *buf, *p;
|
||||
ssize_t buflen;
|
||||
|
||||
if ((buflen = getline(&buf, &alloc, stdin)) > 0) {
|
||||
p = buf;
|
||||
buf[--buflen] = 0;
|
||||
head = node_read(&p, 0);
|
||||
}
|
||||
free(buf);
|
||||
//node_print(head);
|
||||
return head;
|
||||
char *tmp = p;
|
||||
return _node_read(&tmp, 0);
|
||||
}
|
||||
|
||||
/* read input
|
||||
@@ -345,6 +246,7 @@ static int read_lines()
|
||||
lines[nlines][--buflen] = 0;
|
||||
nlines++;
|
||||
}
|
||||
free(lines[nlines]); /* EOF */
|
||||
return nlines;
|
||||
}
|
||||
|
||||
@@ -356,7 +258,7 @@ static void free_lines()
|
||||
free(lines[i]);
|
||||
}
|
||||
|
||||
static s64 node_magnitude(node_t *node)
|
||||
static inline s64 node_magnitude(node_t *node)
|
||||
{
|
||||
if (!node->tree[LEFT])
|
||||
return node->val;
|
||||
@@ -367,35 +269,33 @@ static s64 node_magnitude(node_t *node)
|
||||
static s64 part1()
|
||||
{
|
||||
node_t *head = NULL, *next = NULL;
|
||||
s64 res;
|
||||
|
||||
head = node_read(lines + 0, 0);
|
||||
head = node_read(lines[0]);
|
||||
for (int i = 1; i < nlines; ++i) {
|
||||
next = node_read(lines + i, 0);
|
||||
next = node_read(lines[i]);
|
||||
head = node_reduce(node_add(head, next));
|
||||
}
|
||||
node_print(head);
|
||||
return node_magnitude(head);
|
||||
res = node_magnitude(head);
|
||||
node_free(head);
|
||||
return res;
|
||||
}
|
||||
|
||||
static s64 part2()
|
||||
{
|
||||
node_t *l1 = NULL, *l2 = NULL;
|
||||
node_t *list;
|
||||
s64 max = 0, cur;
|
||||
char *tmp;
|
||||
|
||||
for (int i = 0; i < nlines; ++i) {
|
||||
for (int j = 0; j < nlines; ++j) {
|
||||
if (j == i)
|
||||
continue;
|
||||
tmp = lines[i];
|
||||
l1 = node_read(&tmp, 0);
|
||||
tmp = lines[j];
|
||||
l2 = node_read(&tmp, 0);
|
||||
cur = node_magnitude(node_reduce(node_add(l1, l2)));
|
||||
if (cur > max) {
|
||||
log(2, "NEW BEST: %s + %s\n", lines[i], lines[j]);
|
||||
list = node_reduce(node_add(node_read(lines[i]),
|
||||
node_read(lines[j])));
|
||||
cur = node_magnitude(list);
|
||||
if (cur > max)
|
||||
max = cur;
|
||||
}
|
||||
node_free(list);
|
||||
}
|
||||
}
|
||||
return max;
|
||||
@@ -432,22 +332,7 @@ int main(int ac, char **av)
|
||||
exit(1);
|
||||
read_lines();
|
||||
printf("%s : res=%ld\n", *av, part == 1? part1(): part2());
|
||||
exit(0);
|
||||
node_t *n1, *n2, *n3, *n4;
|
||||
n1 = read_line();
|
||||
n2 = read_line();
|
||||
//node_print(n1);
|
||||
//node_print(n2);
|
||||
n3 = node_add(n1, n2);
|
||||
//node_print(n3);
|
||||
n4 = node_reduce(n3);
|
||||
node_print(n4);
|
||||
free_lines();
|
||||
pool_destroy(pool_nodes);
|
||||
exit(0);
|
||||
//node_print(n1);
|
||||
//node_print(n2);
|
||||
n3 = node_add(n1, n2);
|
||||
node_print(n3);
|
||||
printf("%s : res=%ld\n", *av, part == 1? part1(): part2());
|
||||
exit (0);
|
||||
}
|
||||
|
Reference in New Issue
Block a user