xref: /original-bsd/games/number/number.c (revision 179d6f6f)
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	5.1 (Berkeley) 02/28/91";
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 convert(line)
69 	char	*line;
70 {
71 	register int	len,
72 			ret;
73 	register char	*C,
74 			*fraction;
75 
76 	for (fraction = NULL, C = line;*C && *C != '\n';++C)
77 		if (!isdigit(*C))
78 			switch(*C) {
79 			case '-':
80 				if (C != line)
81 					usage(NO);
82 				break;
83 			case '.':
84 				if (!fraction) {
85 					fraction = C + 1;
86 					*C = EOS;
87 					break;
88 				}
89 			default:
90 				usage(NO);
91 			}
92 	*C = EOS;
93 	if (*line == '-') {
94 		puts("minus");
95 		++line;
96 	}
97 	ret = NO;
98 	if (len = strlen(line)) {
99 		if (len > MAXNUM)
100 			usage(YES);
101 		ret = unit(len,line);
102 	}
103 	if (fraction && (len = strlen(fraction))) {
104 		if (len > MAXNUM)
105 			usage(YES);
106 		for (C = fraction;*C;++C)
107 			if (*C != '0') {
108 				if (ret)
109 					puts("and");
110 				if (unit(len,fraction)) {
111 					++ret;
112 					pfract(len);
113 				}
114 				break;
115 			}
116 	}
117 	if (!ret)
118 		puts("zero.");
119 }
120 
121 unit(len,C)
122 	register int	len;
123 	register char	*C;
124 {
125 	register int	off,
126 			ret;
127 
128 	ret = NO;
129 	if (len > 3) {
130 		if (len % 3) {
131 			off = len % 3;
132 			len -= off;
133 			if (number(C,off)) {
134 				ret = YES;
135 				printf(" %s.\n",name3[len / 3]);
136 			}
137 			C += off;
138 		}
139 		for (;len > 3;C += 3) {
140 			len -= 3;
141 			if (number(C,3)) {
142 				ret = YES;
143 				printf(" %s.\n",name3[len / 3]);
144 			}
145 		}
146 	}
147 	if (number(C,len)) {
148 		puts(".");
149 		ret = YES;
150 	}
151 	return(ret);
152 }
153 
154 number(C,len)
155 	register char	*C;
156 	int	len;
157 {
158 	register int	val,
159 			ret;
160 
161 	ret = 0;
162 	switch(len) {
163 	case 3:
164 		if (*C != '0') {
165 			++ret;
166 			printf("%s hundred",name1[*C - '0']);
167 		}
168 		++C;
169 		/*FALLTHROUGH*/
170 	case 2:
171 		val = (C[1] - '0') + (C[0] - '0') * 10;
172 		if (val) {
173 			if (ret++)
174 				putchar(' ');
175 			if (val < 20)
176 				fputs(name1[val],stdout);
177 			else {
178 				fputs(name2[val / 10],stdout);
179 				if (val % 10)
180 					printf("-%s",name1[val % 10]);
181 			}
182 		}
183 		break;
184 	case 1:
185 		if (*C != '0') {
186 			++ret;
187 			fputs(name1[*C - '0'],stdout);
188 		}
189 	}
190 	return(ret);
191 }
192 
193 pfract(len)
194 	register int	len;
195 {
196 	static char	*pref[] = { "", "ten-", "hundred-" };
197 
198 	switch(len) {
199 	case 1:
200 		puts("tenths.");
201 		break;
202 	case 2:
203 		puts("hundredths.");
204 		break;
205 	default:
206 		printf("%s%sths.\n",pref[len % 3],name3[len / 3]);
207 	}
208 }
209 
210 usage(toobig)
211 	int	toobig;
212 {
213 	if (toobig)
214 		fprintf(stderr,"number: number too large, max %d digits.\n",MAXNUM);
215 	fputs("usage: number # ...\n",stderr);
216 	exit(-1);
217 }
218