Created
November 14, 2011 13:15
-
-
Save jrosskopf/1363927 to your computer and use it in GitHub Desktop.
07_soupsum
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 <math.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
//#define DEBUG | |
#define EOT 4 | |
#define TO_CHAR(_x) ((unsigned char)_x) | |
#define TO_NUMBER(_x) ((_x >= '0' && _x <= '9') ? (double)(_x - '0') : 0.0) | |
#define SIGNUM(_x) (signbit(_x) ? -1.0 : 1.0) | |
#define TOKEN_PM 0 | |
#define TOKEN_DOT 1 | |
#define TOKEN_DIGIT 2 | |
#define TOKEN_EXP 3 | |
#define TOKEN_EOT 5 | |
#define TOKEN_REST 4 | |
#define S0 0 | |
#define S1 1 | |
#define S2 2 | |
#define S3 3 | |
#define S4 4 | |
#define S5 5 | |
#define S6 6 | |
#define S7 7 | |
#define STATE_INITIAL S0 | |
#define STATE_TERMINAL 99 | |
int T[8][6] = { | |
{1, 3, 2, 0, 0, 99}, // S0 | |
{0, 3, 2, 0, 0, 99}, // S1 | |
{0, 4, 2, 5, 0, 99}, // S2 | |
{0, 0, 4, 0, 0, 99}, // S3 | |
{0, 0, 4, 5, 0, 99}, // S4 | |
{6, 0, 7, 0, 0, 99}, // S5 | |
{0, 0, 7, 0, 0, 99}, // S6 | |
{0, 0, 7, 0, 0, 99} // S7 | |
}; | |
int get_token_from_char(unsigned char ch) { | |
if (ch == '+' || ch == '-') | |
return TOKEN_PM; | |
if (ch == '.') | |
return TOKEN_DOT; | |
if (ch >= '0' && ch <= '9') | |
return TOKEN_DIGIT; | |
if (ch == 'e' || ch == 'E') | |
return TOKEN_EXP; | |
if (ch == EOT) | |
return TOKEN_EOT; | |
return TOKEN_REST; | |
} | |
double pow10floor(double x) { | |
return pow(10.0, floor(log10(x))); | |
} | |
int get_next_state(int state, unsigned char ch) { | |
int sym = get_token_from_char(ch); | |
if (state < 0 || state > 7) { | |
fprintf(stderr, "**Error** Invalid state %d at %c\n", state, ch); | |
exit(1); | |
} | |
if (sym < 0 || sym > 5) { | |
fprintf(stderr, "**Error** Invalid symbol %d at %c\n", sym, ch); | |
exit(1); | |
} | |
return T[state][sym]; | |
} | |
void handle_state_transition(double *curr, double *exp, unsigned char ch, int decimal, int next_state) { | |
if (next_state == S1) | |
*curr *= ch == '-' ? -1.0 : 1.0; | |
if (next_state == S2) | |
*curr = (*curr * 10) + SIGNUM(*curr) * TO_NUMBER(ch); | |
if (next_state == S4) | |
*curr += SIGNUM(*curr) * TO_NUMBER(ch) / pow(10.0, decimal); | |
if (next_state == S6) | |
*exp *= ch == '-' ? -1.0 : 1.0; | |
if (next_state == S7) | |
*exp = (*exp * 10) + SIGNUM(*exp) * TO_NUMBER(ch); | |
} | |
char translate_char(unsigned char ch) { | |
if (ch == '\n') | |
return ' '; | |
return ch; | |
} | |
int main(int argc, char **argv) { | |
double sum = 0.0, curr = 0.0, exp = 0.0; | |
int state = STATE_INITIAL, next_state = STATE_INITIAL; | |
int ch = 0; | |
for(int decimal = 0; (ch = getchar()) != EOF; decimal++) { | |
next_state = get_next_state(state, TO_CHAR(ch)); | |
#ifdef DEBUG | |
printf("%10fe%10f >> %c: %2d -> %2d >> ", curr, exp, translate_char(TO_CHAR(ch)), state, next_state); | |
#endif | |
handle_state_transition(&curr, &exp, ch, decimal, next_state); | |
#ifdef DEBUG | |
printf("%10fe%10f\n", curr, exp); | |
#endif | |
if (next_state == S4 && state == S2) { | |
decimal = 0; | |
} | |
if (next_state == S3 && state == S1) { | |
decimal = 0; | |
} | |
if (next_state == STATE_INITIAL || next_state == STATE_TERMINAL) { | |
sum += curr * pow(10.0, exp); | |
curr = 0.0; | |
exp = 0.0; | |
decimal = -1; | |
} | |
if (next_state == STATE_INITIAL && state != STATE_INITIAL) { | |
ungetc(ch, stdin); | |
} | |
if (next_state == STATE_TERMINAL) | |
break; | |
state = next_state; | |
} | |
printf("%.4f\n", sum); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment