Created
February 18, 2012 19:18
-
-
Save shouya/1860706 to your computer and use it in GitHub Desktop.
24-point implement using rpn way
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> /* for printf */ | |
/* constants declaration */ | |
#define TOTAL 24.f | |
#define PRECISION 0.001f /* for float number comparison */ | |
#define MAX_POINT 13 | |
#define MIN_POINT 1 | |
#define NUM_CARDS 4 | |
/* stack operation */ | |
float _stack[NUM_CARDS]; | |
int _top = 0; | |
#define push(num) (_stack[_top++] = (num)) | |
#define pop() (_stack[--_top]) | |
#define top() (_stack[_top - 1]) | |
#define clear() (_top = 0) | |
/* procedure declaration */ | |
typedef float op_type(float, float); | |
float op_plus(float, float); | |
float op_minus(float, float); | |
float op_multiply(float, float); | |
float op_divide(float, float); | |
const char *precedences[] = { | |
"nnonono", | |
"nnonnoo", | |
"nnnoono", | |
"nnnonoo", | |
"nnnnooo", | |
0 | |
}; | |
op_type *operators[] = { | |
&op_plus, | |
&op_minus, | |
&op_multiply, | |
&op_divide, | |
0 | |
}; | |
/* operators implement */ | |
float op_plus(float lhs, float rhs) | |
{ | |
return lhs + rhs; | |
} | |
float op_minus(float lhs, float rhs) | |
{ | |
return lhs - rhs; | |
} | |
float op_multiply(float lhs, float rhs) | |
{ | |
return lhs * rhs; | |
} | |
float op_divide(float lhs, float rhs) | |
{ | |
return lhs / rhs; | |
} | |
/* internal functions declaration */ | |
int test(const char *prec, op_type ***opr_buf, int *num_buf); | |
int cycle_precedence(const char ***pprec); | |
int cycle_operator(op_type ***popr); | |
int cycle_number(int *n); | |
void print(const char *prec, op_type ***opr, int *num, int n); | |
void procedure(void); | |
/* body */ | |
int test(const char *prec, op_type ***opr_buf, int *num_buf) | |
{ | |
const char *pprec = prec; | |
op_type ***popr = opr_buf; | |
int *pnum = num_buf; | |
clear(); | |
while (*pprec) { | |
if (*pprec == 'n') { | |
push((float)(*pnum++)); | |
} else if (*pprec == 'o') { | |
float o1, o2; | |
o1 = pop(); | |
o2 = pop(); | |
push((***popr++)(o1, o2)); | |
} else { | |
/* error */ | |
} | |
++pprec; | |
} | |
if (top() >= TOTAL - PRECISION && | |
top() <= TOTAL + PRECISION) | |
return 1; | |
return 0; | |
} | |
int cycle_precedence(const char ***pprec) | |
{ | |
if (*(*pprec + 1)) { | |
++(*pprec); | |
return 0; | |
} | |
*pprec = &precedences[0]; | |
return 1; | |
} | |
int _cycle_operator(op_type ***popr, int index) | |
{ | |
if (index < 0) | |
return 1; | |
if (*(popr[index]+1) != 0) { | |
++popr[index]; | |
return 0; | |
} | |
popr[index] = &operators[0]; | |
return _cycle_operator(popr, index - 1); | |
} | |
int cycle_operator(op_type ***popr) | |
{ | |
return _cycle_operator(popr, NUM_CARDS - 2); | |
} | |
int _cycle_number(int *n, int index) | |
{ | |
if (index < 0) | |
return 1; | |
if (n[index] < MAX_POINT) { | |
++(n[index]); | |
return 0; | |
} | |
n[index] = MIN_POINT; | |
return _cycle_number(n, index - 1); | |
} | |
int cycle_number(int *n) | |
{ | |
return _cycle_number(n, NUM_CARDS - 1); | |
} | |
char _opr_chr(op_type *opr) | |
{ | |
if (opr == &op_plus) | |
return '+'; | |
else if (opr == &op_minus) | |
return '-'; | |
else if (opr == &op_multiply) | |
return '*'; | |
else if (opr == &op_divide) | |
return '/'; | |
else | |
return '?'; | |
} | |
void print(const char *prec, op_type ***opr, int *num, int n) | |
{ | |
printf("%5d: (%d,%d,%d,%d) %s (%c,%c,%c)\n", | |
n, num[0], num[1], num[2], num[3], prec, | |
_opr_chr(*opr[0]), _opr_chr(*opr[1]), _opr_chr(*opr[2])); | |
} | |
void procedure(void) | |
{ | |
int num_buf[NUM_CARDS]; | |
op_type **opr_buf[NUM_CARDS - 1]; | |
const char **prec = &precedences[0]; | |
int counting = 0; | |
int i = 0; | |
while (i != NUM_CARDS) { | |
num_buf[i++] = MIN_POINT; | |
} | |
i = 0; | |
while (i != NUM_CARDS - 1) { | |
opr_buf[i++] = &operators[0]; | |
} | |
do { | |
do { | |
do { | |
if (test(*prec, opr_buf, num_buf)) | |
print(*prec, opr_buf, num_buf, ++counting); | |
} while (!cycle_precedence(&prec)); | |
} while (!cycle_operator(opr_buf)); | |
} while (!cycle_number(num_buf)); | |
} | |
int main(void) | |
{ | |
procedure(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment