Ruby calling method in quick_sort gives wrong output - ruby

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!

Related

No implicit conversion of Integer into Array

I am doing a ruby challenege in leetcode where I have to remove duplicates in a array and return the array with unique values. I keep getting:
Line 55: no implicit conversion of Integer into Array (TypeError) in serializer__.rb (-)
and my answer is:
def remove_duplicates(nums)
nums.sort.each_with_index do |num,i|
if nums[i + 1].eql? num
nums.delete_at(i)
end
end
nums
end
I was not able to find a clear solution to what I need to do to resolve this. Please let me know what I need to do.
Working example
you need to re-read the question ... you have to replace the nums, and return the count of the remaining figures:
def remove_duplicates(nums)
nums.uniq!
nums.count
end
you have been returning the array, not the count of the array.
Adjustments to original code
to do it with your original code (note that the array should already be sorted, according to the question):
def remove_duplicates(nums)
nums.each_with_index do |num,i|
if nums[i + 1].eql? num
nums.delete_at(i)
end
end
nums.count
end
Working example with Unsorted initial array
if you wanted an answer that worked when the code is not sorted (which is not the case with your particular question, but a commenter seems to ask about this), and you need to generate a sorted unique array, overwriting the original array, and returning the size of the new array, you would need to do something like the following:
def remove_duplicates(nums)
nums.replace(nums.uniq.sort)
nums.count
end

How to solve fibonacci in ruby (HackerRank)

I am trying to solve a Fibonacci solution in HackerRanck.
I am mostly using the inject method.
I first declared an empty array.
I then define a method that takes in a parameter and turns it into a list that stores two initial values, 0 and 1.
The method then takes the last two values and sum them up together and returns the newly-formed list. (I hope I got this logic right)
I was then aiming at calling the method and loop through it this time around summing all the even values in it and returning the final result.
#!/bin/ruby
t = gets.strip.to_i
for a0 in (0..t-1)
n = gets.strip.to_i
end
result = 0
def fibbonacci num
(1..num).inject([0, 1]) { |fib| << fib.last(2).inject(:+)}
end
my_fib_num = fibbonacci n
for i in my_fib_num
if i % 2 == 0
result.inject(0){|sum,x| sum + x }
end
end```
Anything I could be getting wrong here?
I see you are doing unnecessary things over here and you are using inject in completely wrong way. The inject should always be called on an array or a range object. On every loop the result of the loop will be assigned to first parameter (i.e result in the example below) of the block and it will be passed back again to next loop. Finally returns the value in result.
The updated code:
#!/bin/ruby
t = gets.strip.to_i
def fibbonacci(num)
(1..num).inject([0, 1]) { |result| result << result.last(2).inject(:+)}
end
my_fib_num = fibbonacci(t)
result = my_fib_num.inject(:+)
Note: The solution is to solve by using inject.
Ref: https://apidock.com/ruby/Enumerable/inject
May be you can use select and inject together to some the even
t = gets.strip.to_i
def fibbonacci(num)
(1..num).inject([0, 1]) { |fib| fib << fib.last(2).inject(:+)}
end
my_fib_num = fibbonacci(t)
my_fib_num.keep_if{|d| d.even?}.inject(:+)

Is there a better way?: iterating over an array in 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.

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.

How to use less memory generating Array permutation?

So I need to get all possible permutations of a string.
What I have now is this:
def uniq_permutations string
string.split(//).permutation.map(&:join).uniq
end
Ok, now what is my problem: This method works fine for small strings but I want to be able to use it with strings with something like size of 15 or maybe even 20. And with this method it uses a lot of memory (>1gb) and my question is what could I change not to use that much memory?
Is there a better way to generate permutation? Should I persist them at the filesystem and retrieve when I need them (I hope not because this might make my method slow)?
What can I do?
Update:
I actually don't need to save the result anywhere I just need to lookup for each in a table to see if it exists.
Just to reiterate what Sawa said. You do understand the scope? The number of permutations for any n elements is n!. It's about the most aggressive mathematical progression operation you can get. The results for n between 1-20 are:
[1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600,
6227020800, 87178291200, 1307674368000, 20922789888000, 355687428096000,
6402373705728000, 121645100408832000, 2432902008176640000]
Where the last number is approximately 2 quintillion, which is 2 billion billion.
That is 2265820000 gigabytes.
You can save the results to disk all day long - unless you own all the Google datacenters in the world you're going to be pretty much out of luck here :)
Your call to map(&:join) is what is creating the array in memory, as map in effect turns an Enumerator into an array. Depending on what you want to do, you could avoid creating the array with something like this:
def each_permutation(string)
string.split(//).permutation do |permutaion|
yield permutation.join
end
end
Then use this method like this:
each_permutation(my_string) do |s|
lookup_string(s) #or whatever you need to do for each string here
end
This doesn’t check for duplicates (no call to uniq), but avoids creating the array. This will still likely take quite a long time for large strings.
However I suspect in your case there is a better way of solving your problem.
I actually don't need to save the result anywhere I just need to lookup for each in a table to see if it exists.
It looks like you’re looking for possible anagrams of a string in an existing word list. If you take any two anagrams and sort the characters in them, the resulting two strings will be the same. Could you perhaps change your data structures so that you have a hash, with keys being the sorted string and the values being a list of words that are anagrams of that string. Then instead of checking all permutations of a new string against a list, you just need to sort the characters in the string, and use that as the key to look up the list of all strings that are permutations of that string.
Perhaps you don't need to generate all elements of the set, but rather only a random or constrained subset. I have written an algorithm to generate the m-th permutation in O(n) time.
First convert the key to a list representation of itself in the factorial number system. Then iteratively pull out the item at each index specified by the new list and of the old.
module Factorial
def factorial num; (2..num).inject(:*) || 1; end
def factorial_floor num
tmp_1 = 0
1.upto(1.0/0.0) do |counter|
break [tmp_1, counter - 1] if (tmp_2 = factorial counter) > num
tmp_1 = tmp_2 #####
end # #
end # #
end # returns [factorial, integer that generates it]
# for the factorial closest to without going over num
class Array; include Factorial
def generate_swap_list key
swap_list = []
key -= (swap_list << (factorial_floor key)).last[0] while key > 0
swap_list
end
def reduce_swap_list swap_list
swap_list = swap_list.map { |x| x[1] }
((length - 1).downto 0).map { |element| swap_list.count element }
end
def keyed_permute key
apply_swaps reduce_swap_list generate_swap_list key
end
def apply_swaps swap_list
swap_list.map { |index| delete_at index }
end
end
Now, if you want to randomly sample some permutations, ruby comes with Array.shuffle!, but this will let you copy and save permutations or to iterate through the permutohedral space. Or maybe there's a way to constrain the permutation space for your purposes.
constrained_generator_thing do |val|
Array.new(sample_size) {array_to_permute.keyed_permute val}
end
Perhaps I am missing the obvious, but why not do
['a','a','b'].permutation.to_a.uniq!

Resources