How to multiply the elements of an array using array#each? - ruby

I am trying to write a method which takes as its input an array of integers and returns their product. For example:
product([1,2,3]) # returns 6
I need to do this using Array#each and not the inject method. This is what I have come up with, but it seems to be incorrect:
def product(array)
final = 0.0
array.each do |i|
final *= i
end
return final
end
Also, how could I modify this method to return the product of all the odd integers in the array, such that
product([1,2,3]) # returns 3, because 2 is even
product([0,-1,-10]) # returns -1, because 0 and -10 are even

As Ramon said, just initialize final to 1.0:
def product(array)
final = 1.0
array.each { |i| final *= i }
final
end
However, in idiomatic Ruby:
[1, 2, 3].inject(:*)

def find_product(x)
return x.inject(&:*)
end
x = [5, 6, 7, 10, 15, 18, 32]
find_product(x)

arr = [1,2,3,4,5]
First
for i in arr
a=i
for j in arr
a *=j
end
p a
end
Second
for i in arr
p product = arr.inject(i , :*)
end

def product(array)
final = 1.0
array.each do |i|
final *= i
end
final
end

Related

generalize map and reduce lab

I'm working on a lab Using a generalized map method to pass an element and block through returning multiple outcomes.
Really struggled on this one. Found some responses but they don't really make sense to me.
Here is the code:
def map(s)
new = []
i = 0
while i < s.length
new.push(yield(s[i]))
i += 1
end
new
end
Here's is the test:
it "returns an array with all values made negative" do
expect(map([1, 2, 3, -9]){|n| n * -1}).to eq([-1, -2, -3, 9])
end
it "returns an array with the original values" do
dune = ["paul", "gurney", "vladimir", "jessica", "chani"]
expect(map(dune){|n| n}).to eq(dune)
end
it "returns an array with the original values multiplied by 2" do
expect(map([1, 2, 3, -9]){|n| n * 2}).to eq([2, 4, 6, -18])
end
it "returns an array with the original values squared" do
expect(map([1, 2, 3, -9]){|n| n * n}).to eq([1, 4, 9, 81])
end
end
I don't get how the above code can give you these 4 different results.
Could someone help me understand it ?
Thank you for your help!
How your method map works
To see how your method operates let's modify your code to add some intermediate variables and some puts statements to show the values of those variables.
def map(s)
new = []
i = 0
n = s.length
puts "s has length #{n}"
while i < n
puts "i = #{i}"
e = s[i]
puts " Yield #{e} to the block"
rv = yield(e)
puts " The block's return value is #{rv}. Push #{rv} onto new"
new.push(rv)
puts " new now equals #{new}"
i += 1
end
puts "We now return the value of new"
new
end
Now let's execute the method with one of the blocks of interest.
s = [1, 2, 3, -9]
map(s) { |n| n * 2 }
#=> [2, 4, 6, -18] (return value of method)
The following is displayed.
s has length 4
i = 0
Yield 1 to the block
The block's return value is 2. Push 2 onto new
new now equals [2]
i = 1
Yield 2 to the block
The block's return value is 4. Push 4 onto new
new now equals [2, 4]
i = 2
Yield 3 to the block
The block's return value is 6. Push 6 onto new
new now equals [2, 4, 6]
i = 3
Yield -9 to the block
The block's return value is -18. Push -18 onto new
new now equals [2, 4, 6, -18]
We now return the value of new
It may by of interest to execute this modified method with different values of s and different blocks.
A replacement for Array#map?
Is this a replacement for Array#map (or Enumerable#map, but for now let's just consider Array#map)? As you defined it at the top level your map is an instance method of the class Object:
Object.instance_methods.include?(:map) #=> true
It must be invoked map([1,2,3]) { |n| ... } whereas Array#map is invoked [1,2,3].map { |n| ... }. Therefore, for your method map to be a replacement for Array#map you need to define it as follows.
class Array
def map
new = []
i = 0
while i < length
new.push(yield(self[i]))
i += 1
end
new
end
end
[1, 2, 3, -9].map { |n| n * 2 }
#=> [2, 4, 6, -18]
Simplify
We can simplify this method as follows.
class Array
def map
new = []
each { |e| new << yield(e) }
new
end
end
[1, 2, 3, -9].map { |n| n * 2 }
#=> [2, 4, 6, -18]
or, better:
class Array
def map
each_with_object([]) { |e,new| new << yield(e) }
end
end
See Enumerable#each_with_object.
Note that while i < length is equivalent to while i < self.length, because self., if omitted, is implicit, and therefore redundant. Similarly, each { |e| new << yield(e) } is equivalent to self.each { |e| new << yield(e) } and each_with_object([]) { ... } is equivalent to self.each_with_object([]) { ... }.
Are we finished?
If we examine the doc Array#map carefully we see that there are two forms of the method. The first is when map takes a block. Our method Array#map mimics that behaviour and that is the only behaviour needed to satisfy the given rspec tests.
There is a second form, however, where map is not given a block, in which case it returns an enumerator. That allows us to chain the method to another. For example (with Ruby's Array#map),
['cat', 'dog', 'pig'].map.with_index do |animal, i|
i.even? ? animal.upcase : animal
end
#=> ["CAT", "dog", "PIG"]
We could modify our Array#map to incorporate this second behaviour as follows.
class Array
def map
if block_given?
each_with_object([]) { |e,new| new << yield(e) }
else
to_enum(:map)
end
end
end
[1, 2, 3, -9].map { |n| n * 2 }
#=> [2, 4, 6, -18]
['cat', 'dog', 'pig'].map.with_index do |animal, i|
i.even? ? animal.upcase : animal
end
#=> ["CAT", "dog", "PIG"]
See Kernel#block_given? and Object#to_enum.
Notes
You might use, say, arr, rather than s as the variable holding the array, as s often denotes a string, just as h typically denotes a hash. One generally avoids names for variables and custom methods that are the names of core Ruby methods. That is also an objection to your use of new as a variable name, as there are many core methods named new.

Function with arrays as a parameter

How can I write a Ruby function that can calculate the average of an array? If the array doesn't have any elements, the result should be 0. I should use a loop for the implementation. I started like this, but I'm not quite sure how to use the loop.
a = [1, 2, 3, 4, 5, 6]
def average(a)
sum = 0.0
result = 0.0
if array.length > 0 then
array.each do |item|
sum += item
end
result = sum / array.length
end
return result.to_f
end
def average(arr, precision=0)
return 0 if arr.empty?
arr.sum.fdiv(arr.size).round(precision)
end
arr = [1,2,3,7]
average(arr) #=> 3
average(arr,2) #=> 3.25
Rather than using Integer#fdiv you could write
(arr.sum.to_f/arr.size).round(precision)
I suppose we can also write it simply as below
a = [1, 2, 3, 4, 5, 6]
def average(arr=[])
sum = 0.0
i=0
while(i < arr.length) do
sum += arr[i].to_f
i += 1
end
return ((i==0) ? 0 : (sum / i))
end
We can loop and calculate sum this way. Afterwards for average we took value of i which will be retained value after loop and make conditional operator for returning result.
Its simple solution, I have not tested it though so can have mistakes. You can try on your side. Hope This helps !!
You can write this:
def average(values)
total = 0.0
values.each do |i|
total += i
end
return total / values.length()
end
If you want to use a loop, you can do it this way:
def average(values=[])
total = 0.0
for i in values
total += i
end
return total / values.length()
end
If a non-empty array is passed, it will return the average of the values. If an empty array is passed, it will return 0.0.
You can test it like this:
puts average([1, 2, 3, 4, 5]) #=> "3"
puts average([]) #=> "0"
def average(a)
if a.empty?
0
else
sum = a.inject(0.0){|x, sum| sum += x}
sum / a.size.to_f
end
end

Ruby code looping infinitely

class Triplet
def initialize(array,sum)
#array = array.sort()
#array_size = array.size()
#sum = sum
#result = []
end
def get_triplet
#array[0..-3].each_with_index do |arr, ind|
pointer_one = ind + 1
pointer_two = #array_size - 1
while (pointer_one < pointer_two)
temp_sum = #array[pointer_one] + #array[pointer_two] + arr
if(temp_sum == #sum)
#result.push([#array[pointer_one], #array[pointer_two], arr])
elsif temp_sum < #sum
pointer_one = pointer_one +1
else
pointer_two = pointer_two -1
end
end
end
end
def get_result
#result.each do |res|
puts res
end
end
end
puts "Enter the array of numbers"
array = gets.chomp
array = array.split(' ')
array_integer = array.map{|a| a.to_i}
puts array_integer
puts "Enter the sum"
sum = gets.chomp
puts sum
t1 = Triplet.new(array_integer,sum.to_i)
t1.get_triplet
t1.get_result
Can anyone suggest me the fix so that it doesn't loop infinitly. It is program to find triplet in array whose sum is #sum. Its looping in get_triplet method. Initialize method sets the array,array size. get_triplet method should store all three number whose sum is #sum in result array.
Usually a tangle of code like this is a sign something's not right, and in this case the source of the problem is not knowing about the combination method. Here's a functionally equivalent solution:
def triplet(list, target)
list.combination(3).find do |a,b,c|
a + b + c == target
end
end
For example:
arr = [ 1, 2, 3, 4, 5, 6, 7, 8 ]
p triplet(arr, 6)
# => [1, 2, 3]
p triplet(arr, 4)
# => nil
p triplet(arr, 10)
# => [1, 2, 7]
The algorithm used in your code looks problematic, or at least implemented incorrectly, and is also strictly limited to triplets. This code is far more generic and uses a proven, tested algorithm, so it's probably better suited to solving your particular problem.

Find all indices of a substring within a string

I want to be able to find the index of all occurrences of a substring in a larger string using Ruby. E.g.: all "in" in "Einstein"
str = "Einstein"
str.index("in") #returns only 1
str.scan("in") #returns ["in","in"]
#desired output would be [1, 6]
The standard hack is:
indices = "Einstein".enum_for(:scan, /(?=in)/).map do
Regexp.last_match.offset(0).first
end
#=> [1, 6]
def indices_of_matches(str, target)
sz = target.size
(0..str.size-sz).select { |i| str[i,sz] == target }
end
indices_of_matches('Einstein', 'in')
#=> [1, 6]
indices_of_matches('nnnn', 'nn')
#=> [0, 1, 2]
The second example reflects an assumption I made about the treatment of overlapping strings. If overlapping strings are not to be considered (i.e., [0, 2] is the desired return value in the second example), this answer is obviously inappropriate.
This is a more verbose solution which brings the advantage of not relying on a global value:
def indices(string, regex)
position = 0
Enumerator.new do |yielder|
while match = regex.match(string, position)
yielder << match.begin(0)
position = match.end(0)
end
end
end
p indices("Einstein", /in/).to_a
# [1, 6]
It outputs an Enumerator, so you could also use it lazily or just take the n first indices.
Also, if you might need more information than just the indices, you could return an Enumerator of MatchData and extract the indices:
def matches(string, regex)
position = 0
Enumerator.new do |yielder|
while match = regex.match(string, position)
yielder << match
position = match.end(0)
end
end
end
p matches("Einstein", /in/).map{ |match| match.begin(0) }
# [1, 6]
To get the behaviour described by #Cary, you could replace the last line in block by position = match.begin(0) + 1.
#Recursive Function
def indexes string, sub_string, start=0
index = string[start..-1].index(sub_string)
return [] unless index
[index+start] + indexes(string,sub_string,index+start+1)
end
#For better Usage I would open String class
class String
def indexes sub_string,start=0
index = self[start..-1].index(sub_string)
return [] unless index
[index+start] + indexes(sub_string,index+start+1)
end
end
This way we can call in this way: "Einstein".indexes("in") #=> [1, 6]

Looping through an array with step

I want to look at every n-th elements in an array. In C++, I'd do this:
for(int x = 0; x<cx; x+=n){
value_i_care_about = array[x];
//do something with the value I care about.
}
I want to do the same in Ruby, but can't find a way to "step". A while loop could do the job, but I find it distasteful using it for a known size, and expect there to be a better (more Ruby) way of doing this.
Ranges have a step method which you can use to skip through the indexes:
(0..array.length - 1).step(2).each do |index|
value_you_care_about = array[index]
end
Or if you are comfortable using ... with ranges the following is a bit more concise:
(0...array.length).step(2).each do |index|
value_you_care_about = array[index]
end
array.each_slice(n) do |e, *_|
value_i_care_about = e
end
Just use step() method from Range class which returns an enumerator
(1..10).step(2) {|x| puts x}
We can iterate while skipping over a range of numbers on every iteration e.g.:
1.step(10, 2) { |i| print "#{i} "}
http://www.skorks.com/2009/09/a-wealth-of-ruby-loops-and-iterators/
So something like:
array.step(n) do |element|
# process element
end
class Array
def step(interval, &block)
((interval -1)...self.length).step(interval) do |value|
block.call(self[value])
end
end
end
You could add the method to the class Array
What about:
> [1, 2, 3, 4, 5, 6, 7].select.each_with_index { |_,i| i % 2 == 0 }
=> [1, 3, 5, 7]
Chaining of iterators is very useful.
This is a great example for the use of the modulo operator %
When you grasp this concept, you can apply it in a great number of different programming languages, without having to know them in and out.
step = 2
["1st","2nd","3rd","4th","5th","6th"].each_with_index do |element, index|
puts element if index % step == 1
end
#=> "2nd"
#=> "4th"
#=> "6th"

Resources