Arithmetic Drill
December 31, 2010
Here is drill
; the optional argument gives the maximum number for an addend, and defaults to 10:
(define (drill . arg)
(let ((n (if (null? arg) 10 (car arg))))
(let loop ((n1 (randint n)) (n2 (randint n)))
(for-each display `(,n1 " + " ,n2 " = "))
(let ((s (read)))
(cond ((eof-object? s)
(display "Goodbye!") (newline))
((not (number? s))
(display (+ n1 n2)) (newline)
(loop (randint n) (randint n)))
((= (+ n1 n2) s)
(display "Right!") (newline)
(loop (randint n) (randint n)))
(else (display "Wrong, try again!")
(newline) (loop n1 n2)))))))
Scheme handles this better than some other languages because read
can handle both numbers and text.
We used randint
from the Standard Prelude. You can see the code at http://programmingpraxis.codepad.org/tjoTFXBo.
[…] Praxis – Arithmetic Drill By Remco Niemeijer In today’s Programming Praxis exercise, our goal is to write a program that allows children to test their […]
My Haskell solution (see http://bonsaicode.wordpress.com/2010/12/31/programming-praxis-arithmetic-drill/ for a version with comments):
My Python 3 solution:
Here’s a simple ruby version:
My Python solution:
Sorry, only handles keyboard interrupts. This one also handles EOF:
In C:
;; Hum, my comment does not show up (even with refreshes), but the system says I already posted it!
(define (drill)
(call/cc
(lambda(exit)
(let loop ()
(and (call/cc
(lambda (break)
(let ((a (random-integer 10))
(b (random-integer 10)))
(if (or (zero? a) (zero? b))
(break #f))
(map display `(,a ” + ” ,b ” = “))
(let ((v (read)))
(cond
((eof-object? v) (exit ‘bye))
((not (number? v)) (break #f))
((= v (+ a b)) (display ‘yeah!))
(else (display ‘booh)))))))
(newline))
(loop)))))
My ruby version:
Not sure what is meant by handling an end-of-file in the terminal. Just learning Ruby, so probably not the best style.
def quiz (num1=rand(10), num2=rand(10))
while true
print “#{ num1 } + #{ num2 } = ”
answer = STDIN.gets.strip
if answer == “?”
puts “#{ num1 + num2 }”
quiz
elsif answer.to_i == num1 + num2
puts “Right!”
quiz
else
puts “Wrong, try again”
end
end
end
quiz
@Axio: does all that call/cc really bring some benefits or is it just to show some different way it could be done?
Roti: it’s just the way to code it that seemed clear and natural to me. One might argue that call/cc is quite overkill here, as I just use it instead of exceptions to simulate “break” (as in a “while loop”). But it’s just an exit continuation, so this is a quite common pattern that keeps code understandable.
So, whether it is a benefit or not will probably be subjective here.
PHP version
golf score: 305
(require(lib “1.ss” “srfi”))(let p()(let l((n(random 10))(m(random 10)))(printf “~a + ~a = ” n m)(flush-output)(let*((s(read))(z(reduce(lambda(x a)(if(eq?(car x)s)x a))0`((0 “Wrong, try again!”,l,n,m)(,(+ n m) “Right!”,p)(?,(+ n m),p)(^Z “Goodbye!”,void)))))(displayln(cadr z))(apply(caddr z)(cdddr z)))))
C Version:
#include
#include
#include
int createQuestion(int questionType); /*question type decides if the question will be + or -. It returns 0 if answered correct or 1 if wrong.*/
main()
{
int a = 0;
int result = 0;
printf(“\nAnswer the questions. If you get 5 questions wrong the game ends. Try to answer as many as possible.\n”);
printf(“Press 1 for addition problems or 2 for subtraction problems, or 3 for both: “);
scanf(“%d”,&a);
while(result<5){
switch (a)
{
case 1:
result = result +createQuestion(1);
printf("\nresult:%d\n",result);
break;
case 2:
result = result +createQuestion(2);
break;
case 3:
result = result +createQuestion(3);
break;
}//switch
}//while
}//main
int createQuestion(int questionType) {
int int1, int2,input, answer;
srand ( time(NULL) );
int1 = rand() % 256 + 1;
int2 = rand() %256+1;
switch (questionType)
{
case 1:
printf("\n%d+%d= ",int1,int2);
answer = int1+int2;
break;
case 2:
printf("\n%d-%d= ",int1,int2);
answer = int1-int2;
break;
case 3:
if(int1<int2){
printf("\n%d+%d= ",int1,int2);
answer = int1+int2;
}
else{
printf("\n%d-%d= ",int1,int2);
answer = int1 – int2;
}
break;
}
scanf("%d",&input);
printf("\n%d\n",answer);
if(input==answer)
return 0;
else
return 1;
}
I got rid the reduce by using racket’s built in assq function, eliminating the need for srfi/1.
New golf score for my racket scheme version: 238
(let p()(let l((n(random 10))(m(random 10)))(printf”~a + ~a = “n m)(flush-output)(let*((s(read))(z(assq s `((,(+ n m)”Right!”,p)(?,(+ n m),p)(^Z”Goodbye!”,void)(,s”Wrong, try again!”,(lambda()(l n m)))))))(displayln(cadr z))((caddr z)))))
Possible solution REXX