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