1 
2 static char sccsid[] = "	arithmetic.c	4.1	82/10/24	";
3 
4 #include <stdio.h>
5 #include <signal.h>
6 #define	MAX	100
7 
8 char	types[10];
9 int	right[MAX];
10 int	left[MAX];
11 int	rights;
12 int	wrongs;
13 long	stvec;
14 long	etvec;
15 long	dtvec;
16 
17 main(argc,argv)
18 char	*argv[];
19 {
20 	int range, k, dif, l;
21 	char line[100];
22 	int ans,pans,i,j,t;
23 	char	dir,sense;
24 	extern	delete();
25 
26 	signal(SIGINT, delete);
27 
28 	range = 11;
29 	dif = 0;
30 	while(argc > 1) {
31 		switch(*argv[1]) {
32 		case '+':
33 		case '-':
34 		case 'x':
35 		case '/':
36 			while(types[dif] = argv[1][dif])
37 				dif++;
38 			break;
39 
40 		default:
41 			range = getnum(argv[1]) + 1;
42 		}
43 		argv++;
44 		argc--;
45 	}
46 	if(range > MAX) {
47 		printf("Range is too large.\n");
48 		exit();
49 	}
50 
51 	if(dif == 0) {
52 		types[0] = '+';
53 		types[1] = '-';
54 		dif = 2;
55 	}
56 
57 	for(i = 0; i < range; i++) {
58 		left[i] = right[i] = i;
59 	}
60 	time(&stvec);
61 	k = stvec;
62 	srand(k);
63 	k = 0;
64 	l = 0;
65 	goto start;
66 
67 loop:
68 	if(++k%20 == 0)
69 		score();
70 
71 start:
72 	i = skrand(range);
73 	j = skrand(range);
74 	if(dif > 1)
75 		l = random(dif);
76 
77 	switch(types[l]) {
78 		case '+':
79 		default:
80 			ans = left[i] + right[j];
81 			printf("%d + %d =   ", left[i], right[j]);
82 			break;
83 
84 		case '-':
85 			t = left[i] + right[j];
86 			ans = left[i];
87 			printf("%d - %d =   ", t, right[j]);
88 			break;
89 
90 		case 'x':
91 			ans = left[i] * right[j];
92 			printf("%d x %d =   ", left[i], right[j]);
93 			break;
94 
95 		case '/':
96 			while(right[j] == 0)
97 				j = random(range);
98 			t = left[i] * right[j] + random(right[j]);
99 			ans = left[i];
100 			printf("%d / %d =   ", t, right[j]);
101 			break;
102 	}
103 
104 
105 loop1:
106 	getline(line);
107 	dtvec += etvec - stvec;
108 	if(line[0]=='\n') goto loop1;
109 	pans = getnum(line);
110 	if(pans == ans) {
111 		printf("Right!\n");
112 		rights++;
113 		goto loop;
114 	}
115 	else {
116 		printf("What?\n");
117 		wrongs++;
118 		if(range >= MAX)	goto loop1;
119 		left[range] = left[i];
120 		right[range++] = right[j];
121 		goto loop1;
122 	}
123 }
124 
125 getline(s)
126 char *s;
127 {
128 	register char	*rs;
129 
130 	rs = s;
131 
132 	while((*rs = getchar()) == ' ');
133 	while(*rs != '\n')
134 		if(*rs == 0)
135 			exit();
136 		else if(rs >= &s[99]) {
137 			while((*rs = getchar()) != '\n')
138 				if(*rs == '\0')	exit();
139 		}
140 		else
141 			*++rs = getchar();
142 	while(*--rs == ' ')
143 		*rs = '\n';
144 }
145 
146 getnum(s)
147 char *s;
148 {
149 	int	a;
150 	char	c;
151 
152 	a = 0;
153 	while((c = *s++) >= '0' && c <= '9') {
154 		a = a*10 + c - '0';
155 	}
156 	return(a);
157 }
158 
159 int arand;
160 
161 srand(n)
162 {
163 	arand = n&077774 | 01;
164 }
165 
166 rand()		/*uniform on 0 to 2**13-1*/
167 {
168 
169 	arand *= 3125;
170 	arand &= 077777;
171 	return(arand/4);
172 }
173 
174 random(range)
175 {
176 	return(hmul(rand(), 8*range));
177 }
178 
179 skrand(range){
180 int temp;
181 	temp = rand() + rand();
182 	if(temp >017777) temp = 040000 - temp;
183 	return(hmul(temp,8*range));
184 	}
185 
186 /* 'hmul' returns the upper 16 bits of the product, where the operands
187    are assumed to be 16-bit integers. It replaces an old PDP-11
188    assembler language subroutine. -- dks.
189 */
190 hmul(a,b) { return(a*b >> 16); }
191 score()
192 {
193 	time(&etvec);
194 
195 	printf("\n\nRights %d; Wrongs %d; Score %d%%\n", rights, wrongs,
196 		(rights * 100)/(rights + wrongs));
197 
198 	if(rights == 0)	return;
199 	printf("Total time %ld seconds; %.1f seconds per problem\n\n\n",
200 		etvec - stvec,
201 		(etvec - stvec) / (rights + 0.));
202 
203 	sleep(3);
204 	time(&dtvec);
205 	stvec += dtvec - etvec;
206 	return(0);
207 }
208 
209 delete()
210 {
211 	if(rights + wrongs == 0.) {
212 		printf("\n");
213 		exit();
214 	}
215 	score();
216 	exit();
217 }
218 
219