Randomizing array elements - ruby

I have an array #number = [1,2,3,4,5,6,7,8,9]
Now, I want to randomize the array content... something like eg: [5,3,2,6,7,1,8]
Please guide me how to proceed with it.

Use the shuffle method ...
irb(main):001:0> [1,2,3,4,5].shuffle
=> [3, 4, 2, 5, 1]

the shuffle command returns a randomized version of an array
eg:
[1,2,3].shuffle => [2,3,1]

[1,2,3,4,5,6,7,8,9].sort_by {rand}[0,9]
=> [5, 7, 3, 8, 9, 4, 2, 1, 6]

If you are using old version of ruby... this will work
def randomize(array)
b = []
array.length.downto(1) { |n|
b.push array.delete_at(rand(n))
}
b
end
a = [1,2,3,4,5]
b=randomize(a)
print b

loop n times
i = random array index
j = random array index
swap elements i and j
end

Related

How can I remove duplicates in an array without using `uniq`?

The object of my coding exercise is to get rid of duplicates in an array without using the uniq method. Here is my code:
numbers = [1, 4, 2, 4, 3, 1, 5]
def my_uniq(array)
sorted = array.sort
count = 1
while count <= sorted.length
while true
sorted.delete_if {|i| i = i + count}
count += 1
end
end
return sorted
end
When I run this, I get an infinite loop. What is wrong?
Can I use delete the way that I am doing with count?
How will it execute? Will count continue until the end of the array before the method iterates to the next index?
I did this with each or map, and got the same results. What is the best way to do this using each, delete_if, map, or a while loop (with a second loop that compares against the first one)?
Here is a clearly written example.
numbers = [1, 4, 2, 4, 3, 1, 5]
def remove_duplicates(array)
response = Array.new
array.each do |number|
response << number unless response.include?(number)
end
return response
end
remove_duplicates(numbers)
As others pointed out, your inner loop is infinite. Here's a concise solution with no loops:
numbers.group_by{|n| n}.keys
You can sort it if you want, but this solution doesn't require it.
the problem is that the inner loop is an infinite loop:
while true
sorted.delete_if {|i| i = i + count}
count += 1
end #while
you can probably do what you are doing but it's not eliminating duplicates.
one way to do this would be:
numbers = [1, 4, 2, 4, 3, 1, 5]
target = []
numbers.each {|x| target << x unless target.include?(x) }
puts target.inspect
to add it to the array class:
class ::Array
def my_uniq
target = []
self.each {|x| target << x unless target.include?(x) }
target
end
end
now you can do:
numbers = [1, 4, 2, 4, 3, 1, 5]
numbers.my_uniq
You count use Set that acts like an array with does not allow duplicates:
require 'set'
numbers = [1, 4, 2, 4, 3, 1, 5]
Set.new(numbers).to_a
#=> [1, 4, 2, 3, 5]
Try using Array#& passing the array itself as parameter:
x = [1,2,3,3,3]
x & x #=> [1,2,3]
This is one of the answer. However, I do not know how much of performance issue it takes to return unique
def my_uniq(ints)
i = 0
uniq = []
while i < ints.length
ints.each do |integers|
if integers == i
uniq.push(integers)
end
i += 1
end
end
return uniq
end

cycle through array using index

I have an array
arr = [1,2,3,4,5]
and I'm wondering if there is a way to cycle through it so something like:
i = 2
arr[3+n]
would return 1, rather than nil
Is that possible using the index, or even with next?
It's called cycle:
c = [1,2,3,4,5].cycle
10.times{p c.next}
Perform a modulo on the index using the array size:
arr = [1, 2, 3, 4, 5]
arr[5 % arr.size] #=> 1

How to refactor this code to remove output variable?

def peel array
output = []
while ! array.empty? do
output << array.shift
mutate! array
end
output.flatten
end
I have not included the mutate! method, because I am only interested in removing the output variable. The mutate! call is important because we cannot iterate over the array using each because array is changing.
EDIT: I am getting an array as output, which is what I want. The method works correctly, but I think there is a way to collect the array.shift values without using a temp variable.
EDIT #2: OK, here is the mutate! method and test case:
def mutate! array
array.reverse!
end
a = (1..5).to_a
peel( a ).should == [ 1, 5, 2, 4, 3 ]
It doesn't matter if peel modifies array. I guess it should be called peel!. Yes, mutate! must be called after each element is removed.
All this reversing makes me dizzy.
def peel(array)
indices = array.size.times.map do |i|
i = -i if i.odd?
i = i/2
end
array.values_at(*indices) # indices will be [0, -1, 1, -2, 2] in the example
end
a = (1..5).to_a
p peel(a) #=>[1, 5, 2, 4, 3]
Another approach:
def peel(array)
mid = array.size/2
array[0..mid]
.zip(array[mid..-1].reverse)
.flatten(1)
.take(array.size)
end
Usage:
peel [1,2,3,4,5,6]
#=> [1, 6, 2, 5, 3, 4]
peel [1,2,3,4,5]
#=> [1, 5, 2, 4, 3]
Here's a way using parallel assignment:
def peel array
n = array.size
n.times {|i| (n-2-2*i).times {|j| array[n-1-j], array[n-2-j] = array[n-2-j], array[n-1-j]}}
array
end
peel [1,2,3,4,5] # => [1,5,2,4,3]
peel [1,2,3,4,5,6] # => [1,6,2,5,3,4]
What I'm doing here is a series of pairwise exchanges. By way of example, for [1,2,3,4,5,6], the first 6-2=4 steps (6 being the size of the array) alter the array as follows:
[1,2,3,4,6,5]
[1,2,3,6,4,5]
[1,2,6,3,4,5]
[1,6,2,3,4,5]
The 1, 6 and the 2 are in now the right positions. We repeat these steps, but this time only 6-4=2 times, to move the 5 and 3 into the correct positions:
[1,6,2,3,5,4]
[1,6,2,5,3,4]
The 4 is pushed to the end, it's correct position, so we are finished.

