Sort function using recursive logic [closed] - ruby

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 8 years ago.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Improve this question
I am trying to write the Array.sort method in my own way using recursive logic. My code is as follows:
def sorting_array(unsorted,sorted)
temp=unsorted
if unsorted.length==0
return sorted
elsif unsorted.length==1
return sorted.push(unsorted[0])
else
end
if unsorted[0]<=unsorted[1] # check the first position and add
sorted.push(unsorted.shift)
sorting_array(unsorted,sorted)
else # add the 0th element to the end to handle later
unsorted.push(unsorted.shift)
sorting_array(unsorted,sorted)
end
end
array=["pat","aog","cig","Zig","forse","erdvark", "aag"]
p sorting_array(array,[])
I appreciate any insight or input on where I am messing this up.

if unsorted[0]<=unsorted[1] #idea is to check the first position and add
sorted.push(unsorted.shift)
sorting_array(unsorted,sorted)
The problem comes here: you push unsorted[0] into sorted when unsorted[0] <= unsorted[1], no matter if unsorted[0] is the smallest in unsorted.
Try this: unsorted = [100, 101, 1, 2].

Your underlying algorithm is broken and will not produce a sorted array in all cases. Here's a simple counter example. These are arrays of strings of numbers. I'm just lazy and omitted the single/double quotes in the array definitions:
[2, 5, 0 ,4]
"2" <= "5" => true
[2] , [5, 0, 4]
"5" <= "0" => false
[2] , [0, 4, 5]
"0" <= "4" => true
[2, 0] , [4, 5]
"4" <= "5" => true
[2, 0, 4] , [5] <=== At this point your "sorted" array is clearly not sorted
Part of the problem is your code here:
if unsorted[0]<=unsorted[1]
sorted.push(unsorted.shift)
sorting_array(unsorted,sorted)
The if statement doesn't provide the kind of guarantee you need to push something into your sorted array.

Related

