How to do a simple test in ruby - ruby

I have some code below that gives square numbers. I also wrote a simple test that prints true or false.
numbers = (1..20)
test=numbers.each do |number|
puts number * number
end
puts test == [1,4,9,16,25,36,49,64,81,100,121,144,169,196,225,256,289,324,361,400]
I expect it to print true, but it puts false.
I was wondering if anyone could help to see why.

Try below code to get your answer :
numbers = (1..20)
test = numbers.map{|a| a*a}
puts test == [1,4,9,16,25,36,49,64,81,100,121,144,169,196,225,256,289,324,361,400]
You are using first test which contents 1..20. So you have to modify your code.

In your code numbers.each do |number| .. end returns the range (1..20) and that's the value that test will be assigned to after the loop through numbers is done. So even if you deleted the line puts number* number, test will still have the value (1..20). So using map would be the right choice to keep your values in an array. But you should first delete puts, because it shows the value on the screen but returns nil. So if you used map but didn't delete puts test will be assigned to an array of nils.

Related

In Ruby Why is the If/Then logic written without the If/Then structure failing?

Why does the following code fail to produce expected output, for the first two test cases if I don't add the "then" section to the the 'If?' I set the default value of the second variable "False" and I was under the impression that in Ruby a method could take an unspecified number of parameters, and the lack of a parameter when the method is called will roll back to using the default values of that parameters within the method if set.
def alphabetize(arr,rev=false)
arr.sort!
if rev == true
arr.reverse!
end
end
numbers = [1,9,2,1,10]
Test cases:
print alphabetize(numbers,false)
=begin
input: numbers,false
output: nil
expected output: 1,1,2,9,10
=end
print alphabetize(numbers)
=begin
input: numbers
output: nil
expected output 1,1,2,9,10
=end
print alphabetize(numbers,true)
=begin
input: numbers,true
output: 10,9,2,1,1
expected output: 10,9,2,1,1
=end
This code produced the expected results:
def alphabetize(arr,rev=false)
if rev == true
arr.sort!.reverse!
else
arr.sort!
end
end
numbers = [1,9,2,1,10]
You are printing the return value of the alphabetize method, which is not necessarily the value of the array.
In your first code, you have an if without a corresponding else as the last statement. In Ruby, the return value of an if statement without an else is nil, when the if condition fails.
In your second code, you have an if with an else statement. So the return value of the method, when the ifcondition fails, will be what gets executed inside the else block. In this case, arr.sort!.
It's worth mentioning the alphabetize method modifies the numbers array being passed in (indicated by the ! in the sort! and reverse! methods). If you printed numbers, instead of return value of alphabhetize, you would have the expected output as well.
def alphabetize(arr,rev=false)
arr.sort!
if rev == true
arr.reverse!
end
arr
end
Return array at the end when if false it return nil. To make sure the it returns the array value at the end of method.
Tested on rubyfiddle.com
http://rubyfiddle.com/riddles/c36bc/1

"n.times do" block just returns value of n

Judging by the answers to this question, I expected
#n.times do
"hello"
end
to return a number of "hello"s equal to the value of #n. However, no matter how I modify the code, my rails console just returns the value of #n and nothing more. What am I doing wrong?
For example, if I first set #n = 10, then the result of the code would just be 10.
Nope, I don't see how you inferred from those answers that .times block should return anything. What it does is it runs specified block specified number of times, nothing more. Return values of the block are discarded. Will do if you want to, say, print "hello" to standard output N times or do some other work.
n.times do
puts 'hello'
end
If you expected N copies of "hello" string in an array, then there are other ways to achieve this. For example:
Array.new(n, 'hello')
n.times.map { 'hello' }
# and many others
You are not printing anything. Try:
#n.times do
puts "hello"
end

Guessing game for ruby

