Is there a better way?: iterating over an array in ruby - ruby

I'm working on a mini project for a summer class. I'd like some feedback on the code I have written, especially part 3.
Here's the question:
Create an array called numbers containing the integers 1 - 10 and assign it to a variable.
Create an empty array called even_numbers.
Create a method that iterates over the array. Place all even numbers in the array even_numbers.
Print the array even_numbers.
Here's my code, so far:
numbers = [1,2,3,4,5,6,7,8,9,10]
print numbers[3]
even_numbers.empty?
def even_numbers
numbers.sort!
end

Rather than doing explicit iteration, the best way is likely Array#select thus:
even_numbers = numbers.select { |n| n.even? }
which will run the block given on each element in the array numbers and produce an array containing all elements for which the block returned true.

or an alternative solution following the convention of your problem:
def get_even_numbers(array)
even_num = []
array.each do |n|
even_num << n if n.even?
end
even_num
end
and of course going for the select method is always preferred.

Related

Ruby calling method in quick_sort gives wrong output

I am doing a quick sort in ruby and using quick_sort I am grabbing the last 3 elements of the array and multiplying it to get the value.
My quick sort works fine but only thing is when I call the my other method max_product_three in quick_search the sorted_array I pass into the method is only showing up as two random numbers like [-3,-2]. If I take out my method from quick_search it gives the correct output. What is happening that when I put my method the sorted array is wrong which is causing my max_product_three not to work.
quick_search.rb
def quick_search(array)
return array if array.length <= 1
len = array.length - 1
left = []
right = []
pivot = array.sample
array.delete_at(array.index(pivot))
array.each do |num|
if num < pivot
left << num
else
right << num
end
end
sorted = []
sorted << quick_search(left)
sorted << pivot
sorted << quick_search(right)
sorted_array = sorted.flatten
p sorted_array
max_product_three(sorted_array)
end
max_product_three.rb
def max_product_three(sorted_array)
len = sorted_array.length - 1
take_3 = len - 3
mulitple = sorted_array.drop(take_3)
p mulitple.inject(:*)
end
I am using this array as reference [-3,1,2,-2,5,6]
I assume you're writing this to learn how quick-sort works? Because ruby's got a #sort method right there... 😁
There are few things here. Is your intention to do two things: first, sort the array; second, multiply the three largest values in the sorted array? Because that's not what your code currently does. You call your max_product_three method from within your sort, which means it'll be called every time quick_sort is called.
Worse, it's the last line in the method. That means the result of calling max_product_three is what's returned each time you iterate, not the sorted array! So, for each sub-sort, what you get back is a single number instead of the sorted array.
Also, your max_product_three method multiplies the last 4 values, not the last 3 values. (You subtract 1 from its length and then subtract 3 from it, so you're dropping length - 4 values, leaving 4 values to multiply.)
You don't need to do p sorted_array at the end of your quick_search method (presumably, should be quick_sort!) but can just have sorted_array to return the array.
And, a smaller thing, your initial guard clause would be a bit better (and more ruby-ish) by not using an explicit operator, for example:
return array unless array.length.positive?
That's quite a lot, and I may have misinterpreted what you're trying to do here so let me know if I have!

Swap adjacent elements in array

I am trying to build a method in Ruby that will take in a string that has been split into an array of letters and then iterate through the array, swapping the element at index n with that at index n+1. The method will then join the new array into a string and push it to another array.
Here is an example of what I am looking to do:
string = "teh"
some_method(string)
some ruby magic here
array << new_string
end
Expected output:
["eth", "the"]
This is for a spell checker program I am writing for school. The method will check if letters in a misspelled word are swapped by checking to see if the output array elements are in the dictionary. If they are, it will return the word with that is most likely the correct word. I haven't had any luck finding articles or documentation on how to build such a method in ruby or on an existing method to do this. I've been tinkering with building this method for awhile now but my code isn't behaving anything like what I need. Thanks in advance!
As #Sergio advised, you want to use parallel assignment for this:
def reverse_em(str)
(0...str.size-1).map do |i|
s = str.dup
s[i], s[i+1] = s[i+1], s[i]
s
end
end
candidates = reverse_em "alogrithm"
#=> ["laogrithm", "aolgrithm", "algorithm", "alorgithm",
# "alogirthm", "alogrtihm", "alogrihtm", "alogritmh"]
dictionary_check(candidates)
#=> algorithm
# al·go·rithm
# noun \ˈal-gə-ˌri-thəm\
# a set of steps that are followed in order to solve a
# mathematical problem or to complete a computer process
Without splitting it into arrays then joining to new arrays (because that doesn't seem necessary):
def some_method(string)
swapped_strings = []
(0...string.size-1).each do |i|
temp_string = string.dup
temp_string[i], temp_string[i+1] = temp_string[i+1], temp_string[i]
swapped_strings << temp_string
end
swapped_strings
end

Ruby. Range:Each change value

I'm trying to write a siple script, that calculates fibonacci numbers in a loop:
def fib(v)
return v if v < 2
(fib(v-2) + fib(v-1))
end
[0..15].each do |i|
puts "#{fib(i-1)} "
end
But this code fails because i-1 cannot be executed, as i has type Range. What should I do with it? I know, there are many other ways to calculate fibonacci numbers, but I need this code to work, not to rewrite it.
Issue: [] is the syntax for creating an array. So [0..15] creates an array with one element. That one element is the Range, 0..15. Range itself is an enumerable, so you can:
(0..15).each do |i|
puts fibonacci(i - 1)
end
As a side note, using interpolating strings in unnecessary when you have just 1 element to print.

Iterating Over Multidimensional Arrays in Ruby

I'm going over iteration within multidimensional arrays in Ruby on Codecademy and came across a question I can't seem to find the answer to. So, in their example, they show that a multidimensional array can be iterated using the following code:
things = [[1,2,3], ["red", "blue"]]
things.each do |sub_array|
sub_array.each do |item|
puts item
end
end
This prints out the values of both sub_arrays. However, if I only want to display one sub_array, how would I go about that? I have tried the following code but I'm getting an undefined method `each' for 2:Fixnum error.
things = [[1,2,3], ["red", "blue"]]
things.each do |numbers, colors|
colors.each { |item| puts item }
end
So, I guess my question is why my code is not functioning correctly and how I would go about printing out only the array at index 1?
Your block parameters deconstruct the array as follows:
The enumerator generated by :each yields each element of the outer array in sequence, and then applies the pattern matching based on the structure of the block parameters. So in the first iteration, you have [1,2,3] yielded to the block, which is then mapped to numbers = 1 and colors = 2. 3 is ignored because it doesn't fit the pattern.
If you only want to display one sub-array, you don't need iterate over the whole array- just grab the required element by the index (if you know what the index is):
things[1].each {|color| ... }
Or, you can assign it to a variable in a similar way. As long as you know the colors will always be in the second position, you can do this:
_, colors = *things
colors.each {|color| ... }

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