xref: /original-bsd/games/number/number.c (revision 9fa17c5f)
1 /*
2  * Copyright (c) 1988 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 char copyright[] =
10 "@(#) Copyright (c) 1988 Regents of the University of California.\n\
11  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)number.c	4.6 (Berkeley) 06/01/90";
16 #endif /* not lint */
17 
18 #include <stdio.h>
19 #include <ctype.h>
20 
21 #define	YES		1
22 #define	NO		0
23 #define	EOS		'\0'
24 #define	MAXNUM		65		/* biggest number we handle */
25 
26 static char	*name1[] = {
27 	"",		"one",		"two",		"three",
28 	"four",		"five",		"six",		"seven",
29 	"eight",	"nine",		"ten",		"eleven",
30 	"twelve",	"thirteen",	"fourteen",	"fifteen",
31 	"sixteen",	"seventeen",	"eighteen",	"nineteen",
32 },
33 		*name2[] = {
34 	"",		"ten",		"twenty",	"thirty",
35 	"forty",	"fifty",	"sixty",	"seventy",
36 	"eighty",	"ninety",
37 },
38 		*name3[] = {
39 	"hundred",	"thousand",	"million",	"billion",
40 	"trillion",	"quadrillion",	"quintillion",	"sextillion",
41 	"septillion",	"octillion",	"nonillion",	"decillion",
42 	"undecillion",	"duodecillion",	"tredecillion",	"quattuordecillion",
43 	"quindecillion",		"sexdecillion",
44 	"septendecillion",		"octodecillion",
45 	"novemdecillion",		"vigintillion",
46 };
47 
48 main(argc,argv)
49 	int	argc;
50 	char	**argv;
51 {
52 	register int	cnt;
53 	char	line[MAXNUM * 2 + 2];		/* MAXNUM '.' MAXNUM '\0' */
54 
55 	if (argc > 1)
56 		for (cnt = 1;cnt < argc;++cnt) {
57 			convert(argv[cnt]);
58 			puts("...");
59 		}
60 	else
61 		while (fgets(line,sizeof(line),stdin)) {
62 			convert(line);
63 			puts("...");
64 		}
65 	exit(0);
66 }
67 
68 static
69 convert(line)
70 	char	*line;
71 {
72 	register int	len,
73 			ret;
74 	register char	*C,
75 			*fraction;
76 
77 	for (fraction = NULL, C = line;*C && *C != '\n';++C)
78 		if (!isdigit(*C))
79 			switch(*C) {
80 			case '-':
81 				if (C != line)
82 					usage(NO);
83 				break;
84 			case '.':
85 				if (!fraction) {
86 					fraction = C + 1;
87 					*C = EOS;
88 					break;
89 				}
90 			default:
91 				usage(NO);
92 			}
93 	*C = EOS;
94 	if (*line == '-') {
95 		puts("minus");
96 		++line;
97 	}
98 	ret = NO;
99 	if (len = strlen(line)) {
100 		if (len > MAXNUM)
101 			usage(YES);
102 		ret = unit(len,line);
103 	}
104 	if (fraction && (len = strlen(fraction))) {
105 		if (len > MAXNUM)
106 			usage(YES);
107 		for (C = fraction;*C;++C)
108 			if (*C != '0') {
109 				if (ret)
110 					puts("and");
111 				if (unit(len,fraction)) {
112 					++ret;
113 					pfract(len);
114 				}
115 				break;
116 			}
117 	}
118 	if (!ret)
119 		puts("zero.");
120 }
121 
122 static
123 unit(len,C)
124 	register int	len;
125 	register char	*C;
126 {
127 	register int	off,
128 			ret;
129 
130 	ret = NO;
131 	if (len > 3) {
132 		if (len % 3) {
133 			off = len % 3;
134 			len -= off;
135 			if (number(C,off)) {
136 				ret = YES;
137 				printf(" %s.\n",name3[len / 3]);
138 			}
139 			C += off;
140 		}
141 		for (;len > 3;C += 3) {
142 			len -= 3;
143 			if (number(C,3)) {
144 				ret = YES;
145 				printf(" %s.\n",name3[len / 3]);
146 			}
147 		}
148 	}
149 	if (number(C,len)) {
150 		puts(".");
151 		ret = YES;
152 	}
153 	return(ret);
154 }
155 
156 static
157 number(C,len)
158 	register char	*C;
159 	int	len;
160 {
161 	register int	val,
162 			ret;
163 
164 	ret = 0;
165 	switch(len) {
166 	case 3:
167 		if (*C != '0') {
168 			++ret;
169 			printf("%s hundred",name1[*C - '0']);
170 		}
171 		++C;
172 		/*FALLTHROUGH*/
173 	case 2:
174 		val = (C[1] - '0') + (C[0] - '0') * 10;
175 		if (val) {
176 			if (ret++)
177 				putchar(' ');
178 			if (val < 20)
179 				fputs(name1[val],stdout);
180 			else {
181 				fputs(name2[val / 10],stdout);
182 				if (val % 10)
183 					printf("-%s",name1[val % 10]);
184 			}
185 		}
186 		break;
187 	case 1:
188 		if (*C != '0') {
189 			++ret;
190 			fputs(name1[*C - '0'],stdout);
191 		}
192 	}
193 	return(ret);
194 }
195 
196 static
197 pfract(len)
198 	register int	len;
199 {
200 	static char	*pref[] = { "", "ten-", "hundred-" };
201 
202 	switch(len) {
203 	case 1:
204 		puts("tenths.");
205 		break;
206 	case 2:
207 		puts("hundredths.");
208 		break;
209 	default:
210 		printf("%s%sths.\n",pref[len % 3],name3[len / 3]);
211 	}
212 }
213 
214 static
215 usage(toobig)
216 	int	toobig;
217 {
218 	if (toobig)
219 		fprintf(stderr,"number: number too large, max %d digits.\n",MAXNUM);
220 	fputs("usage: number # ...\n",stderr);
221 	exit(-1);
222 }
223