How to duplicate value of array in ruby - ruby

I have two arrays of integers, e.g.
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
b = [7, 8, 9]
I would like to repeatedly duplicate the value of 'b' to get a perfectly matching array lengths like this:
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
b = [7, 8, 9, 7, 8, 9, 7, 8, 9, 7]
We can assume that a.length > b.length

Assuming you mean
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
b = [7, 8, 9]
then you can do:
b.cycle.take(a.length) #=> [7, 8, 9, 7, 8, 9, 7, 8, 9, 7]
<script src="//repl.it/embed/JJ3x/2.js"></script>
See Array#cycle and Enumerable#take for more details.

I would have used Array#cycle had it been available, but since it was taken I thought I'd suggest some alternatives (the first being my fav).
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
b = [7, 8, 9]
[*b*(a.size/b.size), *b[0, a.size % b.size]]
#=> [7, 8, 9, 7, 8, 9, 7, 8, 9, 7]
Array.new(a.size) { |i| b[i % b.size] }
#=> [7, 8, 9, 7, 8, 9, 7, 8, 9, 7]
b.values_at(*(0..a.size-1).map { |i| i % b.size })
#=> [7, 8, 9, 7, 8, 9, 7, 8, 9, 7]

Related

What type of sorting algorithm it will be called? [duplicate]

what is the name of this sort? its just like bubble sort but its easy to write but harder in term of complexity.codes are in python language.
def sort(arr):
n = len(arr)
for i in range(n):
for j in range(n):
if arr[i] < arr[j] :
arr[j], arr[i] = arr[i], arr[j]
but bubble sort is like this :
def bubbleSort(arr):
n = len(arr)
# Traverse through all array elements
for i in range(n):
# Last i elements are already in place
for j in range(0, n-i-1):
# traverse the array from 0 to n-i-1
# Swap if the element found is greater
# than the next element
if arr[j] > arr[j+1] :
arr[j], arr[j+1] = arr[j+1], arr[j]
It is neither selection sort nor bubble sort, but an unnecessary bad sort. All of them, your sort, selection sort and bubble sort are of the same complexity, O(n^2).
Your sort sweeps over the array in two loops without consideration for if an element has reached its proper place (as in selection sort) or if an element has gained a place relative to the next (as in bubble sort). The extra code in bubble and selection sort make them far better than yours.
Compare, yourself:
def sort(arr):
print(arr)
n = len(arr)
for i in range(n):
for j in range(n):
if arr[i] < arr[j] :
arr[j], arr[i] = arr[i], arr[j]
print(arr)
def selectionsort(arr):
print(arr)
n = len(arr)
for i in range(n-1):
min_index = i
for j in range(i+1, n):
if arr[j] < arr[min_index]:
min_index = j
arr[i], arr[min_index] = arr[min_index], arr[i]
print(arr)
def bubblesort(arr):
print(arr)
n = len(arr)
for i in range(n):
for j in range(0, n-i-1):
if arr[j] > arr[j+1] :
arr[j], arr[j+1] = arr[j+1], arr[j]
print(arr)
print("sort:")
sort([4,6,3,2,7,1,8,5])
print("selectionsort:")
selectionsort([4,6,3,2,7,1,8,5])
print("bubblesort:")
bubblesort([4,6,3,2,7,1,8,5])
with the results:
sort:
[4, 6, 3, 2, 7, 1, 8, 5]
[6, 4, 3, 2, 7, 1, 8, 5]
[7, 4, 3, 2, 6, 1, 8, 5]
[8, 4, 3, 2, 6, 1, 7, 5]
[4, 8, 3, 2, 6, 1, 7, 5]
[3, 8, 4, 2, 6, 1, 7, 5]
[3, 4, 8, 2, 6, 1, 7, 5]
[2, 4, 8, 3, 6, 1, 7, 5]
[2, 3, 8, 4, 6, 1, 7, 5]
[2, 3, 4, 8, 6, 1, 7, 5]
[2, 3, 4, 6, 8, 1, 7, 5]
[1, 3, 4, 6, 8, 2, 7, 5]
[1, 2, 4, 6, 8, 3, 7, 5]
[1, 2, 3, 6, 8, 4, 7, 5]
[1, 2, 3, 4, 8, 6, 7, 5]
[1, 2, 3, 4, 6, 8, 7, 5]
[1, 2, 3, 4, 6, 7, 8, 5]
[1, 2, 3, 4, 5, 7, 8, 6]
[1, 2, 3, 4, 5, 6, 8, 7]
[1, 2, 3, 4, 5, 6, 7, 8]
selectionsort:
[4, 6, 3, 2, 7, 1, 8, 5]
[1, 6, 3, 2, 7, 4, 8, 5]
[1, 2, 3, 6, 7, 4, 8, 5]
[1, 2, 3, 6, 7, 4, 8, 5]
[1, 2, 3, 4, 7, 6, 8, 5]
[1, 2, 3, 4, 5, 6, 8, 7]
[1, 2, 3, 4, 5, 6, 8, 7]
[1, 2, 3, 4, 5, 6, 7, 8]
bubblesort:
[4, 6, 3, 2, 7, 1, 8, 5]
[4, 3, 6, 2, 7, 1, 8, 5]
[4, 3, 2, 6, 7, 1, 8, 5]
[4, 3, 2, 6, 1, 7, 8, 5]
[4, 3, 2, 6, 1, 7, 5, 8]
[3, 4, 2, 6, 1, 7, 5, 8]
[3, 2, 4, 6, 1, 7, 5, 8]
[3, 2, 4, 1, 6, 7, 5, 8]
[3, 2, 4, 1, 6, 5, 7, 8]
[2, 3, 4, 1, 6, 5, 7, 8]
[2, 3, 1, 4, 6, 5, 7, 8]
[2, 3, 1, 4, 5, 6, 7, 8]
[2, 1, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8]
It doesn't make a big difference on small arrays but on large arrays it make a lot of difference (but then there are other methods).

Infinite loop in blocks in ruby

Why does the following piece of code result in an infinite loop of 3's?
a = [1,2,3,4,5,6,7,8,9,10]
a.each {|value| puts a.insert(value,3)}
The problem is that insert changes the original array:
a = [1,2,3,4,5,6,7,8,9,10]
a.each do |value|
a.insert(value, 3)
p a
end
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # original, ^ marks current value
# ^
# [1, 3, 2, 3, 4, 5, 6, 7, 8, 9, 10] # inserted 3 at position 1
# ^
# [1, 3, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10] # inserted 3 at position 3
# ^
# [1, 3, 3, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10] # inserted 3 at position 2
# ^
# [1, 3, 3, 3, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10] # inserted 3 at position 2
# ^
# [1, 3, 3, 3, 3, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10] # inserted 3 at position 2
# ^
# [1, 3, 3, 3, 3, 3, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10] # inserted 3 at position 2
# ^
# ... # continues forever ...
What you probably want instead is something like this:
a = [1,2,3,4,5,6,7,8,9,10]
a.each_index {|index| p a.dup.insert(index, 3) }
# [3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# [1, 3, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# [1, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10]
# [1, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10]
# [1, 2, 3, 4, 3, 5, 6, 7, 8, 9, 10]
# [1, 2, 3, 4, 5, 3, 6, 7, 8, 9, 10]
# [1, 2, 3, 4, 5, 6, 3, 7, 8, 9, 10]
# [1, 2, 3, 4, 5, 6, 7, 3, 8, 9, 10]
# [1, 2, 3, 4, 5, 6, 7, 8, 3, 9, 10]
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 3, 10]
each_index iterates over the indices, not the values. This is likely the correct thing to do here, because insert takes an index as first argument.
dup duplicates the array on every iteration so a remains unchanged.

Reduce array to set number of items? [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 8 years ago.
Improve this question
I have a Ruby array of 300 items. I want to reduce that array down to a set number of items, evenly picked from the array.
The number of items in the array will not be the same every time, nor will the number of items needed.
Something like this:
arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
num_of_items = 4
final_arr = [0, 5, 10, 15]
You can use Enumerable#each_slice
arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
#=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
num_of_items = 4
#=> 4
arr.each_slice(arr.size/num_of_items + 1).map(&:first)
#=> [0, 5, 10, 15]
arr = (0..16).to_a
#=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
num_of_items = 5
#=> 5
arr.each_slice(arr.size/num_of_items + 1).map(&:first)
#=> [0, 4, 8, 12, 16]
OR
Numeric#step
arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
#=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
num_of_items = 4
#=> 4
arr.first.step(arr.size, arr.size/num_of_items + 1).map { |i| arr[i] }
#=> [0, 5, 10, 15]
arr = (0..16).to_a
#=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
num_of_items = 5
#=> 5
arr.first.step(arr.size, arr.size/num_of_items + 1).map { |i| arr[i] }
#=> [0, 4, 8, 12, 16]
If you're picking a given number of items at random from this array, use sample -
$ arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
$ arr.sample(5)
=> [1, 3, 5, 4, 12]
$ arr.sample(5)
=> [15, 6, 13, 5, 11]
If the goal of your algorithm is exactly as shown above, you could use in_groups_of, then grab the first element of each child array:
1.9.3p484 :014 > num_of_items = 5
=> 5
1.9.3p484 :011 > arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
1.9.3p484 :012 > arr.in_groups_of(num_of_items)
=> [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [10, 11, 12, 13, 14], [15, nil, nil, nil, nil]]
1.9.3p484 :013 > arr.in_groups_of(num_of_items).map(&:first)
=> [0, 5, 10, 15]

recursive removal of elements in array

Given an array of n elements, remove any adjacent pair of elements which are equal. Repeat this operation until there are no more adjacent pairs to remove; that will be the final array.
For e.g 1 2 2 3 4 should return the array 1 3 4.
please note array need not to be sorted.
check this test case also: 1,2,2,3,4,4,3,5 o/p should be 1,5.
(2,2) and (4,4) gets removed, then (3,3) which became adjacent after the removal of (4,4)
Any time you remove a pair of elements, you also need to see if you generated another pair that you want to remove.
The algorithm should follow naturally from that observation.
In Python:
>>> l=[1,2,2,3,4,4,3,5]
>>> [x for x in l if not l.count(x) > 1]
[1, 5]
This removes all integers that occur more than once in the list. This is a correct result for your example but I think that you are really trying to state something different. I think you are saying:
list:=(an unsorted list of integers)
while adjacent_pairs(list) is True:
remove_adjacent_pairs(list)
Once again, in Python:
#!/usr/bin/env python
def dedupe_adjacent(l):
for i in xrange(len(l) - 1, 0, -1):
if l[i] == l[i-1]:
del l[i-1:i+1]
return True
return False
def process_list(l):
print "input list: ",l
i=1
while(dedupe_adjacent(l)):
print " loop ",i,":",l
i+=1
print "processed list=",l
print
process_list([1,2,2,3,4,4,3,5])
process_list([1,2,2,3,4,4,6,3,5])
Output:
input list: [1, 2, 2, 3, 4, 4, 3, 5]
loop 1 : [1, 2, 2, 3, 3, 5]
loop 2 : [1, 2, 2, 5]
loop 3 : [1, 5]
processed list= [1, 5]
input list: [1, 2, 2, 3, 4, 4, 6, 3, 5]
loop 1 : [1, 2, 2, 3, 6, 3, 5]
loop 2 : [1, 3, 6, 3, 5]
processed list= [1, 3, 6, 3, 5]
The following:
function compress(arr) {
var prev, res = [];
for (var i in arr) {
if (i == 0 || (arr[i] != arr[i - 1]))
res.push(arr[i]);
}
return res;
}
compress([1, 2, 2, 3, 3, 3, 3, 4, 3, 3, 5, 6, 7, 8, 8]);
Returns:
[1, 2, 3, 4, 3, 5, 6, 7, 8]
Also (JavaScript 1.6 solution):
[1, 2, 2, 3, 3, 3, 3, 4, 3, 3, 5, 6, 7, 8, 8].filter(function(el, i, arr) {
return i == 0 || (el != arr[i - 1]);
})
Edit: Removing any item that appears in the array more than once requires a different solution:
function dedup(arr) {
var res = [], seen = {};
for (var i in arr)
seen[arr[i]] = seen[arr[i]] ? ++seen[arr[i]] : 1;
for (var j in arr) {
if (seen[arr[j]] == 1)
res.push(arr[j]);
}
return res;
}
The following:
dedup([1, 2, 2, 3, 4, 4, 3, 5]);
Produces:
[1, 5]
I have a solution to this in Java. You need to use replaceAll method in String class in Java. You can use regular expession to remove such adjacent redundant characters:
public class MyString {
public static void main(String[] args) {
String str = "12234435";
while(!str.replaceAll("(\\w)\\1+", "").equalsIgnoreCase(str))
str = str.replaceAll("(\\w)\\1+", "");
System.out.println(str);
}
}
You can find how to give a regular expression here
I would:
Sort the array.
From the start of the array, until you are at the last element of the array do:
`count` = count the number of array[i] elements.
remove the first `count` elements of the array if `count` > 1.
The following Python 3 code will remove duplicates from a list (array). It does this by scanning the array from start towards end and compares the target element with the element one larger. If they are the same they are removed. If the element pointer is not pointing at 0, then it is reduced by 1 in order to catch nested pairs. If the two compared elements are different then the pointer is incremented.
I'm sure there's a more pythonic way to remove two adjacent elements from a list, but I'm new to Python and haven't figured that out yet. Also, you'll want to get rid of the print(indx, SampleArray) statement--I left it in there to let you follow the progress in the output listing below.
# Algorithm to remove duplicates in a semi-sorted list
def CompressArray(SampleArray):
indx=0
while(indx < len(SampleArray)-1):
print(indx, SampleArray)
if(SampleArray[indx]==SampleArray[indx+1]):
del(SampleArray[indx])
del(SampleArray[indx])
if(indx>0):
indx-=1
else:
indx+=1
return SampleArray
Here are sample runs for:
[1, 2, 2, 3, 4]
[1, 2, 2, 3, 4, 4, 3, 5]
[1, 2, 2, 3, 3, 3, 3, 4, 3, 3, 5, 6, 7, 8, 8]
[1, 2, 2, 3, 4, 6, 7, 7, 6, 4, 3, 8, 8, 5, 9, 10, 10, 9, 11]
[1, 1, 2, 3, 3, 2, 4, 5, 6, 6, 5, 7, 8, 8, 7, 4, 9]
================================
0 [1, 2, 2, 3, 4]
1 [1, 2, 2, 3, 4]
0 [1, 3, 4]
1 [1, 3, 4]
[1, 3, 4]
================================
0 [1, 2, 2, 3, 4, 4, 3, 5]
1 [1, 2, 2, 3, 4, 4, 3, 5]
0 [1, 3, 4, 4, 3, 5]
1 [1, 3, 4, 4, 3, 5]
2 [1, 3, 4, 4, 3, 5]
1 [1, 3, 3, 5]
0 [1, 5]
[1, 5]
================================
0 [1, 2, 2, 3, 3, 3, 3, 4, 3, 3, 5, 6, 7, 8, 8]
1 [1, 2, 2, 3, 3, 3, 3, 4, 3, 3, 5, 6, 7, 8, 8]
0 [1, 3, 3, 3, 3, 4, 3, 3, 5, 6, 7, 8, 8]
1 [1, 3, 3, 3, 3, 4, 3, 3, 5, 6, 7, 8, 8]
0 [1, 3, 3, 4, 3, 3, 5, 6, 7, 8, 8]
1 [1, 3, 3, 4, 3, 3, 5, 6, 7, 8, 8]
0 [1, 4, 3, 3, 5, 6, 7, 8, 8]
1 [1, 4, 3, 3, 5, 6, 7, 8, 8]
2 [1, 4, 3, 3, 5, 6, 7, 8, 8]
1 [1, 4, 5, 6, 7, 8, 8]
2 [1, 4, 5, 6, 7, 8, 8]
3 [1, 4, 5, 6, 7, 8, 8]
4 [1, 4, 5, 6, 7, 8, 8]
5 [1, 4, 5, 6, 7, 8, 8]
[1, 4, 5, 6, 7]
================================
0 [1, 2, 2, 3, 4, 6, 7, 7, 6, 4, 3, 8, 8, 5, 9, 10, 10, 9, 11]
1 [1, 2, 2, 3, 4, 6, 7, 7, 6, 4, 3, 8, 8, 5, 9, 10, 10, 9, 11]
0 [1, 3, 4, 6, 7, 7, 6, 4, 3, 8, 8, 5, 9, 10, 10, 9, 11]
1 [1, 3, 4, 6, 7, 7, 6, 4, 3, 8, 8, 5, 9, 10, 10, 9, 11]
2 [1, 3, 4, 6, 7, 7, 6, 4, 3, 8, 8, 5, 9, 10, 10, 9, 11]
3 [1, 3, 4, 6, 7, 7, 6, 4, 3, 8, 8, 5, 9, 10, 10, 9, 11]
4 [1, 3, 4, 6, 7, 7, 6, 4, 3, 8, 8, 5, 9, 10, 10, 9, 11]
3 [1, 3, 4, 6, 6, 4, 3, 8, 8, 5, 9, 10, 10, 9, 11]
2 [1, 3, 4, 4, 3, 8, 8, 5, 9, 10, 10, 9, 11]
1 [1, 3, 3, 8, 8, 5, 9, 10, 10, 9, 11]
0 [1, 8, 8, 5, 9, 10, 10, 9, 11]
1 [1, 8, 8, 5, 9, 10, 10, 9, 11]
0 [1, 5, 9, 10, 10, 9, 11]
1 [1, 5, 9, 10, 10, 9, 11]
2 [1, 5, 9, 10, 10, 9, 11]
3 [1, 5, 9, 10, 10, 9, 11]
2 [1, 5, 9, 9, 11]
1 [1, 5, 11]
[1, 5, 11]
================================
0 [1, 1, 2, 3, 3, 2, 4, 5, 6, 6, 5, 7, 8, 8, 7, 4, 9]
0 [2, 3, 3, 2, 4, 5, 6, 6, 5, 7, 8, 8, 7, 4, 9]
1 [2, 3, 3, 2, 4, 5, 6, 6, 5, 7, 8, 8, 7, 4, 9]
0 [2, 2, 4, 5, 6, 6, 5, 7, 8, 8, 7, 4, 9]
0 [4, 5, 6, 6, 5, 7, 8, 8, 7, 4, 9]
1 [4, 5, 6, 6, 5, 7, 8, 8, 7, 4, 9]
2 [4, 5, 6, 6, 5, 7, 8, 8, 7, 4, 9]
1 [4, 5, 5, 7, 8, 8, 7, 4, 9]
0 [4, 7, 8, 8, 7, 4, 9]
1 [4, 7, 8, 8, 7, 4, 9]
2 [4, 7, 8, 8, 7, 4, 9]
1 [4, 7, 7, 4, 9]
0 [4, 4, 9]
[9]
================================
I love Java, but functional solutions should get more time on this site.
In Haskell, doing things the way the question asks:
compress lst = if (length lst == length b) then lst else (compress b) where
b = helper lst
helper [] = []
helper [x] = [x]
helper (x:y:xs) = if (x == y) then (helper xs) else (x:helper (y:xs))
You can solve this problem in O(n) time, although it is a bit more complicated
compress' lst = reverse (helper [] lst) where
helper xs [] = xs
helper [] (x:xs) = helper [x] xs
helper (a:as) (x:xs)
| a == x = helper as xs
| otherwise = helper (x:a:as) xs
I think we could use a stack to check adjacent duplicated elements.
Scan the array. For each new element, if it is equal to the top element in the stack, drop it and pop the top element from the stack. Otherwise, push it into the stack.
Here is the stack based algorithm based upon the edited question.
// pseudo code, not tested
void RemoveDupp(vector<int> & vin, vector<int> & vout)
{
int i = 0, int j = -1;
vout.resize(vin.size());
while (i < vin.size())
{
if (j == -1 || vout[j] != vin[i])
vout[++j] = vin[i++]; //push
else
j--, i++; //pop
}
vout.resize(j + 1);
}

Create an array with evenly-spaced values

What is an easy way to generate an array that has values with a fixed distance between them?
For example:
1, 4, 7, 10,... etc
I need to be able to set start, end, and step distance.
Try using Range.step:
> (1..19).step(3).to_a
=> [1, 4, 7, 10, 13, 16, 19]
In Ruby 1.9:
1.step(12).to_a #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
1.step(12,3).to_a #=> [1, 4, 7, 10]
Or you can splat instead of to_a:
a = *1.step(12,3) #=> [1, 4, 7, 10]

Resources