Need to make this more Ruby-like - ruby

I'm new to Ruby and I seem to be comfortable using while loops. But I would like to simplify my code by possibly using the 'each' method. How would I do this for this particular block of code?
sum_array = []
i = 0
while i < array.length - 1
j = i + 1
while j < array.length
sum = array[i] + array[j]
if sum != 0
sum_array << sum
end
j += 1
end
i += 1
end

sum_array = array.combination(2).map{|n, m| n + m}.reject(&:zero?)

array = (1..10).to_a # test array [1,2,3,4,....10]
sum_array = []
(0...array.length).each do |i| # from 0 to array.length-1
(i+1...array.length).each do |j| # from i+1 to array.length-1
sum = array[i] + array[j]
sum_array << sum unless sum == 0 # brief condition
end
end

def sum_array(input)
[].tap do |sums|
input.each_with_index do |x, index|
tail = input[index.next..-1]
tail.each do |y|
sum = x + y
sums << sum unless sum.zero?
end
end
end
end
puts sum_array([1,2,0,0])
# => [3,1,1,2,2]

You could do this:
sum_array = []
array.each_index do |i|
sum_array += (i+1...array.length).collect { |j| array[i] + array[j] }
end
sum_array.reject!(&:zero?)

Related

How to create a bubble sort of a double-linked list for Ruby

I have been implementing a bubble sort for a doubly linked list:
def sort2(list) #bubble sort
for i in 0...list.length
for j in 0...list.length-1-i
if list.get(j+1)<list.get(j)
list.swap(j+1, j)
end
end
end
end
I don't have any idea how implement a bucket-sort. We can only use methods like:
get(i) - which return value of i element
swap(i, j) - which swaps two elements
length(list) - return length of list
This is the code for get, swap and length:
def swap(i,j)
if i > j
i, j = j, i
elsif j == i
return
end
tmp = nil
list = #ListE.next #first element
for it in 0...j
if i == it
tmp = list
end
list = list.next
end
tmp.v, list.v = list.v, tmp.v
end
def get(i)
a = #ListE
while i>0
a = a.next
i-=1
end
return a.next.v
end
def length()
list = #ListE.next
length_of_list = 0
while list.v != nil
length_of_list += 1
list = list.next
end
return length_of_list
end
This is my attempt at an insertion sort:
def sort3(list) #insertion sort
for i in 1...list.length
j = i
while j > 0 and list.get(j-1) > list.get(j)
list.swap(j-1, i)
j -= 1
end
end
end

Nuances of where to define a variable in ruby code

I've just started learning ruby, and the position of where variables are defined somewhat elude me. For example, why does this code work:
def two_sum(nums)
result = nil
i = 0
while i < nums.length
k = (nums.length - 1)
if nums[i] + nums[k] == 0
result = [i,k]
end
i += 1
k -= 1
end
return result
end
And why does this code not work:
def two_sum(nums)
result = nil
i = 0
k = (nums.length - 1)
while i < nums.length
if nums[i] + nums[k] == 0
result = [i,k]
end
i += 1
k -= 1
end
return result
end
Thank you in advance!
I think you code might just have a bug
while i < nums.length
k = (nums.length - 1)
...
k -= 1 # this statement has no effect!
end
Above, the value if k is always (nums.length - 1) because you reassign it at the begin of each iteration. The other statement has no effect.
k = (nums.length - 1)
while i < nums.length
...
k -= 1
end
Above, the value of k starts at (nums.length - 1) in the first iteration and is then reduced by 1 for each iteration.
Pro tipp —
It is very unusual in Ruby to use a for/while/until loop. If you want to loop over all elements use each or each_with_index instead
array.each { |each| ... }
array.each_with_index { |each, n| ... }

Basic ruby code not working

I just learnt Ruby and I am doing some basic practise problems to get familiar with the language. I just came across this question:
"Write a method that takes an array of numbers. If a pair of numbers
in the array sums to zero, return the positions of those two numbers.
If no pair of numbers sums to zero, return nil."
This is my code:
def two_sum(nums)
i = 0
j = 0
while i < nums.length
while j < nums.length
if nums[i] + nums[j] == 0
return [i, j]
end
j+= 1
end
i += 1
end
return nil
end
It returns nil everytime. What's wrong with it?
j should be re-initialized to 0 when i gets incremented:
while i < nums.length
while j < nums.length
if nums[i] + nums[j] == 0
return [i, j]
end
j+= 1
end
i += 1
j = 0 # Here
end
While Yu Hao answers the literal question, here is a more Rubyish solution:
def two_sum(nums)
nums.each_with_index do |x, i|
j = nums.index(-x)
return [i, j] if j
end
nil
end

