Compare commits
10 Commits
fb297756b6
...
1.0
Author | SHA1 | Date | |
---|---|---|---|
26dc599d88 | |||
9ee0453611 | |||
80bd319a6d | |||
3da1891778 | |||
691bc6304a | |||
38838f6e4f | |||
05dbc9d261 | |||
e28083c107 | |||
d2b71dff2e | |||
c6851b22c0 |
2
Makefile
2
Makefile
@@ -33,7 +33,7 @@ TIME := \time -f "\ttime: %E real, %U user, %S sys\n\tcontext-switch:\t%c+%w, pa
|
|||||||
export PATH := .:$(PATH)
|
export PATH := .:$(PATH)
|
||||||
|
|
||||||
TARGETS=lceb tree oper timer
|
TARGETS=lceb tree oper timer
|
||||||
OBJS=lceb.o tree.o oper.o stack.o eval.o best.o timer.o stack.o signal.o
|
OBJS=lceb.o tree.o oper.o stack.o eval.o best.o timer.o stack.o
|
||||||
INCLUDES=lceb.h
|
INCLUDES=lceb.h
|
||||||
DEPS=$(INCLUDES) Makefile
|
DEPS=$(INCLUDES) Makefile
|
||||||
|
|
||||||
|
141
README.md
Normal file
141
README.md
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
# lceb - a Countdown solver in C.
|
||||||
|
|
||||||
|
`lceb` will find the best solutions(s) for the
|
||||||
|
[Numbers part of the Countdown game](https://en.wikipedia.org/wiki/Countdown_(game_show)#Numbers_round)
|
||||||
|
"[_Le compte est Bon_](https://fr.wikipedia.org/wiki/Des_chiffres_et_des_lettres#Le_Compte_est_Bon)" in French).
|
||||||
|
|
||||||
|
## Requisites
|
||||||
|
|
||||||
|
`lceb` has only been tested on `GNU/Linux` systems. It should not compile at all on `Windows`. I am not sure about `MacOS`.
|
||||||
|
|
||||||
|
## Get the source
|
||||||
|
|
||||||
|
``` text
|
||||||
|
git clone https://git.bodiccea.tk/bruno/Le-Compte-est-Bon.git
|
||||||
|
```
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
To display more debug information, you may first enable some DEBUG flags in the `Makefile`. I usually use the `-DDEBUG`, `-DDEBUG_MAIN`, and `-DDEBUG_MEM`, as below
|
||||||
|
|
||||||
|
```makefile
|
||||||
|
CFLAGS:=$(CFLAGS) -DDEBUG # general (signal handler, etc...)
|
||||||
|
CFLAGS:=$(CFLAGS) -DDEBUG_MAIN # general information in main
|
||||||
|
#CFLAGS:=$(CFLAGS) -DDEBUG_MAINSLEEP # sleep 1 sec within main loop (SIGINTR test)
|
||||||
|
#CFLAGS:=$(CFLAGS) -DDEBUG_MAINLOOP # main loop (do not use this!)
|
||||||
|
#CFLAGS:=$(CFLAGS) -DDEBUG_TIMER # timer
|
||||||
|
#CFLAGS:=$(CFLAGS) -DDEBUG_SIGNAL # signal
|
||||||
|
#CFLAGS:=$(CFLAGS) -DDEBUG_BEST # best control
|
||||||
|
#CFLAGS:=$(CFLAGS) -DDEBUG_TREE # tree
|
||||||
|
#CFLAGS:=$(CFLAGS) -DDEBUG_OPER # oper
|
||||||
|
#CFLAGS:=$(CFLAGS) -DDEBUG_STACK # stack
|
||||||
|
#CFLAGS:=$(CFLAGS) -DDEBUG_STACK2 # stack - more details
|
||||||
|
#CFLAGS:=$(CFLAGS) -DDEBUG_EVAL # eval
|
||||||
|
#CFLAGS:=$(CFLAGS) -DDEBUG_EVAL2 # eval 2
|
||||||
|
#CFLAGS:=$(CFLAGS) -DDEBUG_EVAL3 # eval 3
|
||||||
|
CFLAGS:=$(CFLAGS) -DDEBUG_MEM # malloc
|
||||||
|
```
|
||||||
|
|
||||||
|
To build the binaries just run:
|
||||||
|
```console
|
||||||
|
$ make lceb
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### basic usage and output
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ ./lceb 2 7 1 7 8 8
|
||||||
|
timer started...
|
||||||
|
mem: allocating operators working area (5 bytes)
|
||||||
|
new_stack: allocating 1024 stacks
|
||||||
|
get_node: allocating 1024 new nodes - total nodes=1024
|
||||||
|
target assigned (2).
|
||||||
|
SIGINT armed.
|
||||||
|
stacks : 30
|
||||||
|
ops combinations: 256
|
||||||
|
trees : 14
|
||||||
|
max evaluations : 537,600
|
||||||
|
Le compte est bon: 5 solutions with 2 ops (1st after 0.00030 secs).
|
||||||
|
1 8 7 - +
|
||||||
|
1 8 8 / +
|
||||||
|
1 7 7 / +
|
||||||
|
1 8 + 7 -
|
||||||
|
8 7 1 - -
|
||||||
|
Total time elapsed: 0.01327 secs, nodes/leaves evaluated:401,817/397,973
|
||||||
|
```
|
||||||
|
`lceb` takes at least 3 arguments: target number (the one to find), and from 2 to 6 use-able numbers.
|
||||||
|
The solutions are displayed by default in RPN notation (here `1 8 7 - +` means `(8-7)+1`).
|
||||||
|
|
||||||
|
### options
|
||||||
|
|
||||||
|
You can see the available options with `lceb -h`:
|
||||||
|
```console
|
||||||
|
$ ./lceb -h
|
||||||
|
usage: ./lceb [options] target n1 n2 [...n6]
|
||||||
|
Countdown game solver.
|
||||||
|
-1: Show only one solution (immediate stop when exact solution found
|
||||||
|
-c: Show solutions timer
|
||||||
|
-d TYPE: Solutions display type. TYPE can be:
|
||||||
|
r: RPN (default)
|
||||||
|
p: Polish
|
||||||
|
l: Lisp (binary operators)
|
||||||
|
i: Infix (full parentheses)
|
||||||
|
d: Suitable for dc(1) input
|
||||||
|
t: Tree
|
||||||
|
-i: Show intermediate solutions
|
||||||
|
-s: Do not show summary (time, nodes evaluated)
|
||||||
|
-t: Use less trees (Wedderburn–Etherington instead of Catalan)
|
||||||
|
-T TIMER: Will stop after TIMER 1/10th seconds
|
||||||
|
-h: This help
|
||||||
|
```
|
||||||
|
|
||||||
|
### the -t option
|
||||||
|
|
||||||
|
Using `-t` gives a large performance boost. Compare the two output below :
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ ./lceb -di -c 997 4 8 25 2 5 3
|
||||||
|
timer started...
|
||||||
|
mem: allocating operators working area (6 bytes)
|
||||||
|
new_stack: allocating 1024 stacks
|
||||||
|
get_node: allocating 1024 new nodes - total nodes=1024
|
||||||
|
target assigned (997).
|
||||||
|
SIGINT armed.
|
||||||
|
stacks : 720
|
||||||
|
ops combinations: 1,024
|
||||||
|
trees : 42
|
||||||
|
max evaluations : 185,794,560
|
||||||
|
get_node: allocating 1024 new nodes - total nodes=2048
|
||||||
|
get_node: allocating 1024 new nodes - total nodes=3072
|
||||||
|
get_node: allocating 1024 new nodes - total nodes=4096
|
||||||
|
get_node: allocating 1024 new nodes - total nodes=5120
|
||||||
|
Le compte est bon: 3 solutions with 3 ops (1st after 0.00841 secs).
|
||||||
|
0.00841 secs: (((5 * 8) * 25) - 3)
|
||||||
|
0.00841 secs: (((5 * 25) * 8) - 3)
|
||||||
|
0.00841 secs: (((8 * 25) * 5) - 3)
|
||||||
|
Total time elapsed: 3.40713 secs, nodes/leaves evaluated:138,979,332/132,474,697
|
||||||
|
```
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ ./lceb -di -t -c 997 4 8 25 2 5 3
|
||||||
|
timer started...
|
||||||
|
mem: allocating operators working area (6 bytes)
|
||||||
|
new_stack: allocating 1024 stacks
|
||||||
|
get_node: allocating 1024 new nodes - total nodes=1024
|
||||||
|
target assigned (997).
|
||||||
|
SIGINT armed.
|
||||||
|
stacks : 720
|
||||||
|
ops combinations: 1,024
|
||||||
|
trees : 6
|
||||||
|
max evaluations : 26,542,080
|
||||||
|
get_node: allocating 1024 new nodes - total nodes=2048
|
||||||
|
Le compte est bon: 3 solutions with 3 ops (1st after 0.15392 secs).
|
||||||
|
0.15392 secs: (((5 * 8) * 25) - 3)
|
||||||
|
0.15392 secs: (((5 * 25) * 8) - 3)
|
||||||
|
0.15393 secs: (((8 * 25) * 5) - 3)
|
||||||
|
Total time elapsed: 0.47460 secs, nodes/leaves evaluated:18,793,369/18,650,735
|
||||||
|
```
|
||||||
|
|
||||||
|
It should be noted that having general performance improvement does not mean that the first solution will be found sooner.
|
23
best.c
23
best.c
@@ -12,7 +12,7 @@ static int bestops=MAXINT;
|
|||||||
|
|
||||||
static BEST bests[1024*10]; /* TODO: should be dynamic */
|
static BEST bests[1024*10]; /* TODO: should be dynamic */
|
||||||
static int nbests=0;
|
static int nbests=0;
|
||||||
extern int displaytimer;
|
extern int displaytimer, firstonly;
|
||||||
int displayintermediate=0;
|
int displayintermediate=0;
|
||||||
int displaytype=0;
|
int displaytype=0;
|
||||||
|
|
||||||
@@ -43,8 +43,13 @@ int check_best(res, nops, node, values, ops)
|
|||||||
if (diff < bestdiff || (diff == bestdiff && nops < bestops)) {
|
if (diff < bestdiff || (diff == bestdiff && nops < bestops)) {
|
||||||
//best=res;
|
//best=res;
|
||||||
// clear old bests
|
// clear old bests
|
||||||
for (i=0; i<nbests; ++i)
|
for (i=0; i<nbests; ++i) {
|
||||||
free_node(bests[i].root);
|
found=free_node(bests[i].root);
|
||||||
|
# ifdef DEBUG_TREE
|
||||||
|
printf("check_best: freed %d nodes\n", found);
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
bestdiff=diff;
|
bestdiff=diff;
|
||||||
bestops=nops;
|
bestops=nops;
|
||||||
nbests=0;
|
nbests=0;
|
||||||
@@ -120,12 +125,16 @@ void print_best(node, values, pops, depth)
|
|||||||
|
|
||||||
void print_bests()
|
void print_bests()
|
||||||
{
|
{
|
||||||
int i=0;
|
int i=0, j=firstonly? 1: nbests;
|
||||||
printf("BEST SOLUTION: res=%d diff=%d ops=%d ", bests[i].res, bestdiff, bestops);
|
if (bestdiff==0) {
|
||||||
|
printf("Le compte est bon: %d solutions with %d ops ", nbests, bestops);
|
||||||
|
} else {
|
||||||
|
printf("Found %d results with difference %d and %d ops ", nbests, bestdiff, bestops);
|
||||||
|
}
|
||||||
//if (displaytimer)
|
//if (displaytimer)
|
||||||
printf("found after %.5f secs.", get_timer(bests[i].timer));
|
printf("(1st after %.5f secs).", get_timer(bests[i].timer));
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
for (i=0; i<nbests; ++i) {
|
for (i=0; i<j; ++i) {
|
||||||
//print_best(bests[i].root, bests[i].values, bests[i].oper, 0);
|
//print_best(bests[i].root, bests[i].values, bests[i].oper, 0);
|
||||||
//printf("%5d =", bests[i].res);
|
//printf("%5d =", bests[i].res);
|
||||||
if (displaytimer)
|
if (displaytimer)
|
||||||
|
4
eval.c
4
eval.c
@@ -82,7 +82,7 @@ int eval_node(node, depth, pvals, pops, ncalcs)
|
|||||||
if (val1<val2) {
|
if (val1<val2) {
|
||||||
NODE *tmp=node->left;
|
NODE *tmp=node->left;
|
||||||
# ifdef DEBUG_EVAL2
|
# ifdef DEBUG_EVAL2
|
||||||
printf("eval: Sub: swapping val1=%d val2=%d\n", val1, val2);
|
printf("eval: Div: swapping val1=%d val2=%d\n", val1, val2);
|
||||||
# endif
|
# endif
|
||||||
node->left=node->right;
|
node->left=node->right;
|
||||||
node->right=tmp;
|
node->right=tmp;
|
||||||
@@ -115,7 +115,7 @@ int eval_node(node, depth, pvals, pops, ncalcs)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sigint_received) {
|
if (sigint_received) {
|
||||||
print_bests();
|
print_results();
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
24
lceb.c
24
lceb.c
@@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
static char *cmd;
|
static char *cmd;
|
||||||
static int treetype=TREE_CATALAN;
|
static int treetype=TREE_CATALAN;
|
||||||
|
static int maxmillisecs=0;
|
||||||
extern int displaytimer, displayintermediate, displaytype, firstonly;
|
extern int displaytimer, displayintermediate, displaytype, firstonly;
|
||||||
int displaysummary=1;
|
int displaysummary=1;
|
||||||
|
|
||||||
@@ -42,7 +43,7 @@ void help()
|
|||||||
{
|
{
|
||||||
usage();
|
usage();
|
||||||
fprintf(stderr, "Countdown game solver.\n");
|
fprintf(stderr, "Countdown game solver.\n");
|
||||||
fprintf(stderr, " -1: Stops immediately when one solution is found\n");
|
fprintf(stderr, " -1: Show only one solution (immediate stop when exact solution found\n");
|
||||||
fprintf(stderr, " -c: Show solutions timer\n");
|
fprintf(stderr, " -c: Show solutions timer\n");
|
||||||
fprintf(stderr, " -d TYPE: Solutions display type. TYPE can be:\n");
|
fprintf(stderr, " -d TYPE: Solutions display type. TYPE can be:\n");
|
||||||
fprintf(stderr, " r: RPN (default)\n");
|
fprintf(stderr, " r: RPN (default)\n");
|
||||||
@@ -54,6 +55,7 @@ void help()
|
|||||||
fprintf(stderr, " -i: Show intermediate solutions\n");
|
fprintf(stderr, " -i: Show intermediate solutions\n");
|
||||||
fprintf(stderr, " -s: Do not show summary (time, nodes evaluated)\n");
|
fprintf(stderr, " -s: Do not show summary (time, nodes evaluated)\n");
|
||||||
fprintf(stderr, " -t: Use less trees (Wedderburn–Etherington instead of Catalan)\n");
|
fprintf(stderr, " -t: Use less trees (Wedderburn–Etherington instead of Catalan)\n");
|
||||||
|
fprintf(stderr, " -T TIMER: Will stop after TIMER 1/10th seconds\n");
|
||||||
fprintf(stderr, " -h: This help\n");
|
fprintf(stderr, " -h: This help\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +77,7 @@ int main(ac, av)
|
|||||||
TREE *tree;
|
TREE *tree;
|
||||||
char intarray[1024];
|
char intarray[1024];
|
||||||
char *comb;
|
char *comb;
|
||||||
char *options="1thcisd:";
|
char *options="1thcisd:T:";
|
||||||
int option;
|
int option;
|
||||||
# ifdef DEBUG_MAINLOOP
|
# ifdef DEBUG_MAINLOOP
|
||||||
int eval;
|
int eval;
|
||||||
@@ -124,6 +126,9 @@ int main(ac, av)
|
|||||||
case 's':
|
case 's':
|
||||||
displaysummary=0;
|
displaysummary=0;
|
||||||
break;
|
break;
|
||||||
|
case 'T':
|
||||||
|
maxmillisecs=atoi(optarg)*100;
|
||||||
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
treetype=TREE_WEDDERBURN;
|
treetype=TREE_WEDDERBURN;
|
||||||
break;
|
break;
|
||||||
@@ -143,23 +148,26 @@ int main(ac, av)
|
|||||||
}
|
}
|
||||||
setlocale(LC_ALL, ""); /* to use "%'d" in printf */
|
setlocale(LC_ALL, ""); /* to use "%'d" in printf */
|
||||||
start_timer();
|
start_timer();
|
||||||
|
if (maxmillisecs)
|
||||||
|
set_alarm(maxmillisecs);
|
||||||
target=atoi(av[optind]);
|
target=atoi(av[optind]);
|
||||||
stacksize=ac-optind-1;
|
stacksize=ac-optind-1;
|
||||||
nops=stacksize-1;
|
nops=stacksize-1;
|
||||||
|
|
||||||
gen_combinations(nops);
|
|
||||||
ncombs=n_combs();
|
|
||||||
for (i=optind+1; i<ac; ++i) {
|
for (i=optind+1; i<ac; ++i) {
|
||||||
val=atoi(av[i]);
|
val=atoi(av[i]);
|
||||||
push_stack(&inputstack, val);
|
push_stack(&inputstack, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gen_stacks(&inputstack);
|
gen_stacks(&inputstack);
|
||||||
|
|
||||||
|
gen_combinations(nops);
|
||||||
|
ncombs=n_combs();
|
||||||
|
|
||||||
if (treetype==TREE_CATALAN) {
|
if (treetype==TREE_CATALAN) {
|
||||||
gen_tree(intarray, nops, 0, 0);
|
gen_tree(intarray, nops, 0, 0, 0);
|
||||||
} else {
|
} else {
|
||||||
gen_reduced_trees(nops);
|
gen_tree(intarray, nops, 0, 0, 1);
|
||||||
|
//gen_reduced_trees(nops);
|
||||||
}
|
}
|
||||||
set_target(target);
|
set_target(target);
|
||||||
set_intr();
|
set_intr();
|
||||||
|
10
lceb.h
10
lceb.h
@@ -1,12 +1,15 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#define MAXINPUT (6) /* max numbers as input */
|
#define MAXINPUT (10) /* max numbers as input */
|
||||||
#define ALLOCSIZE (1024) /* # of elements to alloc */
|
#define ALLOCSIZE (1024) /* # of elements to alloc */
|
||||||
|
|
||||||
#define MIN(a,b) (((a)<(b))?(a):(b))
|
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||||
#define MAX(a,b) (((a)>(b))?(a):(b))
|
#define MAX(a,b) (((a)>(b))?(a):(b))
|
||||||
#define ABS(a) (((a)<0)?-(a):(a))
|
#define ABS(a) (((a)<0)?-(a):(a))
|
||||||
|
|
||||||
|
#define NANOSEC 1000000000.0
|
||||||
|
#define MILLISEC 1000
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
Nop='N',
|
Nop='N',
|
||||||
Add='+',
|
Add='+',
|
||||||
@@ -71,10 +74,11 @@ extern void print_results();
|
|||||||
/* signal.c */
|
/* signal.c */
|
||||||
extern void set_intr();
|
extern void set_intr();
|
||||||
extern int stopped();
|
extern int stopped();
|
||||||
|
extern void set_alarm(int ms);
|
||||||
|
|
||||||
/* tree.c */
|
/* tree.c */
|
||||||
extern NODE *get_node();
|
extern NODE *get_node();
|
||||||
extern void free_node(NODE *node);
|
extern int free_node(NODE *node);
|
||||||
extern int compare_nodes(NODE *node1, NODE *node2, int depth);
|
extern int compare_nodes(NODE *node1, NODE *node2, int depth);
|
||||||
extern void print_node(NODE *node, char side, int depth, int details);
|
extern void print_node(NODE *node, char side, int depth, int details);
|
||||||
extern void print_tree(TREE *tree, int details);
|
extern void print_tree(TREE *tree, int details);
|
||||||
@@ -85,7 +89,7 @@ extern NODE *dup_node(NODE *src);
|
|||||||
extern NODE *build_tree(char *desc, int size);
|
extern NODE *build_tree(char *desc, int size);
|
||||||
//extern void gen_tree(int *seq, int n, int nb1, int nb0);
|
//extern void gen_tree(int *seq, int n, int nb1, int nb0);
|
||||||
extern void gen_reduced_trees(int n);
|
extern void gen_reduced_trees(int n);
|
||||||
extern void gen_tree(char *seq, int n, int nb1, int nb0);
|
extern void gen_tree(char *seq, int n, int nb1, int nb0, int reduced);
|
||||||
extern TREE *nth_tree(int n);
|
extern TREE *nth_tree(int n);
|
||||||
extern int n_trees();
|
extern int n_trees();
|
||||||
|
|
||||||
|
17
oper.c
17
oper.c
@@ -4,7 +4,7 @@
|
|||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include "lceb.h"
|
#include "lceb.h"
|
||||||
|
|
||||||
static char *combs[1024]; /* should be dynamic */
|
static char **combs;
|
||||||
static int ncombs=0;
|
static int ncombs=0;
|
||||||
|
|
||||||
void print_comb(n)
|
void print_comb(n)
|
||||||
@@ -59,19 +59,23 @@ static char *combine(ops, len, n)
|
|||||||
void gen_combinations(nops)
|
void gen_combinations(nops)
|
||||||
int nops;
|
int nops;
|
||||||
{
|
{
|
||||||
char *ops="+-*/";
|
char *ops="/-*+";
|
||||||
int i, n_combs;
|
int i, n_combs;
|
||||||
int len_ops=strlen(ops);
|
int len_ops=strlen(ops);
|
||||||
# ifdef DEBUG_OPER
|
# ifdef DEBUG_OPER
|
||||||
printf("gen_combinations(%d)\n", nops);
|
printf("gen_combinations(%d)\n", nops);
|
||||||
# endif
|
# endif
|
||||||
n_combs=n_combine(len_ops, nops);
|
n_combs=n_combine(len_ops, nops);
|
||||||
//printf("gen: n=%d\n", n_combs);
|
# ifdef DEBUG_MEM
|
||||||
|
printf("allocating %d operators combinations\n", n_combs);
|
||||||
|
# endif
|
||||||
|
combs=malloc(sizeof (char*)*n_combs);
|
||||||
for (i=0; i<n_combs; ++i) {
|
for (i=0; i<n_combs; ++i) {
|
||||||
combs[ncombs]=strdup(combine(ops, nops, i));
|
combs[ncombs]=strdup(combine(ops, nops, i));
|
||||||
ncombs++;
|
ncombs++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int n_combs()
|
int n_combs()
|
||||||
{
|
{
|
||||||
return ncombs;
|
return ncombs;
|
||||||
@@ -87,12 +91,17 @@ int main(ac, av)
|
|||||||
int ac;
|
int ac;
|
||||||
char **av;
|
char **av;
|
||||||
{
|
{
|
||||||
char *ops="+-*/", *p;
|
char *ops="/-+*", *p;
|
||||||
int len_ops=strlen(ops);
|
int len_ops=strlen(ops);
|
||||||
int i, nops, ncombs;
|
int i, nops, ncombs;
|
||||||
|
|
||||||
|
if (ac!=2) {
|
||||||
|
fprintf(stderr, "usage: %s nops\n", *av);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
nops=atoi(*(av+1));
|
nops=atoi(*(av+1));
|
||||||
ncombs=n_combine(len_ops, nops);
|
ncombs=n_combine(len_ops, nops);
|
||||||
|
combs=malloc(sizeof (char*)*ncombs);
|
||||||
printf("# operators combinations : %d\nlist = ", ncombs);
|
printf("# operators combinations : %d\nlist = ", ncombs);
|
||||||
for (i=0; i<ncombs; ++i) {
|
for (i=0; i<ncombs; ++i) {
|
||||||
p=combine(ops, nops, i);
|
p=combine(ops, nops, i);
|
||||||
|
33
signal.c
33
signal.c
@@ -1,33 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <signal.h>
|
|
||||||
|
|
||||||
int sigint_received=0;
|
|
||||||
|
|
||||||
static void stopall()
|
|
||||||
{
|
|
||||||
printf("SIGINT RECEIVED: aborting eval\n");
|
|
||||||
sigint_received=1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int stopped()
|
|
||||||
{
|
|
||||||
return sigint_received;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_intr()
|
|
||||||
{
|
|
||||||
struct sigaction sig;
|
|
||||||
|
|
||||||
sig.sa_handler = stopall;
|
|
||||||
sigemptyset(&sig.sa_mask);
|
|
||||||
//sigaddset(&new.sa_mask, SIGINT);
|
|
||||||
//sigaddset(&new.sa_mask, SIGALRM);
|
|
||||||
sig.sa_flags = 0;
|
|
||||||
//sigaction(SIGINT, NULL, &old);
|
|
||||||
//if (old_action.sa_handler != SIG_IGN) {
|
|
||||||
sigaction(SIGINT, &sig, NULL);
|
|
||||||
sigaction(SIGALRM, &sig, NULL);
|
|
||||||
# ifdef DEBUG
|
|
||||||
printf("SIGINT and SIGALRM armed.\n");
|
|
||||||
# endif
|
|
||||||
}
|
|
8
stack.c
8
stack.c
@@ -52,7 +52,7 @@ STACK *new_stack(size, name, keep)
|
|||||||
STACK *stack;
|
STACK *stack;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
# ifdef DEBUG_STACK2
|
# ifdef DEBUG_STACK
|
||||||
printf("new_stack(size=%d, name=[%s] last=%d total=%d)\n",
|
printf("new_stack(size=%d, name=[%s] last=%d total=%d)\n",
|
||||||
size, name, laststack, totalstacks);
|
size, name, laststack, totalstacks);
|
||||||
# endif
|
# endif
|
||||||
@@ -82,7 +82,7 @@ STACK *new_stack(size, name, keep)
|
|||||||
strncpy(stack->name, name? name: "No name", sizeof(stack->name));
|
strncpy(stack->name, name? name: "No name", sizeof(stack->name));
|
||||||
//if (size) {
|
//if (size) {
|
||||||
//pelt=malloc(size*sizeof(int));
|
//pelt=malloc(size*sizeof(int));
|
||||||
stack->size=MAXINPUT;
|
stack->size=size;
|
||||||
//stack->stack=pelt;
|
//stack->stack=pelt;
|
||||||
//if (keep)
|
//if (keep)
|
||||||
// keep_stack(stack);
|
// keep_stack(stack);
|
||||||
@@ -146,7 +146,7 @@ STACK *dup_stack(stack, name)
|
|||||||
STACK *new;
|
STACK *new;
|
||||||
int *dst;
|
int *dst;
|
||||||
int size=stack->size, last=stack->last, i;
|
int size=stack->size, last=stack->last, i;
|
||||||
|
//printf("DUP: totalstacks=%d\n", totalstacks);
|
||||||
new=new_stack(size, name, 0);
|
new=new_stack(size, name, 0);
|
||||||
new->last=stack->last;
|
new->last=stack->last;
|
||||||
dst=new->stack;
|
dst=new->stack;
|
||||||
@@ -201,6 +201,8 @@ void gen_stacks(stack)
|
|||||||
int n=1;
|
int n=1;
|
||||||
int exists=1;
|
int exists=1;
|
||||||
|
|
||||||
|
printf("GEN: totalstacks=%d\n", totalstacks);
|
||||||
|
|
||||||
# ifdef DEBUG_STACK
|
# ifdef DEBUG_STACK
|
||||||
printf("generating stacks...\n");
|
printf("generating stacks...\n");
|
||||||
# endif
|
# endif
|
||||||
|
77
timer.c
77
timer.c
@@ -1,13 +1,68 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h>
|
#include <unistd.h>
|
||||||
|
#include <signal.h>
|
||||||
#define NANOSEC 1000000000.0
|
#include <sys/time.h>
|
||||||
#define MILLISEC 1000
|
#include <string.h>
|
||||||
|
#include "lceb.h"
|
||||||
|
|
||||||
|
int sigint_received=0;
|
||||||
int displaytimer=0;
|
int displaytimer=0;
|
||||||
static struct timespec start;
|
static struct timespec start;
|
||||||
|
|
||||||
|
static void stopall(signum)
|
||||||
|
int signum;
|
||||||
|
{
|
||||||
|
printf("SIGNAL %d RECEIVED: aborting eval\n", signum);
|
||||||
|
sigint_received=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int stopped()
|
||||||
|
{
|
||||||
|
return sigint_received;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_intr()
|
||||||
|
{
|
||||||
|
struct sigaction sig;
|
||||||
|
|
||||||
|
sig.sa_handler = stopall;
|
||||||
|
sigemptyset(&sig.sa_mask);
|
||||||
|
sig.sa_flags = 0;
|
||||||
|
sigaction(SIGINT, &sig, NULL);
|
||||||
|
//sigaction(SIGUSR1, &sig, NULL);
|
||||||
|
# ifdef DEBUG
|
||||||
|
printf("SIGINT armed.\n");
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_alarm(ms)
|
||||||
|
int ms;
|
||||||
|
{
|
||||||
|
struct sigaction sig;
|
||||||
|
struct itimerval timer;
|
||||||
|
|
||||||
|
/* Install timer_handler as the signal handler for SIGVTALRM. */
|
||||||
|
//memset (&sa, 0, sizeof (sa));
|
||||||
|
sig.sa_handler = stopall;
|
||||||
|
sigemptyset(&sig.sa_mask);
|
||||||
|
sig.sa_flags = 0;
|
||||||
|
sigaction (SIGALRM, &sig, NULL);
|
||||||
|
|
||||||
|
timer.it_value.tv_sec = ms/1000;
|
||||||
|
timer.it_value.tv_usec = (ms%1000)*1000;
|
||||||
|
# ifdef DEBUG
|
||||||
|
printf("alarm clock set to %.2f secs.\n",
|
||||||
|
timer.it_value.tv_sec + timer.it_value.tv_usec / 1000000.);
|
||||||
|
# endif
|
||||||
|
/* ... and every 250 msec after that. */
|
||||||
|
timer.it_interval.tv_sec = 0;
|
||||||
|
timer.it_interval.tv_usec = 0;
|
||||||
|
/* Start a virtual timer. It counts down whenever this process is executing. */
|
||||||
|
setitimer (ITIMER_REAL, &timer, NULL);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void start_timer()
|
void start_timer()
|
||||||
{
|
{
|
||||||
printf("timer started...\n");
|
printf("timer started...\n");
|
||||||
@@ -44,18 +99,20 @@ int main(ac, av)
|
|||||||
char **av;
|
char **av;
|
||||||
{
|
{
|
||||||
int delay;
|
int delay;
|
||||||
struct timespec end, tsdelay;
|
struct timespec end;
|
||||||
|
|
||||||
if (ac != 2) {
|
if (ac != 2) {
|
||||||
fprintf(stderr, "usage: %s msecs\n", *av);
|
fprintf(stderr, "usage: %s msecs\n", *av);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
delay=atoi(*(av+1));
|
delay=atoi(*(av+1))*10;
|
||||||
start_timer();
|
start_timer();
|
||||||
tsdelay.tv_sec=delay/MILLISEC;
|
set_intr();
|
||||||
tsdelay.tv_nsec=delay%MILLISEC;
|
set_alarm(delay);
|
||||||
printf("delay %d=%ld:%ld\n", delay, tsdelay.tv_sec, tsdelay.tv_nsec);
|
//tsdelay.tv_sec=delay/MILLISEC;
|
||||||
nanosleep(&tsdelay, NULL);
|
//tsdelay.tv_nsec=delay%MILLISEC;
|
||||||
|
//printf("delay %d=%ld:%ld\n", delay, tsdelay.tv_sec, tsdelay.tv_nsec);
|
||||||
|
sleep(5);
|
||||||
set_timer(&end);
|
set_timer(&end);
|
||||||
printf("Time elapsed: %.5f seconds\n", get_timer(end));
|
printf("Time elapsed: %.5f seconds\n", get_timer(end));
|
||||||
|
|
||||||
|
64
tree.c
64
tree.c
@@ -39,19 +39,28 @@ NODE *get_node()
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_node(node)
|
int free_node(node)
|
||||||
NODE *node;
|
NODE *node;
|
||||||
{
|
{
|
||||||
if (node->left) {
|
int n=0;
|
||||||
free_node(node->left);
|
if (node->type==TREE_NODE) {
|
||||||
|
# ifdef DEBUG_TREE2
|
||||||
|
printf("free tree: ");
|
||||||
|
print_node(node, 3);
|
||||||
|
# endif
|
||||||
|
n+=free_node(node->left);
|
||||||
node->left=NULL;
|
node->left=NULL;
|
||||||
}
|
n+=free_node(node->right);
|
||||||
if (node->right) {
|
|
||||||
free_node(node->right);
|
|
||||||
node->right=NULL;
|
node->right=NULL;
|
||||||
|
# ifdef DEBUG_TREE2
|
||||||
|
printf("free tree: ");
|
||||||
|
print_node(node, 3);
|
||||||
|
# endif
|
||||||
}
|
}
|
||||||
node->next=freenodes;
|
node->next=freenodes;
|
||||||
freenodes=node;
|
freenodes=node;
|
||||||
|
n++;
|
||||||
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
int compare_nodes(node1, node2, depth)
|
int compare_nodes(node1, node2, depth)
|
||||||
@@ -290,7 +299,6 @@ NODE *build_tree(desc, size)
|
|||||||
node->type=TREE_LEAF;
|
node->type=TREE_LEAF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,36 +382,55 @@ void gen_reduced_trees(n)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gen_tree(seq, n, nb1, nb0)
|
void gen_tree(seq, n, nb1, nb0, reduced)
|
||||||
char *seq;
|
char *seq;
|
||||||
int n; /* number of nodes */
|
int n; /* number of nodes */
|
||||||
int nb1; /* number of "1" */
|
int nb1; /* number of "1" */
|
||||||
int nb0; /* number of "0" */
|
int nb0; /* number of "0" */
|
||||||
|
int reduced;
|
||||||
{
|
{
|
||||||
char name[80];
|
char name[80];
|
||||||
TREE *tree;
|
TREE *tree;
|
||||||
|
NODE *node;
|
||||||
|
int i;
|
||||||
|
|
||||||
# ifdef DEBUG_TREE
|
# ifdef DEBUG_TREE
|
||||||
printf("gen_tree(n=%d, nb1=%d, nb0=%d)\n", n, nb1, nb0);
|
printf("gen_tree(n=%d, nb1=%d, nb0=%d)\n", n, nb1, nb0);
|
||||||
# endif
|
# endif
|
||||||
if((nb1 + nb0) == 2*n) { /* end */
|
if ((nb1 + nb0) == 2*n) { /* end */
|
||||||
seq[2*n] = '0';
|
seq[2*n] = '0';
|
||||||
seq[2*n+1] = 0;
|
seq[2*n+1] = 0;
|
||||||
ntrees++;
|
node=build_tree(seq, 2*n+1);
|
||||||
sprintf(name, "Tree %d", ntrees);
|
if (reduced) {
|
||||||
tree=new_tree(name);
|
for (i=0; i<ntrees; ++i) {
|
||||||
tree->head=build_tree(seq, 2*n+1);
|
if (compare_nodes(node, nth_tree(i)->head, 0)) {
|
||||||
|
# ifdef DEBUG_TREE
|
||||||
|
printf("gen_tree: skipping unused tree (%d nodes freed)\n", free_node(node));
|
||||||
|
# else
|
||||||
|
free_node(node);
|
||||||
|
# endif
|
||||||
|
node=NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (node) {
|
||||||
|
ntrees++;
|
||||||
|
sprintf(name, "Tree %d", ntrees);
|
||||||
|
tree=new_tree(name);
|
||||||
|
tree->head=node;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(nb1 >= nb0 && nb1 < n) {
|
if (nb1 >= nb0 && nb1 < n) {
|
||||||
seq[nb1+nb0] = '1';
|
seq[nb1+nb0] = '1';
|
||||||
gen_tree(seq, n, nb1+1, nb0);
|
gen_tree(seq, n, nb1+1, nb0, reduced);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(nb0 < nb1 && nb1 <=n) {
|
if(nb0 < nb1 && nb1 <=n) {
|
||||||
seq[nb1+nb0] = '0';
|
seq[nb1+nb0] = '0';
|
||||||
gen_tree(seq, n, nb1, nb0+1);
|
gen_tree(seq, n, nb1, nb0+1, reduced);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -444,10 +471,11 @@ int main(ac, av)
|
|||||||
n=atoi(av[2]);
|
n=atoi(av[2]);
|
||||||
if (type == 0) {
|
if (type == 0) {
|
||||||
printf("generating Calalan tree...\n");
|
printf("generating Calalan tree...\n");
|
||||||
gen_tree(array, n, 0, 0);
|
gen_tree(array, n, 0, 0, 0);
|
||||||
} else {
|
} else {
|
||||||
printf("generating Wedderburn tree...\n");
|
printf("generating Wedderburn tree...\n");
|
||||||
gen_reduced_trees(n);
|
gen_tree(array, n, 0, 0, 1);
|
||||||
|
//gen_reduced_trees(n);
|
||||||
}
|
}
|
||||||
print_trees(details);
|
print_trees(details);
|
||||||
exit(0);
|
exit(0);
|
||||||
|
Reference in New Issue
Block a user