Hi there,
I'm a relative newbie when it comes to scripting in ruby however, for a year 11 project at school, it is necesary for me to program a maths utilit which requests a user - elementary school aged - to add to numbers together to reach an answer. I've effected some coding however, I'm a little stumpt as to why the aplet is not correctly parsing through the loops.
===script extract starts==
question = 1
unless question == 20
score = 0
number_of_questions = 0
num1 = rand(20)
num2 = rand(20)
correct_answer = num1 + num2
puts("What is #{num1} + #{num2}/?")
user_answer = gets.chomp!.to_i
unless user_answer == correct_answer
puts("Sorry, that is not correct. Please try again.")
user_answer = gets.chomp!.to_i
end
score += 1
number_of_questions += 1
question += 1
puts("Well done! That is correct.\nYou have answered #{score} out of #{number_of_questions} questions correctly.")
end
exit
===script extract ends===
Cheers,
Hayden
What loops? I don't see any loops in there at all. I see two
conditionals ("unless question == 20" and "unless user_answer ==
correct_answer") but no loops.
That might be a clue.
···
On Thu, 2008-05-08 at 19:27 +0900, Hayden Smith wrote:
Hi there,
I'm a relative newbie when it comes to scripting in ruby however, for a year 11 project at school, it is necesary for me to program a maths utilit which requests a user - elementary school aged - to add to numbers together to reach an answer. I've effected some coding however, I'm a little stumpt as to why the aplet is not correctly parsing through the loops.
===script extract starts==
question = 1
unless question == 20
score = 0
number_of_questions = 0
num1 = rand(20)
num2 = rand(20)
correct_answer = num1 + num2
puts("What is #{num1} + #{num2}/?")
user_answer = gets.chomp!.to_i
unless user_answer == correct_answer
puts("Sorry, that is not correct. Please try again.")
user_answer = gets.chomp!.to_i
end
score += 1
number_of_questions += 1
question += 1
puts("Well done! That is correct.\nYou have answered #{score} out of #{number_of_questions} questions correctly.")
end
exit
===script extract ends===
--
Michael T. Richter <ttmrichter@gmail.com> (GoogleTalk:
ttmrichter@gmail.com)
The only reason some people get lost in thought is because it's
unfamiliar territory. (Paul Fix)
I dont want to go through it all, so just a few hints:
puts("What is #{num1} + #{num2}/?")
No need for the () here.
Also the / before the ? seems confusing. Maybe omit it.
The
exit
also seems superfluous. Maybe omit it.
My favourite loop in ruby is this:
loop {
# do something here... alter condition, and then finally
break if condition
}
But maybe you meant to use a while
I personally think "until" is not a good name for use here.
···
--
Posted via http://www.ruby-forum.com/.
Hi Hayden,
I hope the following answers are helpful. The idiom that you'd be looking to use in your code would be:
score = 0
1..20.each do |question|
# do stuff
end
where you keep track of the score yourself as part of do stuff. Although I prefer the form:
1..20.inject(0) |sum, question|
# do stuff
sum += some_condition ? 1 : 0
end
but that requires that the last expression in the block be the one that increments the sum variable. Extra marks if you can write the block without using any local variables ![]()
Ellie
Eleanor McHugh
Games With Brains
http://slides.games-with-brains.net
···
On 8 May 2008, at 11:27, Hayden Smith wrote:
Hi there,
I'm a relative newbie when it comes to scripting in ruby however, for a year 11 project at school, it is necesary for me to program a maths utilit which requests a user - elementary school aged - to add to numbers together to reach an answer. I've effected some coding however, I'm a little stumpt as to why the aplet is not correctly parsing through the loops.
===script extract starts==
question = 1
unless question == 20
score = 0
number_of_questions = 0
num1 = rand(20)
num2 = rand(20)
correct_answer = num1 + num2
puts("What is #{num1} + #{num2}/?")
user_answer = gets.chomp!.to_i
unless user_answer == correct_answer
puts("Sorry, that is not correct. Please try again.")
user_answer = gets.chomp!.to_i
end
score += 1
number_of_questions += 1
question += 1
puts("Well done! That is correct.\nYou have answered #{score} out of #{number_of_questions} questions correctly.")
end
exit
----
raise ArgumentError unless @reality.responds_to? :reason
which of course should be:
1..20.inject(0) |sum, question|
#do stuff
sum + (some_condition ? 1 : 0)
end
as the whole point of inject is that it does the assignment for you...
I really must stick to this rule of no coding before my second cup of tea of the day ![]()
Ellie
Eleanor McHugh
Games With Brains
http://slides.games-with-brains.net
···
On 8 May 2008, at 12:07, Eleanor McHugh wrote:
1..20.inject(0) |sum, question|
# do stuff
sum += some_condition ? 1 : 0
end
----
raise ArgumentError unless @reality.responds_to? :reason
My apologies for misuse of terminology: Those two conditionals are the particular elements that I speak of.
···
----- Original Message -----
From: Michael T. Richter
To: ruby-talk ML
Sent: Thursday, May 08, 2008 8:41 PM
Subject: Re: initial stages of scripting
On Thu, 2008-05-08 at 19:27 +0900, Hayden Smith wrote:
Hi there,
I'm a relative newbie when it comes to scripting in ruby however, for a year 11 project at school, it is necesary for me to program a maths utilit which requests a user - elementary school aged - to add to numbers together to reach an answer. I've effected some coding however, I'm a little stumpt as to why the aplet is not correctly parsing through the loops.
===script extract starts==
question = 1
unless question == 20
score = 0
number_of_questions = 0
num1 = rand(20)
num2 = rand(20)
correct_answer = num1 + num2
puts("What is #{num1} + #{num2}/?")
user_answer = gets.chomp!.to_i
unless user_answer == correct_answer
puts("Sorry, that is not correct. Please try again.")
user_answer = gets.chomp!.to_i
end
score += 1
number_of_questions += 1
question += 1
puts("Well done! That is correct.\nYou have answered #{score} out of #{number_of_questions} questions correctly.")
end
exit
===script extract ends===
What loops? I don't see any loops in there at all. I see two conditionals ("unless question == 20" and "unless user_answer == correct_answer") but no loops.
That might be a clue.
--
Michael T. Richter <ttmrichter@gmail.com> (GoogleTalk: ttmrichter@gmail.com)
The only reason some people get lost in thought is because it's unfamiliar territory. (Paul Fix)
Hi Ellie,
Thanks for the suggestions, but as is evident from this code - I believe - I am a relative newbie and therefore, the logic behind this - at this point - is beyond me. Oh well, back to the bottom of the class for me.
Cheers
···
----- Original Message ----- From: "Eleanor McHugh" <eleanor@games-with-brains.com>
To: "ruby-talk ML" <ruby-talk@ruby-lang.org>
Sent: Thursday, May 08, 2008 9:07 PM
Subject: Re: initial stages of scripting
On 8 May 2008, at 11:27, Hayden Smith wrote:
Hi there,
I'm a relative newbie when it comes to scripting in ruby however, for a year 11 project at school, it is necesary for me to program a maths utilit which requests a user - elementary school aged - to add to numbers together to reach an answer. I've effected some coding however, I'm a little stumpt as to why the aplet is not correctly parsing through the loops.
===script extract starts==
question = 1
unless question == 20
score = 0
number_of_questions = 0
num1 = rand(20)
num2 = rand(20)
correct_answer = num1 + num2
puts("What is #{num1} + #{num2}/?")
user_answer = gets.chomp!.to_i
unless user_answer == correct_answer
puts("Sorry, that is not correct. Please try again.")
user_answer = gets.chomp!.to_i
end
score += 1
number_of_questions += 1
question += 1
puts("Well done! That is correct.\nYou have answered #{score} out of #{number_of_questions} questions correctly.")
end
exitHi Hayden,
I hope the following answers are helpful. The idiom that you'd be looking to use in your code would be:
score = 0
1..20.each do |question|
# do stuff
endwhere you keep track of the score yourself as part of do stuff. Although I prefer the form:
1..20.inject(0) |sum, question|
# do stuff
sum += some_condition ? 1 : 0
endbut that requires that the last expression in the block be the one that increments the sum variable. Extra marks if you can write the block without using any local variables
Ellie
Eleanor McHugh
Games With Brains
http://slides.games-with-brains.net
----
raise ArgumentError unless @reality.responds_to? :reason
Hi,
If I were to pursue this line of logic, how would I allow the break to have two conditions to opperate on? For example, in my first nested loop, I wished to test for the equality of user_answer and correct_answer as well as - this was not included due to my ignorance - a comparison to only continue the loop - regardless whether the two previous were correct - but only whilst looper != 3.
Cheers,
Hayden
···
----- Original Message ----- From: "Marc Heiler" <shevegen@linuxmail.org>
Newsgroups: comp.lang.ruby
To: "ruby-talk ML" <ruby-talk@ruby-lang.org>
Sent: Thursday, May 08, 2008 8:48 PM
Subject: Re: initial stages of scripting
I dont want to go through it all, so just a few hints:
puts("What is #{num1} + #{num2}/?")
No need for the () here.
Also the / before the ? seems confusing. Maybe omit it.The
exit
also seems superfluous. Maybe omit it.My favourite loop in ruby is this:
loop {
# do something here... alter condition, and then finally
break if condition
}But maybe you meant to use a while
I personally think "until" is not a good name for use here.
--
Posted via http://www.ruby-forum.com/\.
Well I didn't want to ruin your homework assignment for you so I sort of dodged around your actual task. Apologies if the following breaks that rule, but getting the hang of basic loops etc. is a fundamental if you want to really enjoy programming.
If I lay out your code to better reflect the logical structure it looks like this:
question = 1
unless question == 20
score = 0
number_of_questions = 0
num1 = rand(20)
num2 = rand(20)
correct_answer = num1 + num2
puts("What is #{num1} + #{num2}/?")
user_answer = gets.chomp!.to_i
end
score += 1
number_of_questions += 1
question += 1
puts("Well done! That is correct.\nYou have answered #{score} out of #{number_of_questions} questions correctly.")
end
exit
Clearly there's either a fragment missing at the very start which would matches with the final 'end' statement, or else your first 'end' statement is an erroneous inclusion. This is one of the reasons for laying out code with clear indentation - it makes the logic flow glaringly obvious.
It would make sense to put some kind of loop statement at the start otherwise there will be no repetition. With this inclusion what you have is a classic example of what's known as a sentinel guarded loop. You have a sentinel value (in this case 20) and an accumulator 'question' which changes value with each loop iteration until it reaches a specified value. The way in which you would handle this in a traditional procedural language such as BASIC would be to write a code fragment of this form:
FOR QUESTION = 1 TO 20
num1 = RND(20)
num2 = RND(20)
correct_answer = num1 + num2
REM read the value from the keyboard
REM compare the result and do some stuff
REM etc.
END
In Ruby it's more natural for these kinds of problems to use a Range object (because Ruby is object-oriented) and then enumerate across it:
questions = 1..20 # this creates an instance of the Range 1 through 20
questions.each do |question|
# actions to do for the question asked
end
but you can also use a more procedural style:
questions = 1..20 # this creates an instance of the Range 1 through 20
for question in questions
# actions to do for the question asked
end
and either form would provide the loop that you need to ask the user for their answer to successive questions.
If you then study the actions that you're taking in your code and consider the actual logic of what you're trying to achieve you'll notice that the score generated will be incorrect. This is where my suggestion of enumerating a Range object using the inject() method rather that each() becomes relevant:
questions = 1..20 # this creates an instance of the Range 1 through 20
questions.inject(0) do |sum, question|
#do stuff
sum + (some_condition ? 1 : 0)
end
The 'sum' parameter to the block acts as an accumulator and for each element in the range 'questions' whatever the final expression of the code block evaluates to will be the value stored in 'sum'. Once all elements have been enumerated, the value in 'sum' is then returned by inject() as the value of the expression. So for example:
numbers = 1..20
result = numbers.inject(0) do |sum, number|
sum + number
end
would set 'result' to 210, which is the sum of the first twenty integers. The way in which this then applies to your problem:
questions = 1..20 # this creates an instance of the Range 1 through 20
correct_answers = questions.inject(0) do |sum, question|
#do stuff
sum + (condition_for_correct_answer ? 1 : 0)
end
The use of the ternary logic operator is compact but for more complex behaviour a clearer formulation would be:
correct_answers = questions.inject(0) do |sum, question|
#do stuff
sum + if condition_for_correct_answer ? then
# print some stuff
1
else
# print some other stuff
0
end
end
which takes advantage of the fact that 'if' is also an expression and will return a value which can be used directly. In languages where 'if' is a statement (and hence does not return a value itself) the logic would look more like:
correct_answers = 0
questions.each do |question|
#do stuff
if condition_for_correct_answer ? then
# print some stuff
correct_answers += 1
else
# print some other stuff
correct_answers += 0
end
end
which is also valid Ruby.
And if that's not baffled you completely, you'll be well on your way to Ruby mastery ![]()
Ellie
Eleanor McHugh
Games With Brains
http://slides.games-with-brains.net
···
On 8 May 2008, at 12:36, Hayden Smith wrote:
Hi Ellie,
Thanks for the suggestions, but as is evident from this code - I believe - I am a relative newbie and therefore, the logic behind this - at this point - is beyond me. Oh well, back to the bottom of the class for me.
Cheers
----
raise ArgumentError unless @reality.responds_to? :reason