# Generate math problems

Generate math problems (addition, subtraction, or multiplication) using numbers 0-10. Provide feedback on whether the user was right or wrong and show a score.

Specifics:

• Must generate addition, subtraction, or multiplication problems
• Numbers used must be 0-10
• Each problem must be equally likely
• If user is correct, must print "correct!" (with the exclamation point)
• If user is wrong, must print "wrong!" (with the exclamation point)
• After providing correct or wrong feedback, must show score with these specifications:

• Starts with "Score:"
• Shows number correct and then "correct"
• Pipe (|) separation
• Shows number wrong and then "wrong"
• 2 newlines for separation
• Must repeat forever

For counting characters, the Text Mechanic counter will be used.

Sample session:

1-7=-6
correct!
Score: 1 correct | 0 wrong

9+3=12
correct!
Score: 2 correct | 0 wrong

4*5=20
correct!
Score: 3 correct | 0 wrong

7-8=3
wrong!
Score: 3 correct | 1 wrong

1*1=3
wrong!
Score: 3 correct | 2 wrong

7+6=

• can we assume there is only one operator per problem? – ardnew Mar 8 '13 at 2:23

Post-mortem update:

## Perl 130 bytes

Combining techniques from dan1111's excellent solution with my own, I was able to squeeze one more byte:

@b=qw(Score: 0 correct | 0 wrong);$b[$#x=eval^<>?4:1]++while print"$b[@x]! @b "x/./,$_=(0|rand 11).chr(41^2+rand 3).~~rand 11,'='


There's a few things that might not be immediately obvious. If @x is an array, then $#x (the largest index of @x) will be one smaller than the length of @x. In this way, I can use $#x to point to the appropriate counting variable, and the length of @x to the corresponding message in a single assignment, without having to +1. The score string is repeating by /./, which will return 1 if an only if $_ is non-empty. ## Perl 131 bytes Here's my Perl attempt, which is more or less a direct translation of my PHP solution below. @r=correct,${_^($n=eval^<>?z:r)}++while@z=wrong,print"@$n!
Score: $- @r |$% @z

"x@r,$_=(0|rand 11).chr(41^2+rand 3).~~rand 11,'='  $- and $% are used for counting variables as they default to 0, alleviating the need for a printf, and at the same time allowing me to combine the print statements into one. The score string is not printed the first iteration because @r has not yet been defined, and therefore x@r (repeat by the length of the array @r) repeats the string zero times, resulting in an empty string. Once again using chr(41^2+rand 3) to generate +*-, as well as a bitwise xor _^ to switch between r- and z%. I would have liked to use a type glob for *n=eval^<>?z:r, saving a byte @$n@n, but unfortunately typed as a string this comes back as either *main::r or *main::z, which isn't very useful.

</bandwagon>

## PHP 157 (155) bytes

Just to get a smattering of languages:

<?for($X=$Y=+$x=correct;$y=wrong;)echo$q=rand(0,10).chr(rand(2,4)^41).rand(0,10),'=',eval("${_&$n=$q^fgets(STDIN)?y:x}++;"),$$n,"! Score: X x | Y y ";  The initial X=Y=+ is necessary, because undefined variables print as an empty string, instead of 0. Unfortunate, but still shorter than using a printf. One thing to notice is the 'magic formula' chr(rand(2,4)^41). 2^41 = 43 (+), 3^41 = 42 (*) and 4^41 = 45 (-). chr(rand(3,5)^46) would also work, but in a different order. This can be made 2 bytes shorter by using a few binary characters: <?for(‡=†=+x=correct;y=wrong;)echoq=rand(0,10).chr(rand(2,4)^41).rand(0,10),~Â,eval("${~$n=q^fgets(STDIN)?y:x}++;"),$$n,"!
Score: $‡$x | $†$y

";


where †, ‡ and Â are characters 134, 135 and 194 respectively.

• Perl beats APL! Well done! – tomsmeding Mar 10 '13 at 6:58
• +1, I especially like your use of the while loop to get a single print statement. – user7486 Mar 11 '13 at 12:48

## APL 146 145

In index origin zero:

o←'+-×'
s←0 0
t←'wrong' 'correct'
l:⍞←(e←(⍕?11),o[?3],(⍕?11)),'='
r←(⍎e)=⍎⍞
s[r]←s[r]+1
(∊t[r]),'!'
'Score: ',s[1],t[1],'|',s[0],t[0]
' '
' '
→l

10×8=80
correct!
Score:  1 correct | 0 wrong

2×6=16
wrong!
Score:  1 correct | 1 wrong

2+5=


Perl, 144 characters

@b=qw/+ - * Score: correct 0 | wrong 0/;sub _{print@_;~~rand 11}{_$_=_.$b[rand 3]._,'=';_$b[$x=eval==<>?4:7];$b[$x+1]++;_"!\n@b[3..8]\n\n";redo}


Updated (thanks ardnew)

• very nice. you can save 2 chars by replacing int rand 10 with ~~rand 10 (well technically you should be using ~~rand 11...) – ardnew Mar 8 '13 at 23:57

## Perl 154 chars

$x=correct;$y=wrong;R:$_=join qw|+ - *|[rand 3],map~~rand 11,0,0;print"$_=";$c+=$b=<>==eval;printf"%s!$/Score: %d$x | %d $y$/$/",$b?$x:$y,$c,$.-$c;goto R  with some newlines: $x=correct;
$y=wrong; R:$_=join qw|+ - *|[rand 3],map~~rand 11,0,0;
print"$_=";$c+=$b=<>==eval; printf"%s!$/Score: %d $x | %d$y$/$/",$b?$x:$y,$c,$.-$c;
goto R


## Python 2, 180 176

from random import*
r=randrange
a='correct'
b='wrong'
c=w=0
while 1:e=r(11)+'+-*'[r(3)]+r(11);x=input(e+'=')==eval(e);c+=x;w+=1-x;print(b,a)[x]+'!\nScore:',c,a,'|',w,b+'\n'


That counter says it's only 171 chars, but I've counted new lines since that's what we normally do in code golf.

Thanks to flornquake for some improvements.

Ungolfed:

from random import *
num_correct = num_wrong = 0
while 1:
expression = str(randrange(11)) + '+-*'[randrange(3)] + str(randrange(11))
is_correct = input(expression + '=') == eval(expression)
num_correct += is_correct
num_wrong += 1 - is_correct
print ('wrong', 'correct')[is_correct] + '!\nScore:', num_correct, 'correct', '|', num_wrong, 'wrong\n'

• I tried that code in IDLE and nothing happened. EDIT: Never mind, works in a file. +1 – Doorknob Mar 8 '13 at 2:46
• Didn't think of using c+=x;w+=1-x, had c[x]+=1 instead and some string formatting. – beary605 Mar 8 '13 at 2:58
• Any Chance of an un-golfed version? Thanks. – Ari Porad Jul 22 '14 at 0:11
• @AriPorad I've added one. – grc Jul 22 '14 at 1:19

# CJam, 90 bytes

Seems like I'm a little late to this question... as is my language, so per site rules, this answer can't officially be selected as the winner. But I had completed my answer for a recent question that was marked as a duplicate of this question and didn't want to let it go to waste, so I modified it a bit for this question.

{Bmr3mr"+-*"=Bmr]_o'=o~\~li=:R["correct":C"wrong":W?'!N"Score:"SUR+:USCS'|SVR!+:VSWNN]o1}g


Due to the interactive nature of the program, the online interpreter cannot be used. You must use the Java interpreter.

I normally post a lengthy explanation, but the code works in about as straightforward of a manner as you can get. That's not to say that I banged this answer out in all of a couple of minutes, though, as there was a fair amount of time spent searching for and making small optimizations.

## Javascript 169 chars

Here's a solution that doesn't use the console (does that break the rules?) but works via alert boxes (yeah I know...):

for(c=w=0;r=Math.random;){prompt(x=~~(r()*9+1)+"+-*"[~~(r()*3)]+~~(r()*9+1))==eval(x)?(m="correct",c++):(m="wrong",w++);alert(m+"!\nScore: "+c+" correct | "+w+" wrong")}


The attempts at golfing are quite weak, but this was just for fun right? :)

EDIT: Ungolfed version follows. I expanded variable names and split up the assignment of x into a, op and b. The logic is the same. Bear in mind that ~~(X) == Math.floor(X) for positive X. This is just easier to type.

correct=wrong=0;
rand=Math.random;
while(1){
a=~~(rand()*9+1);
op="+-*"[~~(rand()*3)];
b=~~(rand()*9+1);
x=a+op+b;
if(prompt(x)==eval(x)){msg="correct";correct++}
else{msg="wrong";wrong++}
alert(msg+"!\nScore: "+c+" correct | "+w+" wrong");
}

• do you have an un-golfed version by chance? Thanks – Ari Porad Jul 22 '14 at 0:11
• @AriPorad See my edit. – tomsmeding Jul 23 '14 at 8:06
• You can save some chars if you replace the if-else with statement?(msg="correct",correct++):(msg="wrong",wrong++); – izlin Jul 23 '14 at 10:24

## C# - 283 Characters

This is my solution in C# in 283 characters:

var r=new Random();int a=0,b=0,x=0,y=0;var w="";Action C=()=>Console.WriteLine(w);for(;;){x=r.Next(11);y=r.Next(11);int[]R={x+y,x-y,x*y};w=""+x+"+-*"[x%3]+y+"=";C();var f=Console.ReadLine()==""+R[x%3];x=f?a++:b++;w=(f?"correct":"wrong")+"!\nScore:"+a+" correct | "+b+" wrong\n";C();}


With more indentation, it looks like:

var r=new Random();
int a=0,b=0,x=0,y=0;
var w="";
Action C=()=>Console.WriteLine(w);
for(;;){
x=r.Next(11);y=r.Next(11);
int[] R={x+y,x-y,x*y};
w=""+x+"+-*"[x%3]+y+"=";C();
x=f?a++:b++;
w=(f?"correct":"wrong")+"!\nScore:"+a+" correct | "+b+" wrong\n";C();
}


# K, 155

k:l:0;
while[1;
1@(s:,/(($2?11),(1?"+-*"))0 2 1),"="; -1@*$[(.:s)="I"$0:0;("correct!";l+:1);("wrong!";k+:1)]; -1"Score: ",($l)," correct | ",($k)," wrong\n\n" ]  ## Haskell 286 import System.Random main=0?0 s=show a°b=s a++b r=randomRIO d=r(0,10) p=putStr c?w=do a<-d;b<-d;i<-r(0,2);let{(#)=[(+),(-),(*)]!!i;o="+-*"!!i};p(s a++o:b°"=");r<-getLine;let{u=fromEnum$read r/=a#b;d=c+1-u;v=w+u};p(["correct!\n","wrong!\n"]!!u);p("Score: "++d°" correct | "++v°" wrong\n\n");d?v


## VBA - 250

Sub t()
a=0
b=0
While 1
x=Int(Rnd()*11)
y=Int(Rnd()*11)
o=Int(Rnd()*3)
If InputBox(x & Array("+","-","*")(o) & y & "=")=Array(x+y,x-y,x*y)(o) Then r="Correct!":a=a+1 Else r="Wrong!":b=b+1
MsgBox r & vbCr & "Score:" & a & " correct|" & b & " wrong"
Wend
End Sub


Runs until the memory limit for the variables is reached, otherwise it runs 'forever'.