Ruby wrong result durning vectors calculations

We are trying to implement "Calculating coefficients of interpolating polynomial using Neville's algorithm."
This is our Vector Class:
class Wektor < Array
attr_accessor :coordinatesAmount
def initialize(length)
super(length, 0)
#coordinatesAmount = length
end
def SetVector(w)
for i in (0...coordinatesAmount) do
self[i] = w[i]
end
return self
end
def MultiplyBy(n)
for i in (0...coordinatesAmount) do
self[i] *= n
end
return self
end
def DivideBy(n)
for i in (0...coordinatesAmount) do
self[i] /= n
end
return self
end
def Sub(w)
for i in (0...coordinatesAmount) do
self[i] -= w[i]
end
return self
end
def Add(w)
for i in (0...coordinatesAmount) do
self[i] += w[i]
end
return self
end
def ShiftRight
coordinatesAmount.downto(1) { |i|
self[i-1] = self[i-2]
}
self[0] = 0
return self
end
This is our calculation part:
require_relative 'wektor.rb'
#Coefficients
def Coefficients(i, j, tabX, tabY, pyramid)
#mnozymy przez Xj
length = pyramid[i][j-1].length
temp = Wektor.new(length).SetVector(pyramid[i][j-1])
temp.MultiplyBy(tabX[j])
pyramid[i][j].SetVector(temp)
#odjęcie Pi,j-1 przesuniętego o 1 w prawo
temp = Wektor.new(length).SetVector(pyramid[i][j-1])
temp.ShiftRight
pyramid[i][j].Sub(temp)
#dodanie Pi+1, j przesuniętego o 1 w prawo
temp = Wektor.new(length).SetVector(pyramid[i+1][j])
temp.ShiftRight
pyramid[i][j].Add(temp)
#odjęcie Pi+1, j pomnożonego przez Xi
temp = Wektor.new(length).SetVector(pyramid[i+1][j])
temp.MultiplyBy(tabX[i])
pyramid[i][j].Sub(temp)
#podzielenie przez (Xj - Xi)
pyramid[i][j].DivideBy(tabX[j] - tabX[i])
return pyramid[i][j]
end
#CalculateResult
def CalculatePolynomialResult(x,y,n)
pyramid = Hash.new {|h,k| h[k] = Wektor.new(n)}
for i in 0...n do
for j in 0...n-i do
if (j != i+j) then
next
end
pyramid[j][j] = Wektor.new(n)
pyramid[j][j].push(y[j])
end
end
for i in 0...n do
for j in 0...n-i do
if (j == i+j) then
next
end
pyramid[j][i+j] = Wektor.new(n)
Coefficients(j, i+j, x, y, pyramid)
end
end
return pyramid[0][n-1]
end
We are facing the problem when the Coefficients method is calculating something we still get zeros. There is no exception error but our Vector are zeros. I added a link for our Source at Math Overflow to explain what is going on.
This is the same code but written in C#, to play with .NET.
Any ideas why our vectors are useless? Like something is overwriting them or maybe with some value/reference? We are unable to track that issue.