I'm currently trying to create a simply made guessing game, In the code there will be three set number (for now) that a person has to guess. If he/she guesses all the numbers correctly it puts, "Congrats, you win!"
Now as a beginning test i just wanted the user to guess one number correctly and the code gives back correct or incorrect.
random_guess = [1, 3, 5]
puts "Please Pick a number, 1-5"
pick_num = gets.chomp
if pick_num == random_guess = true
puts "Correct!"
else
puts "Incorrect!"
end
(I know this code is very beginner, i'm very new to ruby.) for some reason every time i run this program it puts incorrect.
Your if statement is wrong. It should be:
if random_guess.include? pick_num.to_i
Note that if you leave off the to_i the equality check will always fail because you're comparing the integer 3 against the string "3".
Just to help you a bit more. Since your end goal is to have the user guess all the numbers correctly. You can just loop on the same if statement I wrote above. And every time they guess a correct number you can remove it from the array like such:
random_guess.delete(pick_num.to_i)
Once the array is empty, the user has won.
Making random_guess random:
random_guess = []
3.times{random_guess << rand(1..5)}
random_guess
# => [5, 1, 4] # will be random in every other iteration
Checking if the number exists, you can either use index or include?:
if random_guess.index(pick_num.to_i) # alternatively random_guess.index(pick_num.to_i)
puts "Correct!"
else
puts "Incorrect!"
end
Why is your code always printing incorrect?
You are doing if pick_num == random_guess = true, which is a blunder. What is actually happening here is:
you are assigning true to random_guess. i.e. irrespective to what value (Array) random_guess holds, you are overwriting it with true.
Then you are comparing random_guess with pick_num.
So essentially you are doing this:
if pick_num == (random_guess = true) # say pick_num = "1"
# "1" == true # which is obviously false.
The correct conditional statement should be:
if pick_num == random_guess
However this will also print false every time. Reason?
pick_num is a string.
random_guess is an array that contains integer values.
You are comparing two different object types. So its always false.
Therefore the right way to solve this is checking whether the user entered value exists in the Array. For that you can use Array#index or Array#include?. Hence the statement in my proposed solution:
if random_guess.index(pick_num.to_i)
NOTE: pick_num.to_i converts pick_num (a character) into an integer. This is required as your array contains only integers and not characters.

Coderbyte Second Great Low - code works but is rejected

I'm currently working through the Coderbyte series to get better at Ruby programming. Maybe this is just a bug in their site (I don't know), but my code works for me everywhere else besides on Coderbyte.
The purpose of the method is to return the 2nd smallest and the 2nd largest elements in any inputted array.
Code:
def SecondGreatLow(arr)
arr=arr.sort!
output=[]
j=1
i=(arr.length-1)
secSmall=''
secLarge=''
while output.length < 1
unless arr.length <= 2
#Get second largest here
while (j<arr.length)
unless arr[j]==arr[j-1]
unless secSmall != ''
secSmall=arr[j]
output.push(secSmall)
end
end
j+=1
end
#get second smallest here
while i>0
unless arr[i-1] == arr[i]
unless secLarge != ''
secLarge=arr[i-1]
output.push(secLarge)
end
end
i-=1
end
end
end
# code goes here
return output
end
# keep this function call here
# to see how to enter arguments in Ruby scroll down
SecondGreatLow(STDIN.gets)
Output
Input: [1,2,3,100] => Output: [2,3] (correct)
Input: [1,42,42,180] => Output: [42,42] (correct)
Input: [4,90] => Output: [90,4] (correct)
The problem is that I'm awarded 0 points and it tells me that my output was incorrect for every test. Yet, when I actually put any inputs in, it gives me the output that I expect. Can someone please assist with what the problem might be? Thanks!
Update
Thanks to #pjs answer below, I realized this could be done in just a few lines:
def SecondGreatLow(arr)
arr=arr.sort!.uniq
return "#{arr[1]} #{arr[-2]}"
end
# keep this function call here
# to see how to enter arguments in Ruby scroll down
SecondGreatLow(STDIN.gets)
It's important to pay close attention to the problem's specification. Coderbyte says the output should be the values separated by a space, i.e., a string, not an array. Note that they even put quotes around their "Correct Sample Outputs".
Spec aside, you're doing way too much work to achieve this. Once the array is sorted, all you need is the second element, a space, and the second-to-last element. Hint: Ruby allows both positive and negative indices for arrays. Combine that with .to_s and string concatenation, and this should only take a couple of lines.
If you are worried about non-unique numbers for the max and min, you can trim the array down using .uniq after sorting.
You need to check condition for when array contains only two elements. Here is the complete code:
def SecondGreatLow(arr)
arr.uniq!
arr.sort!
if arr.length == 2
sec_lowest = arr[1]
sec_greatest = arr[0]
else
sec_lowest = arr[1]
sec_greatest = arr[-2]
end
return "#{sec_lowest} #{sec_greatest}"
end

Storing output into a variable to be used in an array

A snippet of my code below flips a coin and outputs a result of 10 total heads or tails.
(e.g. Heads Tails Heads Tails...)
I'd like to store this into a variable where I can put it into an array and use its strings.
%w[act] only outputs the string "act". How can I get that line of code to output my array of strings from the line act = coin.flip?
Updated and added full code
class Coin
def flip
flip = 1 + rand(2)
if flip == 2
then puts "Heads"
else
puts "Tails"
end
end
end
array = []
10.times do
coin = Coin.new
array << coin.flip
end
puts array
This:
10.times do
coin = Coin.new
act = coin.flip
end
doesn't produce an array. It simply creates ten coin flips and throws them all away, the result of that expression is, in fact, 10. If you want an array, you'll need to build one.
You could take Douglas's approach or try something a bit more idiomatic.
The Integer#times method returns an enumerator so you can use any of the Enumerable methods on it rather than directly handing it a block. In particular, you could use collect to build an array in one nice short piece of code:
a = 10.times.collect { Coin.new.flip }
That gives you 10 flips in the Array a and then you can puts a or puts a.join(', ') or whatever you want.
The %w[] won't work because that's for generating an Array of whitespace separated words:
%w[] Non-interpolated Array of words, separated by whitespace
So %w[a b c] is just a nicer way of saying ['a', 'b', 'c'] and the words within %w[] are treated as single quoted strings rather than variables or method calls to be evaluated.
Seems that there is some editing going on. You'll also want to modify your flip method to return the flip rather than print it:
def flip
flip = 1 + rand(2)
if flip == 2
"Heads"
else
"Tails"
end
end
Then you'll get your Heads and Rails in the array.
Put the act results into an array.
arr = []
10.times do
coin = Coin.new
arr << coin.flip
end
p arr # => [...]

Resources