I searched around a bit and could not found any sorting algorithm that described this way to sort. I do understand that it has no real use as it's terribly inefficient. Here it is in Ruby:
def swap(array, i)
array[i], array[i+1] = array[i+1], array[i]
end
def compare(array, i)
array[i] > array[i+1]
end
def sort(array)
i = 0
until i + 1 == array.length
if compare(array, i)
swap(array, i)
i = 0
else
i += 1
end
end
return array
end
This is Gnome sort kind - walking from the beginning until order violation occurs, then swapping, but here position resets to array begin.
Related
I'm trying to create a recursive method sum_of_digits(i) that takes the sum of integers, i.e. '456' = 4+5+6 = 15
However, I receive a NoMethodError for chr.to_i in the following code:
def sum_of_digits(i)
input = i.to_s
if i == 0
return 0
elsif input.length == 1
return i
else
for n in 1..input.length
sum += input[i].chr.to_i % 10^(n-1)
end
end
return sum
end
Thank you!
String indexes are zero-based in ruby. The problem is here:
for n in 1..input.length
it should be written as
for n in 0..input.length-1
BTW, call to chr is superfluous as well, since you already have a string representation of a digit there. As well, sum must be declared in advance and set to zero.
Also, the whole code is not ruby idiomatic: one should avoid using unnecessary returns and for-loop. The modified version (just in case) would be:
def sum_of_digits(i)
input = i.to_s
case
when i == 0 then 0 # return zero
when input.length == 1 then i # return i
else
sum = 0
input.length.times do |index|
sum += input[index].to_i % 10^index
end
sum
end
end
or, even better, instead of
sum = 0
input.length.times do |index|
sum += input[index].to_i % 10^index
end
sum
one might use inject:
input.length.times.inject(0) do |sum, index|
sum += input[index].to_i % 10^index
end
I am trying to create a method that uses bubble-sort to sort a small array into numerical order. This method accepts two arguments, an array and a method:
def bubble_sort_by(arr)
while(true)
counter = 0
for i in 0...(arr.size-1)
if yield (arr[i], arr[i+1]) > 0
saved = arr[i]
arr[i] = arr[i+1]
arr[i+1] = saved
counter += 1
end
end
if (counter == 0)
break
end
end
print arr
end
bubble_sort_by([4,3,78,2,0,2]) do |left,right|
return left - right
end
The sorted array should be
[0,2,2,3,4,78]
Currently I am using Ruby version 2.3.0p0.
I keep getting a syntax error when I try to run this code.
This is the fixed version:
def bubble_sort_by(arr)
while(true)
counter = 0
for i in 0...(arr.size-1)
if yield(arr[i], arr[i+1]) > 0
saved = arr[i]
arr[i] = arr[i+1]
arr[i+1] = saved
counter += 1
end
end
if (counter == 0)
break
end
end
print arr
end
bubble_sort_by([4,3,78,2,0,2]) do |left,right|
left - right
end
As you can see, it had two issues:
The space a yield - basically the space was extra because it wasn't passing the numbers in the parenthesis as arguments;
The return in the block - you do not want the block to explicitly return the value, you need it to be evaluated in bubble_sort_by and then its result used in the context there.
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
Below are two slightly different methods for listing all lexicographic permutations of N objects. I can't understand why the first method works fine for smallish N, but fails above a certain limit and results in 'stack overflow'. The second method; however, works just fine up to my tested limit of 10**6. Thanks in advance for your help and insight!
$count = 0
$permutations = []
def perms(array)
$permutations = array
$count += 1
if array.length <= 1
return $permuations
end
i = (array.length - 2)
until array[i] < array[i+1]
i -= 1
end
if i < 0
return $permutations
end
j = (array.length - 1)
until array[j] > array[i]
j -= 1
end
array[i], array[j] = array[j], array[i]
i += 1
j = (array.length - 1)
until j < i
array[i], array[j] = array[j], array[i]
i += 1
j -= 1
end
while $count <= (10**6)-2
perms(array)
end
end
perms([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
print $permutations
And here's the second method...
perm_limit = (10**6)
$count = 1
def perms(array)
if array.length <= 1
return false
end
i = (array.length - 2)
until array[i] < array[i+1]
i = (i - 1)
end
if i < 0
return false
end
j = (array.length - 1)
until array[j] > array[i]
j = (j - 1)
end
array[i], array[j] = array[j], array[i]
i = (i + 1)
j = (array.length - 1)
until j < i
array[i], array[j] = array[j], array[i]
i = (i + 1)
j = (j - 1)
end
$count += 1
return true
end
array = [0,1,2,3,4,5,6,7,8,9]
while perms(array) == true
if $count == perm_limit
print array
end
end
Again, thanks.
The first code sample you provide is a recursive function:
while $count <= (10**6)-2
perms(array)
end
The function is calling itself, is calling itself, is calling itself until your stack overflows (everytime a function is called, space on stack is allocated).
Your second algorithm does not use a recursive function and so the depth of your stack is only one - your stack is not growing.
For more information see "What is a stack overflow". The question is for Java, but the concept is the same for all stack-based languages.
Recursive vs. iterative
So why are we writing recursive functions/algorithms if they can overflow? Because recursion can model some problems very nicely, and it can be easier to write a recursive algorithm (it's considered more "mathematically beautiful") than an iterative one. If you know that your recursion depth won't be too deep, then recursion might be the preferred method.
On the other hand, an iterative algorithm is usually the preferred if you're worried about your stack space. An iterative function can be easier or harder to write depending on how you model the problem. All recursive functions can be converted to iterative functions.
On a side note: there are some languages where recursion and stack space is not a problem. These languages may use "tail-calls" meaning the function is recursive, but instead of allocating new space on the stack, it simply re-uses the current function's stack space (and so the stack never grows). You can read more here.
So I'm trying to learn how to sort an array without using the .sort method, this is what I have so far, but the middle number is dropping out.
def my_sort(num)
for j in 1...num.length
key = num[j]
i = j - 1
while i > 0 and num[i] = key
num[i+1] = num[i]
i = i - 1
end
num[i+1] = key
end
end
then I run the method
my_sort([3,1,2])
I get
=> 1...3
but I want
=> 1,2,3
What am I doing wrong?
You're not returning the modified array, but instead the object fed into your for iterator.
What you're missing is simply leaving the array as the last thing in the method:
def my_sort(num)
# ...
num
end
As a note it's usually bad form to wreck the arguments you're given. A more polite function would return a copy.
Actual implementation of insertion sort must look like:
def my_sort(arr)
for j in 1...arr.length
key = arr[j]
i = j-1
while i>=0 and arr[i] > key # You used arr[i] = key here instead
arr[i+1] = arr[i]
i = i-1
end
arr[i+1] = key
end
arr #return the array
end