Rotating elements i to j in an array - ruby

Given an array:
a = [1, 2, 3, 4, 5, 6]
I want to rotate elements i through j in some direction n times. So, for example:
i = 2
j = 3
n = 1
Rotating a will produce:
new_a = [1, 2, 4, 3, 5, 6]
This is what I have:
def rotate_sub(a, i, j, n)
return a[0...i] + a[i..j].rotate(n) + a[j+1..-1]
end
Is there a better way to do this? Since there is no bound-checks, i or j could very well be outside the bounds of the array.

If you are willing to mutate the original array you could do something like:
a[i..j] = a[i..j].rotate n
But I like the functional solution you already have.

I don't think there's a magical way, so perhaps the simplest is the best:
def rotate_sub(a, i, j, n)
a[0...i] + a[i..j].rotate(n) + a[j+1..-1] if i < j && j < a.size
end

Related

Shuffle an int array such that array elements in even indices are smaller than array elements in odd indices

I need to have all the elements in the even indices arr[0],arr[2],arr[4] etc be smaller than the elements with odd indices arr[1],arr[3],arr[5], etc
My approach was to find the MEDIAN and then write out all elements smaller than the median in odd indices and all elements larger than the median in even places.
Question: is there a way to do the array shuffling IN PLACE after finding the median ?
import random
def quickselect(items, item_index):
def select(lst, l, r, index):
# base case
if r == l:
return lst[l]
# choose random pivot
pivot_index = random.randint(l, r)
# move pivot to beginning of list
lst[l], lst[pivot_index] = lst[pivot_index], lst[l]
# partition
i = l
for j in range(l+1, r+1):
if lst[j] < lst[l]:
i += 1
lst[i], lst[j] = lst[j], lst[i]
# move pivot to correct location
lst[i], lst[l] = lst[l], lst[i]
# recursively partition one side only
if index == i:
return lst[i]
elif index < i:
return select(lst, l, i-1, index)
else:
return select(lst, i+1, r, index)
if items is None or len(items) < 1:
return None
if item_index < 0 or item_index > len(items) - 1:
raise IndexError()
return select(items, 0, len(items) - 1, item_index)
def shuffleArray(array, median):
newArray = [0] * len(array)
i = 0
for x in range(0,len(array),2):
newArray[x] = array[i]
i+=1
for y in range(1,len(array),2):
newArray[y] = array[i]
i+=1
return newArray
So here's my interpretation of the question.
Shuffle an array so that all data in even indices are smaller than all data in odd indices.
Eg
[1, 3, 2, 4] would be valid, but [1, 2, 3, 4] wouldn't be.
This stops us just being able to sort the array.
Sort the array, smallest to largest.
Split the array at its mid point (rounding the mid point down).
Shuffle the two arrays together. Such that given array [1, 2, 3] and array [4, 5, 6] it becomes [1, 4, 2, 5, 3, 6].
To elaborate on 3, here's some example code... (using javascript)
let a = [ 1, 2, 3 ];
let b = [ 4, 5, 6 ];
let c = [ ] // this will be the sorted array
for (let i = 0; i < a.length + b.length; i++ ) {
if(i % 2 == 0) c.push( a[Math.floor( i/2 )]);
else c.push( b[Math.floor( i/2 )]);
}
This produces the array [1, 4, 2, 5, 3, 6], which i believe fufils the requirement.

How do you check if one array is a subsequence of another?

I'm looking to explore different algorithms, both recursive and dynamic programming, that checks if one arrayA is a subsequence of arrayB. For example,
arrayA = [1, 2, 3]
arrayB = [5, 6, 1, 7, 2, 9, 3]
thus, arrayA is indeed a subsequence of arrayB.
I've tried a few different searches, but all I can seem to find is algorithms to compute the longest increasing subsequence.
Since you must match all elements of arrayA to some elements of arrayB, you never need to backtrack. In other words, if there are two candidates in arrayB to match an element of arrayA, you can pick the earliest one, and never retract the choice.
Therefore, you do not need DP, because a straightforward linear greedy strategy will work:
bool isSubsequence(int[] arrayA, int[] arrayB) {
int startIndexB = 0;
foreach (int n in arrayA) {
int next = indexOf(arrayB, startIndexB , n);
if (next == NOT_FOUND) {
return false;
}
startIndexB = next+1;
}
return true;
}
As dasblinkenlight has correctly said(and i could not have phrased it better than his answer!!) a greedy approach works absolutely fine. You could use the following pseudocode (with just a little more explanation but totally similar to what dasblinkenlight has written)which is similar to the merging of two sorted arrays.
A = {..}
B = {..}
j = 0, k = 0
/*j and k are variables we use to traverse the arrays A and B respectively*/
for(j=0;j<A.size();){
/*We know that not all elements of A are present in B as we
have reached end of B and not all elements of A have been covered*/
if(k==B.size() && j<A.size()){
return false;
}
/*we increment the counters j and k both because we have found a match*/
else if(A[j]==B[k]){
j++,k++;
}
/*we increment k in the hope that next element may prove to be an element match*/
else if(A[j]!=B[k]){
k++;
}
}
return true; /*cause if we have reached this point of the code
we know that all elements of A are in B*/
Time Complexity is O(|A|+|B|) in the worst case, where |A| & |B| are the number of elements present in Arrays A and B respectively. Thus you get a linear complexity.
As #sergey mentioned earlier, there is no need to do backtracking in this case.
Here just another Python version to the problem: [Time complexity: O(n) - worst]
>>> A = [1, 2, 3]
>>> B = [5, 6, 1, 7, 8, 2, 4, 3]
>>> def is_subsequence(A, B):
it = iter(B)
return all(x in it for x in A)
>>> is_subsequence(A, B)
True
>>> is_subsequence([1, 3, 4], B)
False
>>>
Here is an example in Ruby:
def sub_seq?(a_, b_)
arr_a = [a_,b_].max_by(&:length);
arr_b = [a_,b_].min_by(&:length);
arr_a.select.with_index do |a, index|
arr_a.index(a) &&
arr_b.index(a) &&
arr_b.index(a) <= arr_a.index(a)
end == arr_b
end
arrayA = [1, 2, 3]
arrayB = [5, 6, 1, 7, 2, 9, 3]
puts sub_seq?(arrayA, arrayB).inspect #=> true
Here is an example in GOLANG...
func subsequence(first, second []int) bool {
k := 0
for i := 0; i < len(first); i++ {
j := k
for ; j < len(second); j++ {
if first[i] == second[j] {
k = j + 1
break
}
}
if j == len(second) {
return false
}
}
return true
}
func main(){
fmt.Println(subsequence([]int{1, 2, 3}, []int{5, 1, 3, 2, 4}))
}

How can the complexity of this function be decreased?

I got this function:
def get_sum_slices(a, sum)
count = 0
a.length.times do |n|
a.length.times do |m|
next if n > m
count += 1 if a[n..m].inject(:+) == sum
end
end
count
end
Given this [-2, 0, 3, 2, -7, 4] array and 2 as sum it will return 2 because two sums of a slice equal 0 - [2] and [3, 2, -7, 4]. Anyone an idea on how to improve this to a O(N*log(N))?
I am not familiar with ruby, but it seems to me you are trying to find how many contiguous subarrays that sums to sum.
Your code is doing a brute force of finding ALL subarrays - O(N^2) of those, summing them - O(N) each, and checking if it matches.
This totals in O(N^3) code.
It can be done more efficiently1:
define a new array sums as follows:
sums[i] = arr[0] + arr[1] + ... + arr[i]
It is easy to calculate the above in O(N) time. Note that with the assumption of non negative numbers - this sums array is sorted.
Now, iterate the sums array, and do a binary search for each element sums[i], if there is some index j such that sums[j]-sums[i] == SUM. If the answer is true, add by one (more simple work is needed if array can contains zero, it does not affect complexity).
Since the search is binary search, and is done in O(logN) per iteration, and you do it for each element - you actually have O(NlogN) algorithm.
Similarly, but adding the elements in sums to a hash-set instead of placing them in a sorted array, you can reach O(N) average case performance, since seeking each element is now O(1) on average.
pseudo code:
input: arr , sum
output: numOccurances - number of contiguous subarrays that sums to sum
currSum = 0
S = new hash set (multiset actually)
for each element x in arr:
currSum += x
add x to S
numOccurances= 0
for each element x in S:
let k = number of occurances of sum-x in the hashset
numOccurances += k
return numOccurances
Note that the hash set variant does not need the restriction of non-negative numbers, and can handle it as well.
(1) Assuming your array contains only non negative numbers.
According to amit's algorithm :
def get_sum_slices3(a, sum)
s = a.inject([]) { |m, e| m << e + m.last.to_i }
s.sort!
s.count { |x| s.bsearch { |y| x - y == sum } }
end
Ruby uses quicksort which is nlogn in most cases
You should detail better what you're trying to achieve here. Anyway computing the number of subarray that have a specific sum could be done like this:
def get_sum_slices(a, sum)
count = 0
(2..a.length).each do |n|
a.combination(n).each do |combination|
if combination.inject(:+) == sum
count += 1
puts combination.inspect
end
end
end
count
end
btw your example should return 6
irb> get_sum_slices [-2, 0, 3, 2, -7, 4], 0
[-2, 2]
[-2, 0, 2]
[3, -7, 4]
[0, 3, -7, 4]
[-2, 3, 2, -7, 4]
[-2, 0, 3, 2, -7, 4]
=> 6

Finding the index of second smallest number in the list?

How can I find the second smallest number and return its index?
Another approach :
>> a = [1,3,5,6,2,4]
=> [1, 3, 5, 6, 2, 4]
>> a.index(a.sort[1])
=> 4
>>
I can see two options from the top of my head:
Delete the current min, so the new min will be the previous second min
arr = num.delete(num.min)
min_bis = arr.min
Loop through the array, using 2 variables to store the 2 lowest values.
This might be a little trickier but the complexity would only be O(n).
I don't know why you don't want to sort the array, but if it's a performance issue, it's probably one of the best options (to sort it) especially if the array is small.
(Below, Enumerable is a superset of Array, Hash and Range etc.)
Enumerable#sort returns a fresh array containing all the elements of the original object in a sorted order, so you can write a = num.sort[1] (provided that l > 1) to find the second smallest number, without modfying the original input nums.
Then you can feed it to Enumerable#find_index.
http://ruby-doc.org/core-1.9.3/Enumerable.html#method-i-sort
http://ruby-doc.org/core-1.9.3/Enumerable.html#method-i-find_index
By the way
while (index <l)
nums - gets.to_i
num[index] = nums
index +=1
end
can be written as
nums = (0...l).map{ gets.to_i }
I understand you don't want to sort the array before finding the second-lowest number. But are you willing to use a sorted clone/copy of that array?
If
nums = [1, 5, 1, 9, 3, 8]
Then:
# grab a sorted copy of nums
b = nums.sort
# b = [1, 1, 3, 5, 8, 9]
# delete the lowest number
b.delete(b.min)
# now b = [3, 5, 8, 9]
# so get the index from the original array
nums.index(b.first)
which should return 4 because nums[4] = 3. (You could also use nums.index(b[0]) since b is already sorted.)
If you don't mind being destructive to the original array:
a.delete(a.min)
a.index(a.min)
Here's an approach that does not use sort:
arr = [3,1,2,5,1]
If second_smallest(arr) => 2 is desired:
def second_smallest(arr)
return nil if arr.uniq.size < 2
mn, mx = arr.min, arr.max
arr.map! { |e| e == mn ? mx : e }
arr.index(arr.min)
end
If second_smallest(arr) => 4 is desired:
def second_smallest(arr)
return nil if arr.uniq.size < 2
i1 = arr.index(arr.min)
arr.delete_at(i1)
i2 = arr.index(arr.min)
i2 >= i1 ? i2 + 1 : i2
end
You don't want to use sort as it's O(nlogn). You want to iterate through the array only once (after getting the max):
arr = [123,35,12,34,5,32]
This is a straight forward way of solving the problem:
def second_min_index(arr)
max = arr.max
min, min_index, second_min, second_min_index = max, 0, max, 0
arr.each_with_index do |e, i|
# if something is less than min, second min should become what used to be min
if (e <= min)
second_min, second_min_index, min, min_index = min, min_index, e, i
# if something is less than second min (but not less than min)
# it becomes the second min
elsif (e < second_min)
second_min, second_min_index = e, i
end
end
second_min_index
end
second_min_index(arr)
=> 2
A better and more reusable way of doing this would be via a transform and conquer solution (just in case you get asked for the 3rd smallest number):
def min_index(arr)
min, min_index = arr[0], 0
arr.each_with_index { |e,i| min, min_index = e,i if e < min }
min_index
end
def min_index_excluding(arr, exclude_indexes)
min, min_index = arr[0], 0
arr.each_with_index { |e,i| min, min_index = e,i if (e < min && !exclude_indexes.include?(i)) }
min_index
end
def second_min_index(arr)
min_index_excluding(arr, [min_index(arr)])
end
second_min_index(arr)
=> 2
a_sorted = a.sort
second_min = a_sorted[1]
a.index(second_min)

should destructive functions extend their classes?

I'm implementing some stuff from CLRS, and the partition() algorithm is causing me a little concern. It's implied (from the consistently vague pseudocode therein, but not stated explicitly) that partition should modify the array it's passed, and return a related scalar value:
PARTITION(A, p, r)
1 x = A[r]
2 i = p -1
3 for j = p to r - 1
4 if A[j] <= x
5 i = i + 1
6 swap A[i], A[j]
7 swap A[i+1], A[r]
8 return i + 1
This is easy to throw together in Ruby, but my question is, since it changes the array it's passed without returning it, should it be a class method like array.do_stuff!()?
irb(main):007:0> ary
=> [0, 3, 0, 2, 1, 2, 2, 2, 4, 4, 2]
irb(main):008:0> partition(ary,2,4)
=> 3
irb(main):009:0> ary
=> [0, 3, 0, 1, 2, 2, 2, 2, 4, 4, 2]
For reference, here is my code:
def partition(my_list, part_start, part_end, pivot = my_list[part_end])
# From CLRS p. 171
# In-place rearrangement of subarrays.
sort_separator = part_start - 1
for loop_ind in (part_start..part_end-1)
if my_list[loop_ind] <= my_list[part_end]
sort_separator += 1
my_list[sort_separator],my_list[loop_ind] =
my_list[loop_ind],my_list[sort_separator]
end
end
my_list[sort_separator+1],my_list[part_end] =
my_list[part_end],my_list[sort_separator+1]
return(sort_separator+1)
end

Resources