「C-assign-2009-03-13」の編集履歴(バックアップ)一覧はこちら
「C-assign-2009-03-13」(2009/02/28 (土) 20:19:35) の最新版変更点
追加された行は緑色になります。
削除された行は赤色になります。
*問1
4つの4、4に対して様々な演算子を働かせて数を作る。
結果的にこれで済むことが判明した。どうせ最適化される。
#codehighlight(c){{
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <string.h>
#define LENGTH_OF_ARRAY(x) (sizeof(x)/sizeof((x)[0]))
#define PUT_ERROR(x) fprintf(stderr, (x))
#define ROUND(x) (floor((x) + 0.5))
#define IPOW0(x) 1
#define IPOW1(x) (x)
#define IPOW2(x) ((x)*(x))
#define IPOW3(x) ((x)*(x)*(x))
#define IPOW4(x) ((x)*(x)*(x)*(x))
#define IPOW5(x) ((x)*(x)*(x)*(x)*(x))
#define IPOW6(x) ((x)*(x)*(x)*(x)*(x)*(x))
#define IPOW7(x) ((x)*(x)*(x)*(x)*(x)*(x)*(x))
//#define IPOW7(x) ((x)*(x)*(x)*(x)*(x)*(x)*(x)*(x))
#define STACK_SIZE 64
#define STR_LENGTH 128
double factorial(double x);
int isBinOp(char c);
void d_init(void);
double calc(char *const str);
void s_init(void);
void s_push(char *const str);
char* s_pop();
void toInfix(char *const exp, char *const target);
int makeRPNExp(char *const exp);
void search(char result[][STR_LENGTH]);
const double ERROR_NUM = 1000000.0;
const char* ERROR_OVFLOW = "STACK overflow.\n";
const char* ERROR_NOBODY = "Nakani daremo imasen yo.\n";
const char* STR_NODATA = "Data Empty";
const int SEARCH_RANGE = 31; //114;
const char bin_op[] = "*/+-";
const char uni_op[] = "_sm!.n"; //除く
// m:minus, s:sqrt
// 4.4や4.44 can't be in Z
// .4~==4/9 so n:devide with 9
//const char* const EXP_TYPE[] = {
// "4 4 %c 4 %c 4 %c "
// ,"4 4 %c 4 4 %c %c "
// ,"4 4 4 %c %c 4 %c "
// ,"4 4 4 %c 4 %c %c "
// ,"4 4 4 4 %c %c %c "
//};
const char* const EXP_TYPE[] = {
"4 4 %c 4 %c 4 %c "
,"4 4 %c 4 4 %c %c "
,"4 4 4 %c %c 4 %c "
,"4 4 4 %c 4 %c %c "
,"4 4 4 4 %c %c %c "
};
int ipower(int x, int p)
{
int a=1;
for(; p; --p)
a *= x;
return a;
}
double factorial(double x)
{
int i, ix;
double result = 1.0;
ix = (int)ROUND(x);
for(i=1; i<=ix; ++i)
result *= i;
return result;
}
int isBinOp(char c)
{
char const *ptr;
for(ptr = bin_op; *ptr; ++ptr)
if(*ptr==c)
return 1;
return 0;
}
//this should be template
typedef struct DOUBLE_STACK{
double stack[STACK_SIZE];
unsigned int index;
} d_stack;
d_stack ds;
#define D_INIT ds.index = 0
void d_push(double x)
{
/*if(ds.index < STACK_SIZE)*/
ds.stack[(ds.index)++] = x;
/*else
PUT_ERROR(ERROR_OVFLOW);*/
}
//#define d_push(x) (ds.stack[(ds.index)++] = (x))
//#define D_POP ((ds.index) ? ds.stack[--(ds.index)] : (PUT_ERROR(ERROR_NOBODY),ERROR_NUM))
double d_pop(void)
{
return (ds.stack[--(ds.index)]);
}
double calc(char *const str)
{
char *c;
double op;
D_INIT;
for(c = str; *c; ++c)
{
if(isdigit(*c))
d_push((double)(*c-'0'));
else{
op = d_pop();
switch(*c)
{
case '+':
d_push(d_pop() + op);
break;
case '-':
d_push(d_pop() - op);
break;
case '*':
d_push(d_pop() * op);
break;
case '/':
if(op == 0.0)
return ERROR_NUM;
d_push(d_pop() / op);
break;
case 'm':
d_push(-op);
break;
case 's':
if(op==4.0)
d_push(2.0);
else if(op > 0.0)
d_push(sqrt(op));
else
return ERROR_NUM;
break;
case '!':
if(op==4.0)
d_push(24.0);
else if(op>0.0 && ROUND(op) == op)
d_push(factorial(op));
else
return ERROR_NUM;
break;
case 'n':
if((int)ROUND(op) == op && op==4)
d_push(op/9.0);
else
return ERROR_NUM;
break;
case '.':
if((int)ROUND(op) == 4)
d_push(op/10.0);
else
return ERROR_NUM;
break;
default:
d_push(op);
break;
}
}
}
return d_pop();
}
typedef struct STR_STACK{
char stack[STACK_SIZE][STR_LENGTH];
unsigned int index;
} s_stack;
s_stack ss;
void s_init(void)
{
ss.index = 0;
}
void s_push(char *const str)
{
if(ss.index < STACK_SIZE)
sprintf(ss.stack[(ss.index)++], "%s", str);
else
PUT_ERROR(ERROR_OVFLOW);
}
char* s_pop()
{
return (ss.index)
? ss.stack[--(ss.index)] : (PUT_ERROR(ERROR_NOBODY), (char *)NULL);
}
void toInfix(char *const exp, char *const target)
{
char temp[STR_LENGTH];
char *c; // pointer for char[] exp
s_init();
for(c = exp; *c; ++c)
{
if(isdigit(*c))
sprintf(temp, "%c", *c);
else if(isBinOp(*c))
sprintf(temp, "(%s %c %s)", s_pop(), *c, s_pop());
else if(*c == '.')
sprintf(temp, "%c%s", *c, s_pop());
else if(*c == 'm')
sprintf(temp, "-%s", s_pop());
else if(*c == 's')
sprintf(temp, "sqrt(%s)", s_pop());
else if(*c == '!')
sprintf(temp, "%s%c", s_pop(), *c);
else if(*c == 'n')
sprintf(temp, ".%s~", s_pop());
else
strcpy(temp, s_pop());
s_push(temp);
}
strcpy(target, temp);
}
int makeRPNExp(char *const exp)
{
#define LNB (LENGTH_OF_ARRAY(bin_op)-1)
static int idx_bin, idx_uni, idx_exp; // init with zero
const static int ln_b = LNB;
const static int ln_max = (LNB)*(LNB)*(LNB) - 1;
#undef LNB
#define LNU (LENGTH_OF_ARRAY(uni_op)-1)
//there are 3 bin-ops in exp is the reason why LNB is powered with 3
//int i;
//const static int ln_exp = strlen(EXP_TYPE[0])/2;
if(idx_exp==LENGTH_OF_ARRAY(EXP_TYPE))
++idx_uni, idx_exp = 0;
if(idx_uni==IPOW7(LNU) - 1)
++idx_bin, idx_uni = 0;
//二項演算子の代入
sprintf(exp, EXP_TYPE[idx_exp] ,
bin_op[idx_bin%ln_b],
bin_op[(idx_bin / ln_b) % ln_b],
bin_op[(idx_bin / ln_b / ln_b) % ln_b]);
//単項演算子の挿入
#define INPUT_SINGLE(x) (exp[(x)*2+1] = uni_op[(idx_bin / IPOW##x(LNU)) % LNU])
INPUT_SINGLE(0);
INPUT_SINGLE(1);
INPUT_SINGLE(2);
INPUT_SINGLE(3);
INPUT_SINGLE(4);
INPUT_SINGLE(5);
INPUT_SINGLE(6);
#undef INPUT_SINGLE
++idx_exp;
return (idx_bin == ln_max && idx_uni==IPOW7(LNU) - 1 && idx_exp==LENGTH_OF_ARRAY(EXP_TYPE)) ?
0 : 1;
#undef LNU
}
void search(char result[][STR_LENGTH])
{
char rpn_exp[STR_LENGTH]; // Reverse Polish Notation Expression
char inf_exp[STR_LENGTH]; // Infix notation Expression
double answer;
int i_answer;
int fill_counter=SEARCH_RANGE;
while(makeRPNExp(rpn_exp) && fill_counter)
{
answer = calc(rpn_exp);
i_answer = (int)ROUND(answer);
if(answer == i_answer
&& 0 <= i_answer
&& i_answer < SEARCH_RANGE
&& result[i_answer][0] == STR_NODATA[0]
){
toInfix(rpn_exp, inf_exp);
strcpy(result[i_answer], inf_exp);
--fill_counter;
printf("%d:%s,%s\n", i_answer, rpn_exp, inf_exp);
}
}
}
void test(char *a)
{
char b[256];
double x;
x = calc(a);
toInfix(a, b);
printf("RPN:%s\n"
"INF:%s\n"
"RESULT:%f\n",
a, b, x);
}
int main(int argc, char* argv[])
{
#if 0
test("44*4+");
test("44+4/");
test("11-4+");
test("44/4*");
test("4!");
test("4m");
test("4ms");
test("4s");
test("4.");
test("4n");
printf("4! = %f", factorial(4.0));
#endif
#if 0
test("4!4_4s4_-_*_/_");
test("4s4!4!/_-_4_-_");
test("4_4!4s*_-_4_/_");
test("4!4s4_-_4_/_*_");
test("4!4s-m4_4_/_+_");
test("4s4_4!4_/_*_-_");
test("4!4s4s4_-_/_/_");
#endif
#if 1
char result[SEARCH_RANGE][STR_LENGTH];
int i;
for(i=0; i<SEARCH_RANGE; ++i)
strcpy(result[i], STR_NODATA);
search(result);
for(i=0; i<SEARCH_RANGE; ++i)
printf("%2d : %s\n",i, result[i]);
#endif
return 0;
}
}}
*問1
4つの4、4に対して様々な演算子を働かせて数を作る。
計算を手抜きした版を上に、実直な版を下に添える。
#codehighlight(c){{
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <string.h>
#define LENGTH_OF_ARRAY(x) (sizeof(x)/sizeof((x)[0]))
#define PUT_ERROR(x) fprintf(stderr, (x))
#define ROUND(x) (floor((x) + 0.5))
#define IPOW0(x) 1
#define IPOW1(x) (x)
#define IPOW2(x) ((x)*(x))
#define IPOW3(x) ((x)*(x)*(x))
#define IPOW4(x) ((x)*(x)*(x)*(x))
#define IPOW5(x) ((x)*(x)*(x)*(x)*(x))
#define IPOW6(x) ((x)*(x)*(x)*(x)*(x)*(x))
#define IPOW7(x) ((x)*(x)*(x)*(x)*(x)*(x)*(x))
//#define IPOW7(x) ((x)*(x)*(x)*(x)*(x)*(x)*(x)*(x))
#define STACK_SIZE 64
#define STR_LENGTH 128
double factorial(double x);
int isBinOp(char c);
void d_init(void);
double calc(char *const str);
void s_init(void);
void s_push(char *const str);
char* s_pop();
void toInfix(char *const exp, char *const target);
int makeRPNExp(char *const exp);
void search(char result[][STR_LENGTH]);
const double ERROR_NUM = 1000000.0;
const char* ERROR_OVFLOW = "STACK overflow.\n";
const char* ERROR_NOBODY = "Nakani daremo imasen yo.\n";
const char* STR_NODATA = "Data Empty";
const int SEARCH_RANGE = 114;
const char numbers[] = "4SM?.N";
const char bin_op[] = "*/+-";
const char uni_op[] = "_s"; // m!除く
// m:minus, s:sqrt
// 4.4や4.44 can't be in Z
// .4~==4/9 so n:devide with 9
struct EXP_BASE
{
int bin_position[3];
int num_position[4];
int uni_position[2];
};
const char * EXP_BASE_STRING[] ={
"44$@4$@4$",
"444$@$@4$",
"444$@4$@$",
"4444$@$@$",
"44$@44$@$",
};
struct EXP_BASE exp_base[LENGTH_OF_ARRAY(EXP_BASE_STRING)];
void exp_base_init(const char *pstr[], int length, struct EXP_BASE *target)
{
int i, j;
int c_n, c_u, c_b;
const char *c;
for(i = 0; i < length; ++i)
{
for(c = pstr[i], j = c_n = c_u = c_b = 0; c[j]; ++j)
{
switch(c[j])
{
case '4':
target[i].num_position[c_n++] = j;
break;
case '@':
target[i].uni_position[c_u++] = j;
break;
case '$':
target[i].bin_position[c_b++] = j;
break;
default:
break;
}
}
}
}
double factorial(double x)
{
int i, ix;
double result = 1.0;
ix = (int)ROUND(x);
for(i=1; i<=ix; ++i)
result *= i;
return result;
}
int isBinOp(char c)
{
char const *ptr;
for(ptr = bin_op; *ptr; ++ptr)
if(*ptr==c)
return 1;
return 0;
}
//this should be template
typedef struct DOUBLE_STACK{
double stack[STACK_SIZE];
unsigned int index;
} d_stack;
d_stack ds;
#define D_INIT ds.index = 0
void d_push(double x)
{
/*if(ds.index < STACK_SIZE)*/
ds.stack[(ds.index)++] = x;
/*else
PUT_ERROR(ERROR_OVFLOW);*/
}
//#define d_push(x) (ds.stack[(ds.index)++] = (x))
//#define D_POP ((ds.index) ? ds.stack[--(ds.index)] : (PUT_ERROR(ERROR_NOBODY),ERROR_NUM))
double d_pop(void)
{
return (ds.stack[--(ds.index)]);
}
double calc(char *const str)
{
char *c;
double op;
D_INIT;
for(c = str; *c; ++c)
{
if(isdigit(*c))
d_push(4.0);
else{
switch(*c)
{
case 'M':
d_push(-4.0); /*dump*/
break;
case 'S':
d_push(2.0); /*dump*/
break;
case '?':
d_push(24.0); /*dump*/
break;
case 'N':
d_push(4.0/9.0);
break;
case '.':
d_push(0.4);
break;
case 'm':
d_push(-d_pop());
break;
case 's':
op = d_pop();
if( op < 0.0)
return ERROR_NUM;
else
d_push(sqrt(op));
break;
case '!':
op = d_pop();
if(op != ROUND(op) || op < 0.0)
return ERROR_NUM;
else
d_push(factorial(op));
break;
case '+':
d_push(d_pop() + d_pop());
break;
case '-':
op = d_pop();
d_push(d_pop() - op);
break;
case '*':
d_push(d_pop() * d_pop());
break;
case '/':
op = d_pop();
if(op == 0.0)
return ERROR_NUM;
d_push(d_pop() / op);
break;
default:
break;
}
}
}
return d_pop();
}
typedef struct STR_STACK{
char stack[STACK_SIZE][STR_LENGTH];
unsigned int index;
} s_stack;
s_stack ss;
void s_init(void)
{
ss.index = 0;
}
void s_push(char *const str)
{
if(ss.index < STACK_SIZE)
sprintf(ss.stack[(ss.index)++], "%s", str);
else
PUT_ERROR(ERROR_OVFLOW);
}
char* s_pop()
{
return (ss.index)
? ss.stack[--(ss.index)] : (PUT_ERROR(ERROR_NOBODY), (char *)NULL);
}
void toInfix(char *const exp, char *const target)
{
char temp[STR_LENGTH];
char *c; // pointer for char[] exp
s_init();
for(c = exp; *c; ++c)
{
if(isdigit(*c))
sprintf(temp, "%c", *c);
else
{
switch(*c)
{
case '.':
sprintf(temp, ".4");
break;
case 'N':
sprintf(temp, ".4~");
break;
case 'M':
sprintf(temp, "-4");
break;
case 'S':
sprintf(temp, "sqrt(4)");
break;
case '?':
sprintf(temp, "4!");
break;
case 'm':
sprintf(temp, "-(%s)", s_pop());
break;
case 's':
sprintf(temp, "sqrt(%s)", s_pop());
break;
case '!':
sprintf(temp, "(%s)%c", s_pop(), *c);
break;
default:
if(isBinOp(*c))
sprintf(temp, "(%s %c %s)", s_pop(), *c, s_pop());
else
strcpy(temp, s_pop());
break;
}
}
s_push(temp);
}
strcpy(target, temp);
}
int makeRPNExp(char *const exp)
{
#define LNB (LENGTH_OF_ARRAY(bin_op)-1)
static int idx_bin, idx_num, idx_exp; // init with zero
static int idx_uni;
const static int ln_b = LNB;
const static int ln_max = IPOW3(LNB) - 1;
//there are 3 bin-ops in exp is the reason why LNB is powered with 3
#undef LNB
#define LNU (LENGTH_OF_ARRAY(uni_op) - 1)
#define LNN (LENGTH_OF_ARRAY(numbers) - 1)
if(idx_exp==LENGTH_OF_ARRAY(exp_base))
++idx_num, idx_exp = 0;
if(idx_num==IPOW4(LNN) - 1)
++idx_uni, idx_num = 0;
if(idx_uni==IPOW2(LNU) - 1)
++idx_bin, idx_uni = 0;
//二項演算子の代入
strcpy(exp, EXP_BASE_STRING[0]);
//どうせ全ての項目を後で代入してしまうので、領域が確保されている以上strcpyが無駄。
//と思いきや\0の問題が…仕方ないのできまりきった文字列をコピペすることに
//つまり、EXP_BASE::stringはお飾り
#define INPUT_BINARY(x) exp[exp_base[idx_exp].bin_position[x]] = bin_op[(idx_bin / IPOW##x(ln_b)) % ln_b]
INPUT_BINARY(0);
INPUT_BINARY(1);
INPUT_BINARY(2);
#undef INPUT_BINARY
//数字オブジェクトの挿入
#define INPUT_NUM(x) exp[exp_base[idx_exp].num_position[x]] = numbers[(idx_num / IPOW##x(LNN)) % LNN]
INPUT_NUM(0);
INPUT_NUM(1);
INPUT_NUM(2);
INPUT_NUM(3);
#undef INPUT_NUM
//単項演算子の代入
#define INPUT_SINGLE(x) exp[exp_base[idx_exp].uni_position[x]] = uni_op[(idx_uni / IPOW##x(LNU)) % LNU]
//#define INPUT_SINGLE(x) exp[exp_base[idx_exp].uni_position[x]] = '_'
INPUT_SINGLE(0);
INPUT_SINGLE(1);
#undef INPUT_SINGLE
++idx_exp;
return (idx_bin == ln_max
&& idx_num == IPOW4(LNN) - 1
&& idx_uni == IPOW2(LNU) - 1
&& idx_exp==LENGTH_OF_ARRAY(exp_base)) ?
0 : 1;
#undef LNU
#undef LNN
}
void search(char result[][STR_LENGTH])
{
char rpn_exp[STR_LENGTH]; // Reverse Polish Notation Expression
char inf_exp[STR_LENGTH]; // Infix notation Expression
double answer;
int i_answer;
int fill_counter=SEARCH_RANGE;
while(makeRPNExp(rpn_exp) && fill_counter)
{
answer = calc(rpn_exp);
i_answer = (int)ROUND(answer);
if(answer == i_answer
&& 0 <= i_answer
&& i_answer < SEARCH_RANGE
&& result[i_answer][0] == STR_NODATA[0]
){
toInfix(rpn_exp, inf_exp);
strcpy(result[i_answer], inf_exp);
--fill_counter;
printf("%d:%s,%s\n", i_answer, rpn_exp, inf_exp);
}
}
}
void test(char *a)
{
char b[256];
double x;
x = calc(a);
toInfix(a, b);
printf("RPN:%s\n"
"INF:%s\n"
"RESULT:%f\n",
a, b, x);
}
int main(int argc, char* argv[])
{
exp_base_init(EXP_BASE_STRING, LENGTH_OF_ARRAY(EXP_BASE_STRING), exp_base);
#if 0
test("44*4+");
test("44+4/");
test("11-4+");
test("44/4*");
test("4!");
test("4m");
test("4ms");
test("4s");
test("4.");
test("4n");
printf("4! = %f", factorial(4.0));
#endif
#if 0
test("4!4_4s4_-_*_/_");
test("4s4!4!/_-_4_-_");
test("4_4!4s*_-_4_/_");
test("4!4s4_-_4_/_*_");
test("4!4s-m4_4_/_+_");
test("4s4_4!4_/_*_-_");
test("4!4s4s4_-_/_/_");
#endif
#if 1
char result[SEARCH_RANGE][STR_LENGTH];
int i;
for(i=0; i<SEARCH_RANGE; ++i)
strcpy(result[i], STR_NODATA);
search(result);
for(i=0; i<SEARCH_RANGE; ++i)
printf("%2d : %s\n",i, result[i]);
#endif
return 0;
}
}}
#codehighlight(c){{
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <string.h>
#define LENGTH_OF_ARRAY(x) (sizeof(x)/sizeof((x)[0]))
#define PUT_ERROR(x) fprintf(stderr, (x))
#define ROUND(x) (floor((x) + 0.5))
#define IPOW0(x) 1
#define IPOW1(x) (x)
#define IPOW2(x) ((x)*(x))
#define IPOW3(x) ((x)*(x)*(x))
#define IPOW4(x) ((x)*(x)*(x)*(x))
#define IPOW5(x) ((x)*(x)*(x)*(x)*(x))
#define IPOW6(x) ((x)*(x)*(x)*(x)*(x)*(x))
#define IPOW7(x) ((x)*(x)*(x)*(x)*(x)*(x)*(x))
//#define IPOW7(x) ((x)*(x)*(x)*(x)*(x)*(x)*(x)*(x))
#define STACK_SIZE 64
#define STR_LENGTH 128
double factorial(double x);
int isBinOp(char c);
void d_init(void);
double calc(char *const str);
void s_init(void);
void s_push(char *const str);
char* s_pop();
void toInfix(char *const exp, char *const target);
int makeRPNExp(char *const exp);
void search(char result[][STR_LENGTH]);
const double ERROR_NUM = 1000000.0;
const char* ERROR_OVFLOW = "STACK overflow.\n";
const char* ERROR_NOBODY = "Nakani daremo imasen yo.\n";
const char* STR_NODATA = "Data Empty";
const int SEARCH_RANGE = 31; //114;
const char bin_op[] = "*/+-";
const char uni_op[] = "_sm!.n"; //除く
// m:minus, s:sqrt
// 4.4や4.44 can't be in Z
// .4~==4/9 so n:devide with 9
//const char* const EXP_TYPE[] = {
// "4 4 %c 4 %c 4 %c "
// ,"4 4 %c 4 4 %c %c "
// ,"4 4 4 %c %c 4 %c "
// ,"4 4 4 %c 4 %c %c "
// ,"4 4 4 4 %c %c %c "
//};
const char* const EXP_TYPE[] = {
"4 4 %c 4 %c 4 %c "
,"4 4 %c 4 4 %c %c "
,"4 4 4 %c %c 4 %c "
,"4 4 4 %c 4 %c %c "
,"4 4 4 4 %c %c %c "
};
int ipower(int x, int p)
{
int a=1;
for(; p; --p)
a *= x;
return a;
}
double factorial(double x)
{
int i, ix;
double result = 1.0;
ix = (int)ROUND(x);
for(i=1; i<=ix; ++i)
result *= i;
return result;
}
int isBinOp(char c)
{
char const *ptr;
for(ptr = bin_op; *ptr; ++ptr)
if(*ptr==c)
return 1;
return 0;
}
//this should be template
typedef struct DOUBLE_STACK{
double stack[STACK_SIZE];
unsigned int index;
} d_stack;
d_stack ds;
#define D_INIT ds.index = 0
void d_push(double x)
{
/*if(ds.index < STACK_SIZE)*/
ds.stack[(ds.index)++] = x;
/*else
PUT_ERROR(ERROR_OVFLOW);*/
}
//#define d_push(x) (ds.stack[(ds.index)++] = (x))
//#define D_POP ((ds.index) ? ds.stack[--(ds.index)] : (PUT_ERROR(ERROR_NOBODY),ERROR_NUM))
double d_pop(void)
{
return (ds.stack[--(ds.index)]);
}
double calc(char *const str)
{
char *c;
double op;
D_INIT;
for(c = str; *c; ++c)
{
if(isdigit(*c))
d_push((double)(*c-'0'));
else{
op = d_pop();
switch(*c)
{
case '+':
d_push(d_pop() + op);
break;
case '-':
d_push(d_pop() - op);
break;
case '*':
d_push(d_pop() * op);
break;
case '/':
if(op == 0.0)
return ERROR_NUM;
d_push(d_pop() / op);
break;
case 'm':
d_push(-op);
break;
case 's':
if(op==4.0)
d_push(2.0);
else if(op > 0.0)
d_push(sqrt(op));
else
return ERROR_NUM;
break;
case '!':
if(op==4.0)
d_push(24.0);
else if(op>0.0 && ROUND(op) == op)
d_push(factorial(op));
else
return ERROR_NUM;
break;
case 'n':
if((int)ROUND(op) == op && op==4)
d_push(op/9.0);
else
return ERROR_NUM;
break;
case '.':
if((int)ROUND(op) == 4)
d_push(op/10.0);
else
return ERROR_NUM;
break;
default:
d_push(op);
break;
}
}
}
return d_pop();
}
typedef struct STR_STACK{
char stack[STACK_SIZE][STR_LENGTH];
unsigned int index;
} s_stack;
s_stack ss;
void s_init(void)
{
ss.index = 0;
}
void s_push(char *const str)
{
if(ss.index < STACK_SIZE)
sprintf(ss.stack[(ss.index)++], "%s", str);
else
PUT_ERROR(ERROR_OVFLOW);
}
char* s_pop()
{
return (ss.index)
? ss.stack[--(ss.index)] : (PUT_ERROR(ERROR_NOBODY), (char *)NULL);
}
void toInfix(char *const exp, char *const target)
{
char temp[STR_LENGTH];
char *c; // pointer for char[] exp
s_init();
for(c = exp; *c; ++c)
{
if(isdigit(*c))
sprintf(temp, "%c", *c);
else if(isBinOp(*c))
sprintf(temp, "(%s %c %s)", s_pop(), *c, s_pop());
else if(*c == '.')
sprintf(temp, "%c%s", *c, s_pop());
else if(*c == 'm')
sprintf(temp, "-%s", s_pop());
else if(*c == 's')
sprintf(temp, "sqrt(%s)", s_pop());
else if(*c == '!')
sprintf(temp, "%s%c", s_pop(), *c);
else if(*c == 'n')
sprintf(temp, ".%s~", s_pop());
else
strcpy(temp, s_pop());
s_push(temp);
}
strcpy(target, temp);
}
int makeRPNExp(char *const exp)
{
#define LNB (LENGTH_OF_ARRAY(bin_op)-1)
static int idx_bin, idx_uni, idx_exp; // init with zero
const static int ln_b = LNB;
const static int ln_max = (LNB)*(LNB)*(LNB) - 1;
#undef LNB
#define LNU (LENGTH_OF_ARRAY(uni_op)-1)
//there are 3 bin-ops in exp is the reason why LNB is powered with 3
//int i;
//const static int ln_exp = strlen(EXP_TYPE[0])/2;
if(idx_exp==LENGTH_OF_ARRAY(EXP_TYPE))
++idx_uni, idx_exp = 0;
if(idx_uni==IPOW7(LNU) - 1)
++idx_bin, idx_uni = 0;
//二項演算子の代入
sprintf(exp, EXP_TYPE[idx_exp] ,
bin_op[idx_bin%ln_b],
bin_op[(idx_bin / ln_b) % ln_b],
bin_op[(idx_bin / ln_b / ln_b) % ln_b]);
//単項演算子の挿入
#define INPUT_SINGLE(x) (exp[(x)*2+1] = uni_op[(idx_bin / IPOW##x(LNU)) % LNU])
INPUT_SINGLE(0);
INPUT_SINGLE(1);
INPUT_SINGLE(2);
INPUT_SINGLE(3);
INPUT_SINGLE(4);
INPUT_SINGLE(5);
INPUT_SINGLE(6);
#undef INPUT_SINGLE
++idx_exp;
return (idx_bin == ln_max && idx_uni==IPOW7(LNU) - 1 && idx_exp==LENGTH_OF_ARRAY(EXP_TYPE)) ?
0 : 1;
#undef LNU
}
void search(char result[][STR_LENGTH])
{
char rpn_exp[STR_LENGTH]; // Reverse Polish Notation Expression
char inf_exp[STR_LENGTH]; // Infix notation Expression
double answer;
int i_answer;
int fill_counter=SEARCH_RANGE;
while(makeRPNExp(rpn_exp) && fill_counter)
{
answer = calc(rpn_exp);
i_answer = (int)ROUND(answer);
if(answer == i_answer
&& 0 <= i_answer
&& i_answer < SEARCH_RANGE
&& result[i_answer][0] == STR_NODATA[0]
){
toInfix(rpn_exp, inf_exp);
strcpy(result[i_answer], inf_exp);
--fill_counter;
printf("%d:%s,%s\n", i_answer, rpn_exp, inf_exp);
}
}
}
void test(char *a)
{
char b[256];
double x;
x = calc(a);
toInfix(a, b);
printf("RPN:%s\n"
"INF:%s\n"
"RESULT:%f\n",
a, b, x);
}
int main(int argc, char* argv[])
{
#if 0
test("44*4+");
test("44+4/");
test("11-4+");
test("44/4*");
test("4!");
test("4m");
test("4ms");
test("4s");
test("4.");
test("4n");
printf("4! = %f", factorial(4.0));
#endif
#if 0
test("4!4_4s4_-_*_/_");
test("4s4!4!/_-_4_-_");
test("4_4!4s*_-_4_/_");
test("4!4s4_-_4_/_*_");
test("4!4s-m4_4_/_+_");
test("4s4_4!4_/_*_-_");
test("4!4s4s4_-_/_/_");
#endif
#if 1
char result[SEARCH_RANGE][STR_LENGTH];
int i;
for(i=0; i<SEARCH_RANGE; ++i)
strcpy(result[i], STR_NODATA);
search(result);
for(i=0; i<SEARCH_RANGE; ++i)
printf("%2d : %s\n",i, result[i]);
#endif
return 0;
}
}}
表示オプション
横に並べて表示:
変化行の前後のみ表示: