Skip to content

Instantly share code, notes, and snippets.

@shouya
Created February 18, 2012 19:18
Show Gist options
  • Save shouya/1860706 to your computer and use it in GitHub Desktop.
Save shouya/1860706 to your computer and use it in GitHub Desktop.
24-point implement using rpn way
#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