Snailfish data structure diagram + cosmetic changes
This commit is contained in:
@@ -18,19 +18,37 @@
|
||||
#include "debug.h"
|
||||
#include "list.h"
|
||||
|
||||
/* Data structure : A snailfish number (SN) is represented as a binary tree and a
|
||||
* (doubly) linked list LL for leaves (= decimal numbers).
|
||||
* The latter will allow to easily find previous/next number.
|
||||
*
|
||||
* Example, [1,[4,2]] is represented as :
|
||||
*
|
||||
* ------> SN root <-------------- Depth: 0
|
||||
* | / \ |
|
||||
* LL| / \ |
|
||||
* | / \ |LL
|
||||
* --> 1 <--- SN node | Depth: 1
|
||||
* | / \ |
|
||||
* | / \ |
|
||||
* LL---> 4 <-------> 2 <-- Depth: 2
|
||||
* LL
|
||||
*/
|
||||
|
||||
static pool_t *pool_nodes;
|
||||
|
||||
#define MAX_LINES 128 /* I know, I know... */
|
||||
static char *lines[MAX_LINES];
|
||||
static int nlines;
|
||||
|
||||
#define LEFT 0
|
||||
#define RIGHT 1
|
||||
#define IS_LEAF(node) (!(node)->tree[LEFT])
|
||||
#define LEFT 0
|
||||
#define RIGHT 1
|
||||
|
||||
#define IS_LEAF(node) (!(node)->left)
|
||||
|
||||
typedef struct node {
|
||||
int val;
|
||||
struct node *tree[2]; /* left & right subtrees */
|
||||
struct node *left, *right;
|
||||
struct list_head leaf_list; /* tree root is list head */
|
||||
} node_t;
|
||||
|
||||
@@ -40,8 +58,8 @@ static inline node_t *node_get()
|
||||
{
|
||||
node_t *node = pool_get(pool_nodes);
|
||||
|
||||
node->tree[LEFT] = NULL;
|
||||
node->tree[RIGHT] = NULL;
|
||||
node->left = NULL;
|
||||
node->right = NULL;
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -50,8 +68,8 @@ static inline node_t *node_get()
|
||||
static inline void node_free(node_t *node)
|
||||
{
|
||||
if (!IS_LEAF(node)) {
|
||||
node_free(node->tree[LEFT]);
|
||||
node_free(node->tree[RIGHT]);
|
||||
node_free(node->left);
|
||||
node_free(node->right);
|
||||
}
|
||||
pool_add(pool_nodes, node);
|
||||
}
|
||||
@@ -72,17 +90,17 @@ static int node_split(node_t *node)
|
||||
right = node_get();
|
||||
right->val = (node->val + 1) / 2;
|
||||
|
||||
node->tree[LEFT] = left;
|
||||
node->tree[RIGHT] = right;
|
||||
node->left = left;
|
||||
node->right = right;
|
||||
|
||||
/* 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_add(&node->right->leaf_list, &node->leaf_list);
|
||||
list_add(&node->left->leaf_list, &node->leaf_list);
|
||||
list_del(&node->leaf_list);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
return node_split(node->tree[LEFT]) || node_split(node->tree[RIGHT]);
|
||||
return node_split(node->left) || node_split(node->right);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -95,9 +113,9 @@ static int node_explode(node_t *node, int depth)
|
||||
static node_t *root;
|
||||
node_t *left, *right;
|
||||
|
||||
if (!(left = node->tree[LEFT]))
|
||||
if (!(left = node->left))
|
||||
return 0;
|
||||
right = node->tree[RIGHT];
|
||||
right = node->right;
|
||||
|
||||
/* Need to keep leaves list head */
|
||||
if (depth == 0)
|
||||
@@ -110,10 +128,10 @@ static int node_explode(node_t *node, int depth)
|
||||
if (!list_is_last(&right->leaf_list, &root->leaf_list))
|
||||
list_next_entry(right, leaf_list)->val += right->val;
|
||||
|
||||
/* node becomes a leaf */
|
||||
/* current node becomes a leaf */
|
||||
node->val = 0;
|
||||
node->tree[LEFT] = NULL;
|
||||
node->tree[RIGHT] = NULL;
|
||||
node->left = NULL;
|
||||
node->right = NULL;
|
||||
list_add(&node->leaf_list, &left->leaf_list);
|
||||
|
||||
/* remove children from leaves list, and put back in mem pool */
|
||||
@@ -134,7 +152,7 @@ static int node_explode(node_t *node, int depth)
|
||||
static node_t *node_reduce(node_t *node)
|
||||
{
|
||||
while (1) {
|
||||
if (!node_explode(node, 0) && !node_split(node))
|
||||
if (! (node_explode(node, 0) || node_split(node)))
|
||||
return node;
|
||||
}
|
||||
}
|
||||
@@ -145,17 +163,16 @@ static node_t *node_add(node_t *n1, node_t *n2)
|
||||
{
|
||||
node_t *head = pool_get(pool_nodes);
|
||||
|
||||
/* create new tree from the two nodes
|
||||
*/
|
||||
INIT_LIST_HEAD(&head->leaf_list);
|
||||
head->left = n1;
|
||||
head->right = n2;
|
||||
|
||||
/* create new tree from the two
|
||||
/* link leaves lists
|
||||
*/
|
||||
head->tree[LEFT] = n1;
|
||||
head->tree[RIGHT] = n2;
|
||||
|
||||
/* link corresponding leaves
|
||||
*/
|
||||
list_splice_tail(&n1->leaf_list, &head->leaf_list);
|
||||
list_splice_tail(&n2->leaf_list, &head->leaf_list);
|
||||
list_splice(&n2->leaf_list, &head->leaf_list);
|
||||
list_splice(&n1->leaf_list, &head->leaf_list);
|
||||
return head;
|
||||
}
|
||||
|
||||
@@ -174,9 +191,9 @@ static inline node_t *_node_read(char **p, int depth)
|
||||
switch (**p) {
|
||||
case '[':
|
||||
(*p)++; /* skip left bracket */
|
||||
node->tree[LEFT] = _node_read(p, depth + 1);
|
||||
node->left = _node_read(p, depth + 1);
|
||||
(*p)++; /* skip comma */
|
||||
node->tree[RIGHT] = _node_read(p, depth + 1);
|
||||
node->right = _node_read(p, depth + 1);
|
||||
break;
|
||||
default: /* number: add to tail list */
|
||||
node->val = **p - '0';
|
||||
@@ -218,10 +235,9 @@ static void free_lines()
|
||||
|
||||
static inline int node_magnitude(node_t *node)
|
||||
{
|
||||
if (!node->tree[LEFT])
|
||||
if (!node->left)
|
||||
return node->val;
|
||||
return 3 * node_magnitude(node->tree[LEFT]) +
|
||||
2 * node_magnitude(node->tree[RIGHT]);
|
||||
return 3 * node_magnitude(node->left) + 2 * node_magnitude(node->right);
|
||||
}
|
||||
|
||||
static int part1()
|
||||
|
Reference in New Issue
Block a user