game.c
/*
* game.c
*
* Created on: 2011-9-27
* Author: brunie
*/
#include "game.h"
#include "stack.h"
Node* standardize_tree(Node* root);
int save_unique(Game *game, Node *root);
void get_expression(Node *root, char *exp);
Node *copy_tree(Node *root);
void destroy_tree(Node *root);
int operate(Node *left, Node *right, Node *result, int type)
{
switch (type)
{
case ADD:
result->res = left->res + right->res;
result->op = '+';
result->left = left;
result->right = right;
break;
case SUB:
result->res = left->res - right->res;
result->op = '-';
result->left = left;
result->right = right;
break;
case MUL:
result->res = left->res * right->res;
result->op = '*';
result->left = left;
result->right = right;
break;
case DIV:
if (right->res != 0)
{
result->res = left->res / right->res;
result->op = '/';
result->left = left;
result->right = right;
}
break;
case RSUB:
result->res = right->res - left->res;
result->op = '-';
result->left = right;
result->right = left;
break;
case RDIV:
if (left->res != 0)
{
result->res = right->res / left->res;
result->op = '/';
result->left = right;
result->right = left;
}
break;
}
return 1;
}
int calculate(Node **node_list, int len, Game *game)
{
int i, j, k, tmp, type;
if (len == 1)
{
if (fabs(node_list[0]->res - FINAL_RESULT) < PRECISION)
{
save_unique(game, node_list[0]);
game->success = OK;
}
}
else
{
Node **next = (Node **) malloc((len - 1) * sizeof(pNode));
pNode tmp_result = (pNode) malloc(sizeof(Node));
next[0] = tmp_result;
for (i = 0; i < len; i++)
{
for (j = i + 1; j < len; j++)
{
tmp = 1;
for (k = 0; k < len; k++)
{
if (k != i && k != j)
{
next[tmp++] = node_list[k];
}
}
for (type = 0; type < OPERATOR_TYPES; type++)
{
operate(node_list[i], node_list[j], tmp_result, type);
calculate(next, len - 1, game);
}
}
}// for i
free(next);
free(tmp_result);
}//else
return 1;
}
void Game_execute(Game *game)
{
calculate(game->node_list, N_FIGURES, game);
}
int priority(char operator)
{
if (operator == 0)
return 3;
else if (operator == '+' || operator == '-')
return 1;
else
return 2;
}
Node* copy_tree(Node *root)
{
if (0 == root)
return 0;
Node *new_root = (Node *)malloc(sizeof(Node));
*new_root = *root;
new_root->left = copy_tree(root->left);
new_root->right = copy_tree(root->right);
return new_root;
}
void destroy_tree(Node *root)
{
if (root->left)
destroy_tree(root->left);
if (root->right)
destroy_tree(root->right);
free(root);
}
void sort_node(pNode *pnodes, int len)
{
int i,j;
int flag = 1;
for (i = 0; i < len - 1 && flag; i++)
{
flag = 0;
for (j = 0; j < len - i - 1; j++)
{
if (pnodes[j]->res > pnodes[j + 1]->res)
{
pNode tmp = pnodes[j];
pnodes[j] = pnodes[j + 1];
pnodes[j + 1] = tmp;
flag = 1;
}
}
}
/*for (i = 0; i < len; i++)
printf("%f ", (*pnodes[i])->res);
printf("\n");*/
}
Node* create_tree(pNode *left_nodes, int left_len,
pNode *right_nodes, int right_len, char op)
{
sort_node(left_nodes, left_len);
sort_node(right_nodes, right_len);
pNode left_result, right_result;
int type;
int i;
if (op == '+')
type = ADD;
else
type = MUL;
if (left_len >= 2)
{
for (i = 0; i < left_len - 1; i++)
{
left_result = (pNode) malloc(sizeof(Node));
operate(left_nodes[i], left_nodes[i + 1], left_result, type);
left_nodes[i + 1] = left_result;
}
}
else
{
left_result = left_nodes[0];
}
if (right_len >= 1)
{
for (i = 0; i < right_len; i++)
{
right_result = (pNode) malloc(sizeof(Node));
operate(left_result, right_nodes[i], right_result, type + 1);
left_result = right_result;
}
}
return left_result;
}
Node* standardize_tree(Node* root)
{
Node *tmp, *mid_root;
istack *open = (istack*)malloc(sizeof(istack));
pNode left_nodes[N_FIGURES];
pNode right_nodes[N_FIGURES];
int left_len = 0, right_len = 0;
char op_a, op_b, op;
init_stack(open);
tmp = root;
op = tmp->op;
if (op == '+' || op == '-')
{
op = op_a = '+';
op_b = '-';
}
else
{
op = op_a = '*';
op_b = '/';
}
do
{
if (tmp->op == op_a)
{
push(open, tmp);
tmp = tmp->left;
}
else if (tmp->op == op_b)
{
push(open, tmp);
mid_root = tmp->right;
if (tmp->right->op)
mid_root = standardize_tree(tmp->right);
right_nodes[right_len++] = mid_root;
tmp->right = 0;
tmp = tmp->left;
}
else
{
mid_root = tmp;
if (tmp->op)
mid_root = standardize_tree(tmp);
left_nodes[left_len++] = mid_root;
if (!stack_empty(open))
{
pop(open, &tmp);
while (!tmp->right && !stack_empty(open))
{
free(tmp);
pop(open, &tmp);
}
mid_root = tmp;
tmp = tmp->right;
if (mid_root->op)
free(mid_root);
}
else
tmp = 0;
}
} while (tmp || !stack_empty(open));
free(open);
mid_root = create_tree(left_nodes, left_len, right_nodes, right_len, op);
return mid_root;
}
int save_unique(Game *game, Node* root)
{
int i;
char *exp = (char*) malloc(EXPRESSION_LEN);
exp[0] = '\0';
Node *tmp_root = copy_tree(root);
tmp_root = standardize_tree(tmp_root);
get_expression(tmp_root, exp);
//printf("%s\n", exp);
destroy_tree(tmp_root);
for (i = 0; i < game->n_solutions; i++)
{
if (strcmp(exp, game->unique_expressions[i]) == 0)
{
break;
}
}
if (i == game->n_solutions)
{
if (game->n_solutions == MAX_N_SOLUTIONS)
{
game->unique_expressions = (char **) realloc(
game->unique_expressions,
(game->n_solutions + MAX_N_SOLUTIONS) * sizeof(char*));
if (!game->unique_expressions)
exit(OVERFLOW);
}
game->unique_expressions[game->n_solutions++] = exp;
return TRUE;
}
return FALSE;
}
void get_expression(Node *root, char *exp)
{
char left_op, right_op, op;
if (root->left == 0 && root->right == 0)
{
sprintf(exp + strlen(exp),"%d", (int)(root->res));
}
else
{
left_op = root->left->op;
right_op = root->right->op;
op = root->op;
if (priority(op) > priority(left_op))
{
sprintf(exp + strlen(exp),"(");
get_expression(root->left, exp);
sprintf(exp + strlen(exp),")");
}
else
get_expression(root->left, exp);
sprintf(exp + strlen(exp), " %c ", op);
if (priority(op) > priority(right_op)
|| (op == '-' && right_op == '-')
|| (op == '-' && right_op == '+')
|| (op == '/' && right_op == '*')
|| (op == '/' && right_op == '/'))
{
sprintf(exp + strlen(exp), "(");
get_expression(root->right, exp);
sprintf(exp + strlen(exp), ")");
}
else
get_expression(root->right, exp);
}
}
void print_results(Game *game)
{
printf("\nTotal %d unique results:\n", game->n_solutions);
int i;
for (i = 0; i < game->n_solutions; i++)
{
printf("%s = %d\n", game->unique_expressions[i], FINAL_RESULT);
}
}
void init_list(Game *game)
{
int i;
game->success = 0;
game->n_solutions = 0;
for (i = 0; i < N_FIGURES; i++)
{
game->node_list[i]->res = game->figures[i];
}
}
int init_data(Game *game)
{
int i;
game->figures = (int *)malloc(N_FIGURES * sizeof (int));
game->node_list = (pNode *)malloc(N_FIGURES * sizeof (pNode));
game->unique_expressions = (char **)malloc(MAX_N_SOLUTIONS * sizeof (char *));
if (!(game->figures && game->node_list && game->unique_expressions))
exit(OVERFLOW);
for (i = 0; i < N_FIGURES; i++)
{
game->node_list[i] = (pNode)malloc(sizeof(Node));
if (!game->node_list[i])
exit(OVERFLOW);
game->node_list[i]->left = 0;
game->node_list[i]->right = 0;
game->node_list[i]->op = 0;
}
return TRUE;
}
void destory_data(Game *game)
{
int i;
if (game->figures)
{
free(game->figures);
game->figures = 0;
}
if (game->node_list)
{
for (i = 0; i < N_FIGURES; i++)
{
free(game->node_list[i]);
}
free(game->node_list);
game->node_list = 0;
}
if (game->unique_expressions)
{
for (i = 0; i < game->n_solutions; i++)
{
free(game->unique_expressions[i]);
}
free(game->unique_expressions);
game->unique_expressions = 0;
}
}
game.h
/*
* game.h
*
* Created on: 2011-9-27
* Author: brunie
*/
#ifndef GAME_H_
#define GAME_H_
#define MAX_INPUT 13
#define MIN_INPUT 1
#define N_FIGURES 4
#define OPERATOR_TYPES 6
#define FINAL_RESULT 24
#define EXPRESSION_LEN 30
#define MAX_N_SOLUTIONS 100
#define PRECISION (1E-6)
#define TRUE 1
#define FALSE 0
#define OK 1
#define OVERFLOW (-2)
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <string.h>
typedef struct Node
{
double res;
struct Node *left;
struct Node *right;
char op;
}Node, *pNode;
enum Operators {ADD, SUB, MUL, DIV, RSUB, RDIV};
typedef struct Game
{
int *figures;
pNode *node_list;
int success;
int n_solutions;
char **unique_expressions;
}Game, *pGame;
void Game_execute(Game *game);
void print_results(Game *game);
void init_list(Game *game);
int init_data(Game *game);
void destory_data(Game *game);
#endif /* GAME_H_ */
main.c
/*
* main.c
*
* Created on: 2011-9-27
* Author: brunie
*/
#include "twenty_four.h"
int main()
{
setbuf(stdout,0);
int status;
status = play_game();
if (status)
printf("Successful!\n");
else
printf("Not exist!\n");
return 0;
}
stack.c
/*
* stack.c
*
* Created on: 2011-10-5
* Author: brunie
*/
#include "stack.h"
int init_stack(istack *stack)
{
stack->base = (pNode *)malloc(STACK_INIT_SIZE * sizeof(pNode));
if (!stack->base)
exit (-1);
stack->top = stack->base;
stack->stack_size = STACK_INIT_SIZE;
return 1;
}
void destory_stack(istack *stack)
{
if(!stack->base)
free(stack->base);
stack->base = 0;
}
int stack_empty(istack *stack)
{
if (stack->top == stack->base)
return TRUE;
else
return FALSE;
}
int stack_length(istack *stack)
{
return stack->top - stack->base;
}
int get_top(istack *stack, pNode *pnode)
{
if (stack->top == stack->base)
return 0;
*pnode = *(stack->top - 1);
return 1;
}
int push(istack *stack, pNode pnode)
{
if (stack->top - stack->base >= stack->stack_size)
{
stack->base = (pNode *) realloc(stack->base,
(stack->stack_size + STACK_INCREMENT) * sizeof(pNode));
if (!stack->base)
exit(-1);
stack->top = stack->base + stack->stack_size;
stack->stack_size += STACK_INCREMENT;
}
*stack->top++ = pnode;
return 1;
}
int pop(istack *stack, pNode *pnode)
{
if (stack->top == stack->base)
return 0;
*pnode = * --stack->top;
return 1;
}
stack.h
/*
* stack.h
*
* Created on: 2011-10-5
* Author: brunie
*/
#ifndef STACK_H_
#define STACK_H_
#include "game.h"
#define STACK_INIT_SIZE 50
#define STACK_INCREMENT 10
typedef struct
{
pNode *base;
pNode *top;
int stack_size;
}istack;
int init_stack(istack *stack);
void destory_stack(istack *stack);
int stack_empty(istack *stack);
int stack_length(istack *stack);
int get_top(istack *stack, pNode *pnode);
int pop(istack *stack, pNode *pnode);
int push(istack *stack, pNode pnode);
#endif /* STACK_H_ */
twenty_four.c
/*
* twenty_four.c
*
* Created on: 2011-10-5
* Author: brunie
*/
#include "twenty_four.h"
void input(Game *game)
{
int digit;
int c;
int i;
while(1)
{
printf("Please input %d figures, each figure in the range of [%d,%d]:\n",N_FIGURES, MIN_INPUT, MAX_INPUT);
digit = 0;
i = 0;
while ((c = getchar()) == ' ');
do
{
if (c <= '9' && c >= '0')
digit = digit * 10 + c - '0';
else if (c == ' ')
{
if (digit > MAX_INPUT || digit < MIN_INPUT)
break;
game->figures[i++] = digit;
//printf("%d ",digit);
if (i == N_FIGURES)
break;
while((c = getchar()) == ' ');
if(c > '9' || c < '0')
break;
digit = c - '0';
}
else
{
if (c == '\n')
{
game->figures[i++] = digit;
//printf("%d ",digit);
}
break;
}
}while ((c = getchar()) != EOF);
if (c != '\n')
while ((c = getchar()) != '\n');
if (i == N_FIGURES)
break;
printf("Illegal input!\n");
}
}
int play_game()
{
int c;
int flag;
Game game;
init_data(&game);
do
{
input(&game);
init_list(&game);
Game_execute(&game);
print_results(&game);
printf("Do you want to play again(y/n):");
flag = getchar();
while ((c = getchar()) != '\n' && c != EOF)
;
} while (flag == 'y' || flag == 'Y');
destory_data(&game);
return game.success;
}
tweny_four.h
/*
* twenty_four.h
*
* Created on: 2011-10-5
* Author: brunie
*/
#ifndef TWENTY_FOUR_H_
#define TWENTY_FOUR_H_
#include "game.h"
void input(Game *game);
int play_game();
#endif /* TWENTY_FOUR_H_ */