Ruby : Generate Random number in a range less one element [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
Folks,
I'm trying to generate a random number between (0..10) less, say, 5.
new_index = rand(0..(old_index - 1)) || new_index = rand((old_index + 1)..10)
Can anyone shed any light?
new_sample_space = (0..10).to_a - [5] #=> [0, 1, 2, 3, 4, 6, 7, 8, 9, 10]
new_index = new_sample_space.sample #=> random integer from 0-10, except 5
Of course, doing this with a large range is probably not a good idea because of memory concerns. In such "huge" cases, you could possibly just get another random number after you get 5.
loop do
new_index = rand(1..10)
break if new_index != 5
end

Efficient way of removing similar arrays in an array of arrays

I am trying to analyze some documents and find similarities in them. After analysis, I have an array, the elements of which are arrays of data from documents considered similar. But sometimes I have two almost similar elements, and naturally I want to leave the biggest of them. For simplification:
data = [[1,2,3,4,5,6], [7,8,9,10], [1,2,3,5,6]...]
How do I efficiently process the data that I get:
data = [[1,2,3,4,5,6], [7,8,9,10]...]
I suppose I could intersect every array, and if the intersected array matches one of the original arrays - I ignore it. Here is a quick code I wrote:
data = [[1,2,3,4,5,6], [7,8,9,10], [1,2,3,5,6], [7,9,10]]
cleaned = []
data.each_index do |i|
similar = false
data.each_index do |j|
if i == j
next
elsif data[i]&data[j] == data[i]
similar = true
break
end
end
unless similar
cleaned << data[i]
end
end
puts cleaned.inspect
Is this an efficient way to go? Also, the current behaviour only allows to leave out arrays that are a few elements short, and I might want to merge similar arrays if they occur:
[[1,2,3,4,5], [1,3,4,5,6]] => [[1,2,3,4,5,6]]
You can delete any element in the list if it is fully contained in another element:
data.delete_if do |arr|
data.any? { |a2| !a2.equal?(arr) && arr - a2 == [] }
end
# => [[1, 2, 3, 4, 5, 6], [7, 8, 9, 10]]
This is a bit more efficient than your suggestion since once you decide that an element should be removed, you don't check against it in the next iterations.

Why doesn't this algorithm yield the fibonacci sequence under 100? [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 9 years ago.
Improve this question
a = 1; b = 2
fibonacci = []
while fibonacci.length < 100
fibonacci.push(a)
fibonacci.push(b)
a = a + b; b = a + b
end
push fibonacci
The error message is "undefined method `push' for main:Obj"
You're trying to #push the array itself on the last line! :)
That's what it's complaining about. The push method is being invoked on the 'main' object, and push is not a Kernel method.
I'm guessing you mean puts. Otherwise it looks okay, if somewhat non-idiomatic. Naturally you can find lots of Ruby solutions for this problem on the site that might read a bit more clearly (see here for a recursive one.)
As others have said before the last line should be 'puts'
Also your numbers are wrong.
a = 1; b = 1
fibonacci = []
while fibonacci.length < 100
fibonacci << a
fibonacci << b
a += b
b += a
end
puts fibonacci
But also the fib starts at 1 and the the second element is also 1.
This make you sequence off, if you start at 1, 2
Fib = 1, 1, 2, 3, 5, 8, ...

Ruby sums of objects in array equal to zero [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
Write a method that finds if an array of numbers has a pair that sums to zero. Be careful of the case of zero; there needs to be two zeroes in the array to make a pair that sums to zero.
Below is the code that I wrote, but I know that it is wrong. I know that at some point it will be adding itself so if there is only one 0 in my array, then it will still return true. I am new to programming and Ruby so any advice will be really appreciated.
Thanks!
def has_zero?(array)
left, right = [-1,1]
lefter=[]
righter=[]
righter=array.each {|x| x+= array[right]}
lefter=array.each {|x| x+= array[left]}
if lefter.include?(0) || righter.include?(0)
return true
else return false
end
left,right = [left-1,right+1]
end
Ruby has some built-in methods that make this pretty easy:
def has_zero_sum_pair?(a)
a.permutation(2).any?{|pair| pair.inject(:+) == 0}
end
a.permutation(2) gives you every pair in a. any? returns true if the block ever returns true. inject(:+) is an easy way to get the sum of an array.
has_zero_sum_pair?([1, 2, 3])
# => false
has_zero_sum_pair?([1, 2, 3, -2])
# => true
has_zero_sum_pair?([1, 2, 3, 0])
# => false
has_zero_sum_pair?([0, 1, 2, 3, 0])
# => true
Update: If I didn't know about Array#permutation and had to accomplish this in the first way that came to mind, or if I was concerned about performance, I'd probably do something like this:
def has_zero_sum_pair2?(a)
(0..a.length-2).each do |i|
(i+1..a.length-1).each do |j|
return true if a[i] + a[j] == 0
end
end
false
end
I find that uglier and more error-prone, and it took longer to write. But it's about four times faster with small arrays and 10 times faster for larger arrays. It's typical in programming to have an easy way that works well enough in most cases but isn't ideal in performance. Sometimes better performance can be attained without costing clarity by choosing a better algorithm or data structure. Often a trade-off has to be made.
Update 2: If I really cared about performance, I'd use #FMc's technique. That's a great example of using a better data structure and algorithm for huge performance gains.
This works except for zero.
[1, 2, 3, -2]
.uniq.group_by(&:abs).any?{|_, tuple| tuple.length == 2}
# => true
array = [1,2,3,-2,0,0]
array.any?{|a| array.rindex(-a) > array.index(a)}
Check to see if the negative of any item is further to the right in the array. (rindex finds the index of the last occurance in the array.)
This problem calls for a Hash.
vals = [0, 4, 3, 0, -3, 2, -2, 1, 3, -4, -4]
# Our hash:
# groups[X] = Array of vals equal to X
groups = vals.group_by { |v| v }
# Just check whether the hash contains a pair
# of keys X and -X, or whether the original array
# had more than one zero in it.
p groups.any? { |k, vs| k == 0 ? vs.size > 1 : groups.has_key?(-k) }
You can generalize to any target sum by changing the test slightly:
k == target / 2 ? vs.size > 1 : groups.has_key?(target - k)

Ruby: how to know depth of multidemensional array

This is my problem I have met in my assignment.
Array A has two elements: array B and array C.
Array B has two elements: array D and array E
At some point, array X just contains two elements: string a and string b.
I don't know how to determine how deep array A is. For example:
arrA = [
[
[1,2]
]
]
I have tested by: A[0][0][0] == nil which returns false. Moreover, A[0][0]..[0] == nil always returns false. So, I cannot do this way to know how deep array A is.
If this is not what you're looking for, it should be a good starting point:
def depth (a)
return 0 unless a.is_a?(Array)
return 1 + depth(a[0])
end
> depth(arrA)
=> 3
Please note that this only measures the depth of the first branch.
My solution which goes below answers the maximum depth of any array:
Example: for arr=[ [[1],[2,3]], [[[ 3,4 ]]] ], the maximum depth of arr is 4 for 3,4.
Aprroach - flatten by one level and compare
b, depth = arr.dup, 1
until b==arr.flatten
depth+=1
b=b.flatten(1)
end
puts "Array depth: #{depth}" #=> 4
Hope it answers your question.
A simple pure functional recursive solution:
def depth(xs, n=0)
return case
when xs.class != Array
n
when xs == []
n + 1
else
xs.collect{|x| depth x, n+1}.max
end
end
Examples:
depth([]) == 1
depth([['a']])) == 2
depth([1, 2, 3, 4, [1, 2, 3, [[2, 2],[]], 4, 5, 6, 7], 5, 5, [[[[[3, 4]]]]], [[[[[[[[[1, 2]]]]]]]]]]) == 10
Here's a one-liner similar to kiddorails' solution extracted into a method:
def depth(array)
array.to_a == array.flatten(1) ? 1 : depth(array.flatten(1)) + 1
end
It will flatten the array 1 dimension at the time until it can't flatten anymore, while counting the dimensions.
Why is this better than other solutions out there?
doesn't require modification to native classes (avoid that if possible)
doesn't use metaprogramming (is_a?, send, respond_to?, etc.)
fairly easy to read
works on hashes as well (notice array.to_a)
actually works (unlike only checking the first branch, and other silly stuff)
Also one line code if you want to use
def depth (a)
a.to_s.count("[")
end

Resources