トップ 差分 一覧 Farm ソース 検索 ヘルプ PDF RSS ログイン

2003ae1.c

// Probrem E

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>

#define MAXSTR 100
#define ATOM_NO (26+26*26)
#define TRUE  1
#define FALSE 0

#define NUM(x) (x-'0')
#define alp(x) (x-'a')
#define ALP(x) (x-'A')

void push(int w);
int pop(void);

int sp=0;	 // スタックポインタ
int st[100]; // スタック
void space(int n);

int main(int argc, char *argv[])
{
	FILE *fp;
	int a,i,j,k,n,w,z;
	char buf[MAXSTR], form[MAXSTR];
	int atom[ATOM_NO];
	int count, flag;
	
//	printf("%d\n", 26+26*26);
	push(1);
	a=pop();
	printf("%d\n", a);
	
	if(argc != 2){
		fprintf(stderr, "Usage: program input-file\n");
		exit(-1);
	}
	
	if((fp=fopen(argv[1],"r")) == NULL){
		fprintf(stderr, "can't open %s\n", argv[1]);
		exit(-1);
	}
	
	for(i=0; i<ATOM_NO; i++){
		atom[i]=0;
	}
	
	while(1){
		fgets(buf, MAXSTR, fp);
		sscanf(buf, "%s %d", form, &w);
		if(!strcmp(form, "END_OF_FIRST_PART")) break;
		
		printf("%s =%d\n", form, w);
//		printf("%s =%d (len=%d)\n", form, w, strlen(form));
		
//		count=0;
		if(strlen(form)==1){
//			atom[form[0]-'A']=w;
			atom[ALP(form[0])]=w;
			printf("%d = %d\n", ALP(form[0]), w);
//			count++;
		}else{
//			atom[(form[0]-'A')*26+(form[1]-'a')]=w;
			atom[ALP(form[0])*26+alp(form[1])]=w;
//			printf("%d = %d\n", ALP(form[0])*26+alp(form[1]), w);
//			count++;
		}
	}
	
//	for(i=0; i<ATOM_NO; i++){
//		if(atom[i]){
//			printf("%d = %d\n", i, atom[i]);
//		}
//		printf("%d ", atom[i]);
//	}
	printf("\n");
	
	while(1){
		fgets(buf, MAXSTR, fp);
		sscanf(buf, "%s", form);
		if(!strcmp(form, "0")) break;
		
		// 文字列を超えて操作する危険を避けるために文字列の後ろを全部ヌルにしておく
		for(i=strlen(form); i<MAXSTR; i++){
			form[i]='\0';
		}
		printf("%s\n", form);
		
		i=0;
		
		flag=TRUE;
		w=0;
		while(i<strlen(form)){
			char now=form[i];
			char next=form[i+1];
			char next2=form[i+2];
			char next3=form[i+3];
			
			if(!isupper(now)){ 	// 大文字以外だったら
				if(now=='('){	// 左カッコだったら
					space(sp); puts("--push--");
					push(w);		// スタックに積む
					w=0;			// 新たに重さを計算する
					i++;
					continue;
				}else if(now==')'){ // 右カッコだったら
					int tmp=pop();		// スタックから取り出す
					space(sp); puts("--pop--");
					if(!isdigit(next)){ // 次の文字が数字じゃなかったら
						printf("(%d)\n", tmp);
						w+=tmp;				// 取り出したものを重さに加える
						i++;
						continue;
					}else{ // 次の文字が数字だったら
						if(isdigit(next2)){ // その次も数字だったら
							space(sp);
							printf("(%d) x %d = %d\n", w, NUM(next)*10+NUM(next2), w*(NUM(next)*10+NUM(next2)));
							w*=(NUM(next)*10+NUM(next2));
							w+=tmp;
							i+=3;
							continue;
						}else{ // その次が数字じゃなかったら
							space(sp);
							printf("(%d) x %d = %d\n", w, NUM(next), w*NUM(next));
							w*=NUM(next);
							w+=tmp;
							i+=2;
							continue;
						}
					}
				}else{
					printf("*** %c\n", now);
					i++;
				}
			}else{ // 大文字の時
				if(islower(next)){ // 2文字目が小文字だったら
					a=atom[ALP(now)*26+alp(next)];
//					printf("%c%c = %d\n", now, next, a);
					if(!a){
						space(sp);
						puts("2:dame");
						flag=FALSE; break; // 重さが無いとき
					}
					if(!isdigit(next2)){ // 3文字目が数字じゃないとき時
						space(sp);
						printf("%c%c = %d\n", now, next, a);
						w+=a;
						i+=2;
						continue;
					}else{ // 3文字目が数字の時
						if(isdigit(next3)){ // 4文字目も数字の時
							space(sp);
							printf("%c%c x %d = %d\n", now,next,NUM(next2)*10+NUM(next3),a*(NUM(next2)*10+NUM(next3)));
							w+=a*(NUM(next2)*10+NUM(next3));
							i+=4;
							continue;
						}else{
							space(sp);
							printf("%c%c x %d = %d\n", now, next, NUM(next2), a*NUM(next2));
							w+=a*NUM(next2);
							i+=3;
							continue;
						}
					}
				}else{ // 2文字目が小文字じゃない時
					a=atom[ALP(now)];
//					printf("%c = %d\n", now, a);
					if(!a){
						space(sp);
						puts("1:dame");
						flag=FALSE; break; // 重さが無いとき、おしまい
					}
					if(!isdigit(next)){ // 2文字目が数字じゃない時
						space(sp);
						printf("%c = %d\n", now, a);
						w+=a;
						i++;
						continue;
					}else{ // 2文字目が数字の時
						if(isdigit(next2)){ // 3文字目も数字の時
							space(sp);
							printf("%c x %d = %d\n", now, NUM(next)*10+NUM(next2), a*(NUM(next)*10+NUM(next2)));
							w+=a*(NUM(next)*10+NUM(next2));
							i+=3;
							continue;
						}else{ // 3文字目が数字じゃない時
							space(sp);
							printf("%c x %d = %d\n", now, NUM(next), a*NUM(next));
							w+=a*NUM(next);
							i+=2;
							continue;
						}
					}
				}
			}
		}
		if(flag){
			printf("OK %d\n", w);
		}else{
			printf("UNKNOWN\n");
		}
		printf("\n");
	}
	
	fclose(fp);
	
	return(0);
}

void space(int n)
{
	int i;
	
	for(i=0; i<n; i++){
		printf(" ");
	}
}

void push(int w) // 引数をスタックに積む
{
	st[sp++]=w;
}

int pop(void) // スタックから取り出す
{
	return(st[--sp]);
}