fix display, add trees optimisation text.

This commit is contained in:
2021-01-25 15:13:22 +01:00
parent cfde68dd96
commit d72eb84347
3 changed files with 274 additions and 14 deletions

249
REDUCE-TREES.txt Normal file
View File

@@ -0,0 +1,249 @@
I thought about a way to drastically reduce the number of necessary trees. Does it make sense ?
For a 5 leaves (numbers) and 4 operators, I define following tree types:
;; Type A
o
/ \
o
/ \
o
/ \
o
/ \
;; type B
o
/ \
o o
/ \ / \
o
/ \
;; Type C
o
/ \
o
/ \
o o
/ \ / \
Normally, we have 14 trees for 5 numbers. But I categorize them within the 3 types above.
What I think is: 2 trees of same type will find the same solutions, given we permute all operators and numbers :
- It looks trivial for operators '+' and '-'.
- For '/' et '-', if we swap subtrees numbers to always have maximum on the left, we are left with always one operation (if possible), so the order does not matter.
My generated trees generated (in tree.c) for 5 numbers are :
1: (Op x (Op x (Op x (Op x x))))
2: (Op x (Op x (Op (Op x x) x)))
3: (Op x (Op (Op x x) (Op x x)))
4: (Op x (Op (Op x (Op x x)) x))
5: (Op x (Op (Op (Op x x) x) x))
6: (Op (Op x x) (Op x (Op x x)))
7: (Op (Op x x) (Op (Op x x) x))
8: (Op (Op x (Op x x)) (Op x x))
9: (Op (Op x (Op x (Op x x))) x)
10: (Op (Op x (Op (Op x x) x)) x)
11: (Op (Op (Op x x) x) (Op x x))
12: (Op (Op (Op x x) (Op x x)) x)
13: (Op (Op (Op x (Op x x)) x) x)
14: (Op (Op (Op (Op x x) x) x) x)
Categories:
;; 1 : type A
(Op x o
(Op x / \
(Op x o
(Op x / \
x)))) o
/ \
o
/ \
;; 2 : Type A
(Op x o
(Op x / \
(Op o
(Op x / \
x) o
x))) / \
o
/ \
;; 3 : Type C
(Op x o
(Op / \
(Op x o
x) / \
(Op x o o
x))) / \ / \
;; 4 : Type A
o
(Op x / \
(Op o
(Op x / \
(Op x o
x)) / \
x)) o
/ \
;; 5 : Type A
(Op x o
(Op / \
(Op o
(Op x / \
x) o
x) / \
x)) o
/ \
;; 6 : Type B
(Op o
(Op x / \
x) o o
(Op x / \ / \
(Op x o
x))) / \
;; 7 : Type B
(Op o
(Op x / \
x) o o
(Op / \ / \
(Op x o
x) / \
x))
;; 8 : Type B
(Op o
(Op x / \
(Op x o o
x)) / \ / \
(Op x o
x)) / \
;; 9 : Type A
(Op o
(Op x / \
(Op x o
(Op x / \
x))) o
x) / \
o
/ \
;; 10 : Type A
(Op o
(Op x / \
(Op o
(Op x / \
x) o
x)) / \
x) o
/ \
;; 11 : Type B
(Op o
(Op / \
(Op x o o
x) / / \
x) o
(Op x / \
x))
;; 12 : Type C
(Op o
(Op / \
(Op x o
x) / \
(Op x o o
x)) / \ / \
x)
;; 13 : Type A
(Op o
(Op / \
(Op x o
(Op x / \
x)) o
x) / \
x) o
/ \
;; 14 : Type A
(Op o
(Op / \
(Op o
(Op x / \
x) o
x) / \
x) o
x) / \
Below are all categories by input of N numbers, for N={2,3,4,5,6} :
w is max leaves on same level, and h is height (distance from root to lowest leaf).
2 leaves (1, Catalan=1):
o
/ \
width=2, height=1
3 leaves (1, Catalan=2):
o
/ \
o
/ \
w=2, h=2
4 leaves (2, Catalan=5):
o o
/ \ / \
o o o
/ \ / \ / \
o
/ \
w=2, h=3 w=4, h=2
5 leaves (3, Catalan=14):
o o o
/ \ / \ / \
o o o o
/ \ / \ / \ / \
o o o o
/ \ / \ / \ / \
o
/ \
w=2, h=4 w=3, h=3 w=4, h=3
6 leaves (6, Catalan=42):
o o o o
/ \ / \ / \ / \
o o o o o
/ \ / \ / \ / \ / \
o o o o o
/ \ / \ / \ / \ / \
o o o o o
/ \ / \ / \ / \ / \
o
/ \
w=2, h=5 w=3, h=4 w=3, h=4 w=4, h=4
o o
/ \ / \
o o o o
/ \ / \ / \ / \
o o o o
/ \ / \ / \ / \
w=4, h=3 w=4, h=3

View File

@@ -5,6 +5,7 @@
#define NANOSEC 1000000000.0
#define MILLISEC 1000
int displaytimer=0;
static struct timespec start;
void start_timer()

38
tree.c
View File

@@ -15,9 +15,11 @@ NODE *get_node()
if (!freenodes) {
register int i;
freenodes=malloc(ALLOCSIZE*sizeof(NODE));
totnodes+=ALLOCSIZE;
printf("allocating %d nodes - total nodes=%d\n", ALLOCSIZE, totnodes);
# ifdef DEBUG_MEM
printf("get_node: allocating %d new nodes - total nodes=%d\n", ALLOCSIZE, totnodes);
# endif
freenodes=malloc(ALLOCSIZE*sizeof(NODE));
for (i=0; i<ALLOCSIZE-1; ++i) { /* create chained list */
(freenodes+i)->left=NULL;
(freenodes+i)->right=NULL;
@@ -74,6 +76,7 @@ void print_node(node, side, depth, details)
print_node(node->right, TREE_RIGHT, depth+1, details);
break;
case 0:
case 5:
print_node(node->left, TREE_LEFT, depth+1, details);
print_node(node->right, TREE_RIGHT, depth+1, details);
if (node->type==TREE_NODE) {
@@ -81,6 +84,8 @@ void print_node(node, side, depth, details)
} else {
printf("%d ", node->val);
}
if (details==5 && depth==0)
printf("p");
break;
case 3:
if (node->type==TREE_NODE) {
@@ -127,7 +132,6 @@ void print_node(node, side, depth, details)
print_node(node->left, TREE_LEFT, depth+1, details);
print_node(node->right, TREE_RIGHT, depth+1, details);
break;;
}
}
@@ -135,7 +139,6 @@ void print_tree(tree, details)
TREE *tree;
int details;
{
int i;
switch (details) {
case 2:
print_node(tree->head, TREE_TOP, 0, details);
@@ -377,24 +380,31 @@ int n_trees()
}
#ifdef STANDALONE
void main(ac, av)
int main(ac, av)
int ac;
char **av;
{
int n, details=0;
int n, details=0, type=0;
char array[1024];
if (ac<2 || ac>3) {
fprintf(stderr, "usage: %s nodes [type]\n", *av);
fprintf(stderr, "type can be 0 (RPN, default, 1 (polish), 2 (details), 3 (lisp notation), 4 (parenthesed notation)\n");
if (ac<3 || ac>4) {
fprintf(stderr, "usage: %s type nodes [display]\n", *av);
fprintf(stderr, "type : 0 for Catalan, 1 for Wedderburn\n");
fprintf(stderr, "display can be 0 (RPN, default, 1 (polish), 2 (details), 3 (lisp notation), 4 (parenthesed notation)\n");
exit (1);
}
if (ac==3) {
details=atoi(av[2]);
if (ac==4) {
details=atoi(av[3]);
}
type=atoi(av[1]);
n=atoi(av[2]);
if (type == 0) {
printf("generating Calalan tree...\n");
gen_tree(array, n, 0, 0);
} else {
printf("generating Wedderburn tree...\n");
gen_reduced_trees(n+1);
}
n=atoi(av[1]);
gen_reduced_trees(n+1);
//gen_tree(array, n, 0, 0);
print_trees(details);
exit(0);
}