Using the Bubble sort method for an array in Ruby [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I'm trying to implement the Bubble sort method into an easy coding problem for Ruby, but I'm having some trouble. I understand the idea is to look at the value of the first element and compare it to the value of the second element and then swap them accordingly, but I can't seem to do it in an actual problem. Would anyone be willing to provide a brief example of how this might work in Ruby?
Correct implementation of the bubble sort with a while loop
def bubble_sort(list)
return list if list.size <= 1 # already sorted
swapped = true
while swapped do
swapped = false
0.upto(list.size-2) do |i|
if list[i] > list[i+1]
list[i], list[i+1] = list[i+1], list[i] # swap values
swapped = true
end
end
end
list
end
arr = [4,2,5,1]
loop until arr.each_cons(2).with_index.none?{|(x,y),i| arr[i],arr[i+1] = y,x if x > y}
p arr #=> [1, 2, 4, 5]
Source
def bubble_sort(list)
return list if list.size <= 1 # already sorted
loop do
swapped = false
0.upto(list.size-2) do |i|
if list[i] > list[i+1]
list[i], list[i+1] = list[i+1], list[i] # swap values
swapped = true
end
end
break unless swapped
end
list
end
Although I would certainly recommend something with a better run-time than bubblesort :)
Here's my version of the top answer. It calls size on the array only once instead of every loop. It doesn't compare elements once they have moved to the end of the array.
And the while loop quits one loop sooner. You're done once you've gone through the whole array and only did one swap, so no need to do another with 0 swaps.
def bubble_sort(list)
iterations = list.size - 2
return list unless iterations > 0 # already sorted
swaps = 2
while swaps > 1 do
swaps = 0
0.upto(iterations) do |i|
if list[i] > list[i + 1]
list[i], list[i + 1] = list[i + 1], list[i] # swap values
swaps += 1
end
end
iterations -= 1
end
list
end
Running this test takes 25% less time.
that_array = this_array = [22,66,4,44,5,7,392,22,8,77,33,118,99,6,1,62,29,14,139,2]
49.times {|variable| that_array = that_array + this_array}
bubble_sort that_array
Just re-writing #VanDarg's code to use a while loop
(note: code not tested... run at your own peril)
def bubble_sort(list)
return list if list.size <= 1 # already sorted
swapped = true
while swapped
swapped = false # maybe this time, we won't find a swap
0.upto(list.size-2) do |i|
if list[i] > list[i+1]
list[i], list[i+1] = list[i+1], list[i] # swap values
swapped = true # found a swap... keep going
end
end
end
list
end
Edit: updated swapped-values because bubble sort keeps sorting while there are still swaps being made - as soon as it finds no more swaps, it stops sorting. Note, this does not follow #Doug's code, but does conform with #cLuv's fix
def bubble_sort array
array.each do
swap_count = 0
array.each_with_index do |a, index|
break if index == (array.length - 1)
if a > array[index+1]
array[index],array[index+1] = array[index +1], array[index]
swap_count += 1
end
end
break if swap_count == 0 # this means it's ordered
end
array
end
The straight forward:
def bubble_sort(n)
return n if n.length <= 1
0.upto(n.length - 1) do |t|
0.upto(n.length - 2 - t) do |i|
if n[i] > n[i + 1]
n[i], n[i + 1] = n[i + 1], n[i]
end
end
end
n
end
If you don't want to use this funny swapping line (IMO):
arr[i], arr[j] = arr[j], arr[i]
here's my take:
def bubble_sort(arr)
temp = 0
arr.each do |i|
i = 0
j = 1
while (j < arr.length)
if arr[i] > arr[j]
temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
p arr
end
i+=1
j+=1
end
end
arr
end
Old school
def bubble_sort(random_numbers)
for i in 0..random_numbers.size
for j in i+1..random_numbers.size-1
random_numbers[i], random_numbers[j] = random_numbers[j], random_numbers[i] if(random_numbers[i] > random_numbers[j])
end
end
random_numbers
end
class Array
a = [6, 5, 4, 3, 2, 1]
n = a.length
for j in 0..n-1
for i in 0..n - 2 - j
if a[i]>a[i+1]
tmp = a[i]
a[i] = a[i+1]
a[i+1] = tmp
end
end
end
puts a.inspect
end
Here's my take using the operator XOR:
def bubble(arr)
n = arr.size - 1
k = 1
loop do
swapped = false
0.upto(n-k) do |i|
if arr[i] > arr[i+1]
xor = arr[i]^arr[i+1]
arr[i] = xor^arr[i]
arr[i+1] = xor^arr[i+1]
swapped = true
end
end
break unless swapped
k +=1
end
return arr
end
Another, slightly different naming.
def bubble_sort(list)
return list if list.size <= 1
not_sorted = true
while not_sorted
not_sorted = false
0.upto(list.size - 2) do |i|
if list[i] > list[i + 1]
list[i], list[i + 1] = list[i + 1], list[i]
not_sorted = true
end
end
end
list
end
def bubbleSort(list)
sorted = false
until sorted
sorted = true
for i in 0..(list.length - 2)
if list[i] > list[i + 1]
sorted = false
list[i], list[i + 1] = list[i + 1], list[i]
end
end
end
return list
end
Here is my code. I like using the (arr.length-1). For loops you can also use such iterations such as until, while, for, upto, loop do, etc. Fun to try different things to see how it functions.
def bubble_sort(arr) #10/17/13 took me 8mins to write it
return arr if arr.length <= 1
sorted = true
while sorted
sorted = false
(arr.length-1).times do |i|
if arr[i] > arr[i+1]
arr[i], arr[i+1] = arr[i+1], arr[i]
sorted = true
end
end
end
arr
end

Resources