/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