This commit was generated by cvs2svn to track changes on a CVS vendor
[unix-history] / games / number / number.c
CommitLineData
15637ed4
RG
1/*
2 * Copyright (c) 1988 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35char copyright[] =
36"@(#) Copyright (c) 1988 Regents of the University of California.\n\
37 All rights reserved.\n";
38#endif /* not lint */
39
40#ifndef lint
41static char sccsid[] = "@(#)number.c 5.1 (Berkeley) 2/28/91";
42#endif /* not lint */
43
44#include <stdio.h>
45#include <ctype.h>
46
47#define YES 1
48#define NO 0
49#define EOS '\0'
50#define MAXNUM 65 /* biggest number we handle */
51
52static char *name1[] = {
53 "", "one", "two", "three",
54 "four", "five", "six", "seven",
55 "eight", "nine", "ten", "eleven",
56 "twelve", "thirteen", "fourteen", "fifteen",
57 "sixteen", "seventeen", "eighteen", "nineteen",
58},
59 *name2[] = {
60 "", "ten", "twenty", "thirty",
61 "forty", "fifty", "sixty", "seventy",
62 "eighty", "ninety",
63},
64 *name3[] = {
65 "hundred", "thousand", "million", "billion",
66 "trillion", "quadrillion", "quintillion", "sextillion",
67 "septillion", "octillion", "nonillion", "decillion",
68 "undecillion", "duodecillion", "tredecillion", "quattuordecillion",
69 "quindecillion", "sexdecillion",
70 "septendecillion", "octodecillion",
71 "novemdecillion", "vigintillion",
72};
73
74main(argc,argv)
75 int argc;
76 char **argv;
77{
78 register int cnt;
79 char line[MAXNUM * 2 + 2]; /* MAXNUM '.' MAXNUM '\0' */
80
81 if (argc > 1)
82 for (cnt = 1;cnt < argc;++cnt) {
83 convert(argv[cnt]);
84 puts("...");
85 }
86 else
87 while (fgets(line,sizeof(line),stdin)) {
88 convert(line);
89 puts("...");
90 }
91 exit(0);
92}
93
94convert(line)
95 char *line;
96{
97 register int len,
98 ret;
99 register char *C,
100 *fraction;
101
102 for (fraction = NULL, C = line;*C && *C != '\n';++C)
103 if (!isdigit(*C))
104 switch(*C) {
105 case '-':
106 if (C != line)
107 usage(NO);
108 break;
109 case '.':
110 if (!fraction) {
111 fraction = C + 1;
112 *C = EOS;
113 break;
114 }
115 default:
116 usage(NO);
117 }
118 *C = EOS;
119 if (*line == '-') {
120 puts("minus");
121 ++line;
122 }
123 ret = NO;
124 if (len = strlen(line)) {
125 if (len > MAXNUM)
126 usage(YES);
127 ret = unit(len,line);
128 }
129 if (fraction && (len = strlen(fraction))) {
130 if (len > MAXNUM)
131 usage(YES);
132 for (C = fraction;*C;++C)
133 if (*C != '0') {
134 if (ret)
135 puts("and");
136 if (unit(len,fraction)) {
137 ++ret;
138 pfract(len);
139 }
140 break;
141 }
142 }
143 if (!ret)
144 puts("zero.");
145}
146
147unit(len,C)
148 register int len;
149 register char *C;
150{
151 register int off,
152 ret;
153
154 ret = NO;
155 if (len > 3) {
156 if (len % 3) {
157 off = len % 3;
158 len -= off;
159 if (number(C,off)) {
160 ret = YES;
161 printf(" %s.\n",name3[len / 3]);
162 }
163 C += off;
164 }
165 for (;len > 3;C += 3) {
166 len -= 3;
167 if (number(C,3)) {
168 ret = YES;
169 printf(" %s.\n",name3[len / 3]);
170 }
171 }
172 }
173 if (number(C,len)) {
174 puts(".");
175 ret = YES;
176 }
177 return(ret);
178}
179
180number(C,len)
181 register char *C;
182 int len;
183{
184 register int val,
185 ret;
186
187 ret = 0;
188 switch(len) {
189 case 3:
190 if (*C != '0') {
191 ++ret;
192 printf("%s hundred",name1[*C - '0']);
193 }
194 ++C;
195 /*FALLTHROUGH*/
196 case 2:
197 val = (C[1] - '0') + (C[0] - '0') * 10;
198 if (val) {
199 if (ret++)
200 putchar(' ');
201 if (val < 20)
202 fputs(name1[val],stdout);
203 else {
204 fputs(name2[val / 10],stdout);
205 if (val % 10)
206 printf("-%s",name1[val % 10]);
207 }
208 }
209 break;
210 case 1:
211 if (*C != '0') {
212 ++ret;
213 fputs(name1[*C - '0'],stdout);
214 }
215 }
216 return(ret);
217}
218
219pfract(len)
220 register int len;
221{
222 static char *pref[] = { "", "ten-", "hundred-" };
223
224 switch(len) {
225 case 1:
226 puts("tenths.");
227 break;
228 case 2:
229 puts("hundredths.");
230 break;
231 default:
232 printf("%s%sths.\n",pref[len % 3],name3[len / 3]);
233 }
234}
235
236usage(toobig)
237 int toobig;
238{
239 if (toobig)
240 fprintf(stderr,"number: number too large, max %d digits.\n",MAXNUM);
241 fputs("usage: number # ...\n",stderr);
242 exit(-1);
243}