Computer Programming Contest Preparation

ToolBox - Source for: 4/424/d.c



/home/toolbox/public_html/solutions/4/424/d.c
    1 #include <stdio.h>
    2 #include <ctype.h>
    3 #include <string.h>
    4 #include <sys/types.h>
    5 #include <sys/stat.h>
    6 #include <fcntl.h>
    7 #include <stdint.h>
    8 #include <math.h>
    9 #include <stdlib.h>
   10 
   11 #define TRUE  (1 == 1)
   12 #define FALSE (1 != 1)
   13 
   14 #define DEBUG if (FALSE)
   15 
   16 /*
   17  *  Author: Isaac Traxler
   18  *    Date: 2015 02 11
   19  * Purpose:
   20  * Problem: 424
   21  */
   22 
   23 /*
   24  * This template reads data until a terminating value is reached.
   25  */
   26 
   27 #define MAX_LINE 1025
   28 
   29 #define LN_MAX_DIGITS 1000
   30 
   31 typedef struct LARGE_NUMBER_STRUCT
   32 {
   33     unsigned short int array[LN_MAX_DIGITS]; /* /* might consider unsigned char here
   34                                              /* to reduce storage by 50% */
   35     signed short   int sign;
   36     signed long    int exponent;
   37     signed short   int digitCount;
   38 }
   39 LARGE_NUMBER_STRUCT;
   40 
   41 char buffer[MAX_LINE];
   42 LARGE_NUMBER_STRUCT tot;
   43 LARGE_NUMBER_STRUCT num;
   44 
   45 
   46 void LNprint(LARGE_NUMBER_STRUCT *n)
   47 /* simple routine to print large number */
   48 {
   49     /* BEGIN function LNprint -- (200302) */
   50     char str[LN_MAX_DIGITS+25];
   51 
   52     LNarr2str(n, str);
   53     printf("[%s]\n", str);
   54 } /* END function LNprint -- (200302) */
   55 
   56 int LNstr2arr(char str[], LARGE_NUMBER_STRUCT *ln)
   57 {
   58     /* BEGIN function LNstr2arr -- (200302) */
   59 #define START  1
   60 #define NUM1   2
   61 #define NUM2   3
   62 #define DEC1   4
   63 #define DEC2   5
   64 #define EXP1   6
   65 #define EXP2   7
   66 #define EXP3   8
   67     int state = START, done = 0, n = 0;
   68     signed short int dpflag = 0, numflag = 0, sign = 1;
   69     signed long int exp;
   70     char *ch = str;
   71 
   72     /* skip leading blanks and leading zeroes (start < > start) */
   73     while ( (isspace(*ch)) || ('0' == *ch) ) ch++;
   74 
   75     if (0 != *ch) /* is it end of string? */
   76         {
   77             /* not empty string */
   78             /* do we have a sign (must be first char)  */
   79             if ('-' == *ch)
   80                 {
   81                     /* negative - state is NUM1 */
   82                     sign = -1;
   83                     ch++;
   84                 } /* negative - state is NUM1 */
   85             else
   86                 /* Check for plus sign: Not really necessary...(these 4 lines may  */
   87                 /* be omitted) if numbers are not going to have unary pluses */
   88                 if (*ch == '+')
   89                     {
   90                         /* positive (the default) - state is NUM1 */
   91                         ch++;
   92                     } /* positive (the default) - state is NUM1 */
   93 
   94             /* now get digits until the decimal point or exponent */
   95             while (isdigit(*ch))
   96                 {
   97                     /* process digits -- into state NUM2 */
   98                     state = NUM2;
   99                     ln->array[n++] = *ch - '0';
  100                     ch++;  /* move to next char in string */
  101                 } /* process digits -- into state NUM2 */
  102             exp = n;
  103 
  104             if ('.' == *ch)
  105                 {
  106                     /* decimal point  */
  107                     /* set state to DEC1 if no digits, DEC2 if digits already */
  108                     state = (NUM2 != state) ? DEC1 : DEC2;
  109                     ch++;
  110 
  111                     /* now get digits after the decimal point */
  112                     if (isdigit(*ch)) state = DEC2;
  113                     while (isdigit(*ch))
  114                         {
  115                             /* process digits -- into state NUM2 */
  116                             ln->array[n++] = *ch - '0';
  117                             ch++;  /* move to next char in string */
  118                         } /* process digits -- into state NUM2 */
  119                 } /* decimal point */
  120 
  121             /* only things left are Ee (exponent), whitespace and end of string */
  122             if (('E' == *ch) || ('e' == *ch))
  123                 {
  124                     /* okay we have an exponent */
  125                     signed long int texp;
  126 
  127                     state = EXP2;
  128                     ch++;
  129                     sscanf(ch, "%d", &texp);
  130                     exp += texp;
  131                 } /* okay we have an exponent */
  132         } /* not empty string */
  133 
  134     if ((EXP2 == state) || (DEC2 == state) || (NUM2 == state))
  135         {
  136             /* normalize number */
  137             ln->sign = sign;
  138             ln->exponent = exp;
  139             ln->digitCount = n;
  140             state = 0;
  141         } /* normalize number */
  142     return state;
  143 } /* END function LNstr2arr -- (200302)  */
  144 
  145 int LNnormalize(LARGE_NUMBER_STRUCT *ln)
  146 /* fix LN so that arr[0] <> 0 (if possible)  */
  147 {
  148     /* BEGIN function LNnormalize -- (200302)  */
  149     /* errorLevel - Errorlevel to return.  */
  150     /* zeroCount - How many zeroes?  */
  151     /* i - Loop variable  */
  152     int i, errorLevel = 0, zeroCount = 0;
  153 
  154     if (0 < ln->digitCount)
  155         {
  156             /* digits to process */
  157             while ((ln->array[zeroCount] == 0) && (zeroCount < ln->digitCount))
  158                 {
  159                     /* count leading zeroes */
  160                     zeroCount ++;
  161                 } /* count leading zeroes */
  162             if (0 < zeroCount)
  163                 {
  164                     /* found leading zeroes */
  165                     if (zeroCount == ln->digitCount)
  166                         {
  167                             /* entire number is zero */
  168                             ln->exponent = 0;
  169                             ln->digitCount = 0;
  170                             ln->sign = 1;
  171                         } /* entire number is zero */
  172                     else
  173                         {
  174                             /* digits to shift */
  175                             ln->digitCount -= zeroCount;
  176                             ln->exponent -= zeroCount;
  177                             for (i = 0; i < ln->digitCount; i++)
  178                                 {
  179                                     /* shift them */
  180                                     ln->array[i] = ln->array[i + zeroCount];
  181                                 } /* shift them */
  182                         } /* digits to shift */
  183                 } /* found leading zeroes */
  184             /* handle railing zeroes  */
  185             i = ln->digitCount - 1;
  186             while ((i >= 0) && (0 == ln->array[i]))
  187                 {
  188                     /* while */
  189                     ln->digitCount--;
  190                     i--;
  191                 } /* while */
  192             if (0 == ln->digitCount)
  193                 {
  194                     /* entire number is zero */
  195                     ln->exponent = 0;
  196                     ln->sign = 1;
  197                 } /* entire number is zero */
  198         } /* digits to process */
  199     return (errorLevel);
  200 } /* END function LNnormalize -- (200302)  */
  201 
  202 int LNadd(LARGE_NUMBER_STRUCT *lna, LARGE_NUMBER_STRUCT *lnb,
  203           LARGE_NUMBER_STRUCT *ln3)
  204 /* ln3=ln1+ln2        */
  205 {
  206     /* BEGIN function LNadd  -- (200302)  */
  207     int i, cnt, state = 0, carry = 0;
  208     LARGE_NUMBER_STRUCT ln1, ln2;
  209 
  210     if (0 == lna->digitCount)
  211         *ln3 = *lnb;
  212     else if (0 == lnb->digitCount)
  213         *ln3 = *lna;
  214     else
  215         {
  216             /* add non-zero numbers  */
  217             ln1 = *lna;
  218             ln2 = *lnb;
  219             if (ln1.sign == ln2.sign)
  220                 {
  221                     /* signs are same -- continue adding */
  222                     if (ln1.exponent > ln2.exponent)
  223                         {
  224                             /* ln1 is biger */
  225                             LNshift(&ln1, 1);
  226                             LNshift(&ln2, (ln1.exponent - ln2.exponent));
  227                         } /* ln1 is biger */
  228                     else
  229                         {
  230                             /* ln2 is biger */
  231                             LNshift(&ln2, 1);
  232                             LNshift(&ln1, (ln2.exponent - ln1.exponent));
  233                         } /* ln2 is biger */
  234 
  235                     if (ln1.digitCount > ln2.digitCount)
  236                         {
  237                             /* 1 has more digits */
  238                             for (i = ln1.digitCount - 1; i >= ln2.digitCount; i--)
  239                                 ln3->array[i] = ln1.array[i];
  240                             cnt = ln2.digitCount;
  241                             ln3->digitCount = ln1.digitCount;
  242                         } /* 1 has more digits */
  243                     else
  244                         {
  245                             /* 2 has more digits */
  246                             for (i = ln2.digitCount - 1; i >= ln1.digitCount; i--)
  247                                 ln3->array[i] = ln2.array[i];
  248                             cnt = ln1.digitCount;
  249                             ln3->digitCount = ln2.digitCount;
  250                         } /* 2 has more digits */
  251                     /* now actually add */
  252                     ln3->exponent = ln1.exponent;
  253                     for (i = cnt - 1; i >= 0;  i--)
  254                         {
  255                             /* for */
  256                             ln3->array[i] = ln1.array[i] + ln2.array[i] + carry;
  257                             if (ln3->array[i] > 9)
  258                                 {
  259                                     /* set carry */
  260                                     carry = 1;
  261                                     ln3->array[i] -= 10;
  262                                 } /* set carry */
  263                             else
  264                                 {
  265                                     /* reset carry */
  266                                     carry = 0;
  267                                 } /* reset carry */
  268                         } /* for */
  269                     LNnormalize(ln3);
  270                 } /* signs are same -- continue adding */
  271         } /* add non-zero numbers  */
  272     return state;
  273 } /* END function LNadd -- (200302)  */
  274 
  275 
  276 void init()
  277 {
  278     /* FUNCTION init */
  279     buffer[0] = '0';
  280     buffer[1] = 0;
  281     LNstr2arr(buffer, &tot);
  282 } /* FUNCTION init */
  283 
  284 int getInput()
  285 {
  286     /* FUNCTION getInput */
  287     int dataReadFlag;
  288     int i;
  289     int top;
  290 
  291     scanf(" %s ", buffer);
  292     if (0 == strcmp("0", buffer))
  293         {
  294             /* end of file reached */
  295             dataReadFlag = FALSE;
  296         } /* end of file reached */
  297     else
  298         {
  299             /* read in something */
  300             LNstr2arr(buffer, &num);
  301         } /* read in something */
  302     return (dataReadFlag);
  303 } /* FUNCTION getInput */
  304 
  305 void process()
  306 {
  307     /* FUNCTION process */
  308     LNadd(&num, &tot, &tot);
  309 } /* FUNCTION process */
  310 
  311 int main()
  312 {
  313     /* main */
  314     int moreToDo;
  315     int gotInput = FALSE;
  316 
  317     init();
  318     moreToDo = getInput();
  319     while (moreToDo)
  320         {
  321             /* while */
  322             gotInput = TRUE;
  323             process();
  324             moreToDo = getInput();
  325         } /* while */
  326     if (gotInput)
  327         {
  328             LNprint(&tot);
  329         }
  330 
  331     return EXIT_SUCCESS;
  332 } /* main */
  333