How to drop the end of an array in Ruby

Array#drop removes the first n elements of an array. What is a good way to remove the last m elements of an array? Alternately, what is a good way to keep the middle elements of an array (greater than n, less than m)?
This is exactly what Array#pop is for:
x = [1,2,3]
x.pop(2) # => [2,3]
x # => [1]
You can also use Array#slice method, e.g.:
[1,2,3,4,5,6].slice(1..4) # => [2, 3, 4, 5]
or
a = [1,2,3,4,5,6]
a.take 3 # => [1, 2, 3]
a.first 3 # => [1, 2, 3]
a.first a.size - 1 # to get rid of the last one
The most direct opposite of drop (drop the first n elements) would be take, which keeps the first n elements (there's also take_while which is analogous to drop_while).
Slice allows you to return a subset of the array either by specifying a range or an offset and a length. Array#[] behaves the same when passed a range as an argument or when passed 2 numbers
this will get rid of last n elements:
a = [1,2,3,4,5,6]
n = 4
p a[0, (a.size-n)]
#=> [1, 2]
n = 2
p a[0, (a.size-n)]
#=> [1, 2, 3, 4]
regard "middle" elements:
min, max = 2, 5
p a.select {|v| (min..max).include? v }
#=> [2, 3, 4, 5]
I wanted the return value to be the array without the dropped elements. I found a couple solutions here to be okay:
count = 2
[1, 2, 3, 4, 5].slice 0..-(count + 1) # => [1, 2, 3]
[1, 2, 3, 4, 5].tap { |a| a.pop count } # => [1, 2, 3]
But I found another solution to be more readable if the order of the array isn't important (in my case I was deleting files):
count = 2
[1, 2, 3, 4, 5].reverse.drop count # => [3, 2, 1]
You could tack another .reverse on there if you need to preserve order but I think I prefer the tap solution at that point.
You can achieve the same as Array#pop in a non destructive way, and without needing to know the lenght of the array:
a = [1, 2, 3, 4, 5, 6]
b = a[0..-2]
# => [1, 2, 3, 4, 5]
n = 3 # if we want drop the last n elements
c = a[0..-(n+1)]
# => [1, 2, 3]
Array#delete_at() is the simplest way to delete the last element of an array, as so
arr = [1,2,3,4,5,6]
arr.delete_at(-1)
p arr # => [1,2,3,4,5]
For deleting a segment, or segments, of an array use methods in the other answers.
You can also add some methods
class Array
# Using slice
def cut(n)
slice(0..-n-1)
end
# Using pop
def cut2(n)
dup.tap{|x| x.pop(n)}
end
# Using take
def cut3(n)
length - n >=0 ? take(length - n) : []
end
end
[1,2,3,4,5].cut(2)
=> [1, 2, 3]

Ruby: Multiply all elements of an array

Let's say I have an array A = [1, 2, 3, 4, 5]
how can I multiply all elements with ruby and get the result? 1*2*3*4*5 = 120
and what if there is an element 0 ? How can I ignore this element?
This is the textbook case for inject (also called reduce)
[1, 2, 3, 4, 5].inject(:*)
As suggested below, to avoid a zero,
[1, 2, 3, 4, 5].reject(&:zero?).inject(:*)
There is also another way to calculate this factorial!
Should you want to, you can define whatever your last number is as n.
In this case, n=5.
From there, it would go something like this:
(1..num).inject(:*)
This will give you 120. Also, .reduce() works the same way.
Well, this is a dummy way but it works :)
A = [1, 2, 3, 4, 5]
result = 1
A.each do |i|
if i!= 0
result = result*i
else
result
end
end
puts result
If you want to understand your code later on, use this: Assume A = 5, I used n instead of A
n = 5
n.times {|x| unless x == 0; n = n * x; ++x; end}
p n
To carry it forward, you would:
A = [1,2,3,4,5]
arb = A.first
a = A.count
a.times {|x| arb = arb * A[x]; ++x}
p arb

Resources