Build and order an array with the first element of other arrays - ruby-on-rails

I'm trying to transform an array of 3 arrays in an array of 4 where each array is built and ordered with the first element of each other.
I have this:
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
And I would like the following:
[[1, 4, 7, 10], [2, 5, 8, 11], [3, 6, 9, 12]]
Any ideas?

Use Array#transpose.
your_array.transpose
will do it.

array = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
array.transpose
[[1, 4, 7, 10], [2, 5, 8, 11], [3, 6, 9, 12]]
Is this what you were looking for?

Related

I tried to solve n queens problem, but my program returns ... instead of

def attack(k,x):
for i in range(0,k-1):
if x[i]==x[k] or abs(x[i]-x[k])==abs(i-k):
return 1
return 0
def nQueens(n):
x=[]
for i in range(0,n):
x.append(-1)
k=0
solution=[]
while k>=0:
x[k]=x[k]+1
while x[k]<=n-1 and attack(k,x)==1:
x[k]=x[k]+1
if x[k]<=n-1:
if k==n-1:
solution.append(x)
else:
k=k+1
x[k]=0
else:
k=k-1
return solution
n=4
print(nQueens(n))
I tried to solve n queens problem, but my program returns
[[4, 4, 4, 4], [4, 4, 4, 4], [4, 4, 4, 4], [4, 4, 4, 4], [4, 4, 4, 4], [4, 4, 4, 4], [4, 4, 4, 4], [4, 4, 4, 4], [4, 4, 4, 4], [4, 4, 4, 4], [4, 4, 4, 4], [4, 4, 4, 4], [4, 4, 4, 4], [4, 4, 4, 4], [4, 4, 4, 4], [4, 4, 4, 4]]
instead of [[2, 4, 1, 3], [3, 1, 4, 2]]. Any suggestions where am I wrong?

Ruby array to subarray with fall factor

Is there any inbuilt method available to split large array into smaller chunks with dynamic fall factor?
Eg: i=0
src_arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
if batch_size = 5 and fall_factor = 1, first chunk should be [1, 2, 3, 4, 5] and subsequent array chunks should start from start_index = i * (batch_size - fall_factor). ie, start_index will be 0, 4, 8, 12, and
result: [1, 2, 3, 4, 5]
[5, 6, 7, 8, 9]
[9, 10, 11, 12, 13]
[13, 14]
if fall_factor = 2 result should be as below
[1, 2, 3, 4, 5]
[4, 5, 6, 7, 8]
[7, 8, 9, 10, 11]
[10, 11, 12, 13, 14]
I know how to SOLVE this. My question is if any inbuilt method available like each_slice to get this done instead of reinventing.
For example you can use just #step method of Numeric
0.step(src_arr.size - fall_factor - 1, batch_size - fall_factor).map do |ind|
src_arr[ind, batch_size]
end
# fall_factor = 1
# => [[1, 2, 3, 4, 5], [5, 6, 7, 8, 9], [9, 10, 11, 12, 13], [13, 14]]
# fall_factor = 2
# => [[1, 2, 3, 4, 5], [4, 5, 6, 7, 8], [7, 8, 9, 10, 11], [10, 11, 12, 13, 14]]
Code
def doit(arr, batch_size, fall_factor)
arr[batch_size..-1].
each_slice(batch_size-fall_factor).
each_with_object([arr[0,batch_size]]) { |b,c| c << [*c.last[-fall_factor..-1], *b] }
end
Examples
arr = (1..14).to_a
#=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
doit(arr, 5, 1)
#=> [[1, 2, 3, 4, 5], [5, 6, 7, 8, 9], [9, 10, 11, 12, 13], [13, 14]]
doit(arr, 5, 2)
#=> [[1, 2, 3, 4, 5], [4, 5, 6, 7, 8], [7, 8, 9, 10, 11], [10, 11, 12, 13, 14]]
doit(arr, 5, 3)
#=> [[1, 2, 3, 4, 5], [3, 4, 5, 6, 7], [5, 6, 7, 8, 9], [7, 8, 9, 10, 11],
# [9, 10, 11, 12, 13], [11, 12, 13, 14]]
doit(arr, 5, 4)
#=> [[1, 2, 3, 4, 5], [2, 3, 4, 5, 6], [3, 4, 5, 6, 7], [4, 5, 6, 7, 8],
# [5, 6, 7, 8, 9], [6, 7, 8, 9, 10], [7, 8, 9, 10, 11], [8, 9, 10, 11, 12],
# [9, 10, 11, 12, 13], [10, 11, 12, 13, 14]]
Explanation
For arr above and:
batch_size = 5
fall_factor = 2
we have:
a = arr[batch_size..-1]
#=> arr[5..-1]
#=> [6, 7, 8, 9, 10, 11, 12, 13, 14]
b = a.each_slice(batch_size-fall_factor)
#=> a.each_slice(3)
#=> #<Enumerator: [6, 7, 8, 9, 10, 11, 12, 13, 14]:each_slice(3)>
We can see the elements of the enumerator b by converting it to an array:
b.to_a
#=> [[6, 7, 8], [9, 10, 11], [12, 13, 14]]
Continuing:
d = [arr[0,batch_size]]
#=> [[1, 2, 3, 4, 5]]
b.each_with_object(d) { |b,c| c << [*c.last[-fall_factor..-1], *b] }
#=> [[1, 2, 3, 4, 5], [4, 5, 6, 7, 8], [7, 8, 9, 10, 11], [10, 11, 12, 13, 14]]
To see how the last calculation is performed, let:
e = b.each_with_object(d)
#=> #<Enumerator: #<Enumerator: [6, 7, 8, 9, 10, 11, 12, 13, 14]:
# each_slice(3)>:each_with_object([[1, 2, 3, 4, 5]])>
e.to_a
#=> [[[6, 7, 8], [[1, 2, 3, 4, 5]]],
# [[9, 10, 11], [[1, 2, 3, 4, 5]]],
# [[12, 13, 14], [[1, 2, 3, 4, 5]]]]
We can use Enumerator#next to obtain each element of e that is passed to the block, set the block variables to each of those values and perform the block calculation. The first element is passed to the block:
b, c = e.next
#=> [[6, 7, 8], [[1, 2, 3, 4, 5]]]
b #=> [6, 7, 8]
c #=> [[1, 2, 3, 4, 5]]
The block calculation is therefore:
c << [*c.last[-fall_factor..-1], *b]
#=> c << [*[[1, 2, 3, 4, 5]].last[-2..-1], *[6, 7, 8]]
# c << [*[1, 2, 3, 4, 5][-2..-1], *[6, 7, 8]]
# c << [*[4, 5], *[6, 7, 8]]
# c << [4, 5, 6, 7, 8]
c #=> [[1, 2, 3, 4, 5], [4, 5, 6, 7, 8]]
The next element of e is now passed to the block:
b, c = e.next
#=> [[9, 10, 11], [[1, 2, 3, 4, 5], [4, 5, 6, 7, 8]]]
b #=> [9, 10, 11]
c #=> [[1, 2, 3, 4, 5], [4, 5, 6, 7, 8]]
The remaining calculations are performed similarly.
Based on logic shared by you, below is one possible implementation:
b = 5 # batch size
f = 2 # fall factor
indices = (0...src_arr.size).collect {|i| i * (b-f)}.reject {|i| i + f >= src_arr.size}
result = indices.each_with_object([]) do |i, obj|
obj << src_arr[i, b]
end
p result
#=> [[1, 2, 3, 4, 5], [4, 5, 6, 7, 8], [7, 8, 9, 10, 11], [10, 11, 12, 13, 14]]

Sort array in Ruby on Rails

arr = [
[0, "Moving Companies", 10],
[0, "ab-thera-sensa", 5],
[0, "belt-center", 16],
[0, "isabel", 3],
[0, "kreatio", 2],
[0, "service1", 7],
[0, "sorbion-sachet-multi-star", 6],
[0, "sss", 15],
[0, "telecom-service-industry", 14],
[1, " AbsoPad", 13],
[1, "telecom-service", 8],
[2, "cutisorb-ultra", 12],
[2, "sorbion-contact", 11],
[2, "sorbion-sachet-multi-star", 9]
]
Suppose this is my array, now I want to sort it on the basis of the first element in descending order. I can do a arr.sort.reverse but the problem starts now
I get the array as :
[
[2, "sorbion-sachet-multi-star", 9],
[2, "sorbion-contact", 11],
[2, "cutisorb-ultra", 12],
[1, "telecom-service", 8],
[1, " AbsoPad", 13],
[0, "telecom-service-industry", 14],
[0, "sss", 15], [0, "sorbion-sachet-multi-star", 6],
[0, "service1", 7],
[0, "kreatio", 2],
[0, "isabel", 3],
[0, "belt-center", 16],
[0, "ab-thera-sensa", 5],
[0, "Moving Companies", 10]
]
Now the array should be sorted on the basis of the second element in ascending order.
How can that be achieved?
The result should look like :
[
[2, "cutisorb-ultra", 12],
[2, "sorbion-contact", 11],
[2, "sorbion-sachet-multi-star", 9],
[1,.......]
]
Customize the sorting with a block. First do a descending sort by the first element (0). If they are equal do instead an ascending sort by the second element (1):
arr.sort! do |a, b|
result = b[0] <=> a[0]
result = a[1] <=> b[1] if result == 0
result
end
How about this?
arr.sort { |i,j| [j[0],j[2]] <=> [i[0],i[2]] }
Outputs:
=> [[2, "cutisorb-ultra", 12],
[2, "sorbion-contact", 11],
[2, "sorbion-sachet-multi-star", 9],
[1, " AbsoPad", 13],
[1, "telecom-service", 8],
[0, "belt-center", 16],
[0, "sss", 15],
[0, "telecom-service-industry", 14],
[0, "Moving Companies", 10],
[0, "service1", 7],
[0, "sorbion-sachet-multi-star", 6],
[0, "ab-thera-sensa", 5],
[0, "isabel", 3],
[0, "kreatio", 2]]
please try:
arr.sort_by{|x|[-x[0],-x[2]]}

Ruby "bucketize" an array

Suppose I have the following array:
a = (1..10).to_a
Is there a single in-built ruby (or rails) function that is capable or splitting the array into exactly N roughly equal parts while maintaining the order?
I'm looking for something like this:
a.bucketize(3)
=> [[1,2,3,4],[5,6,7],[8,9,10]]
a.bucketize(5)
=> [[1,2],[3,4],[5,6],[7,8],[9,10]]
Hint: each_slice doesn't do this.
Also, I know I could write this function myself and open up the Array class or Enumerable module.
Thanks.
I'd do it like this:
ary = (1..10).to_a
ary.each_slice((ary.length.to_f/3).ceil).to_a
=> [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10]]
ary.each_slice((ary.length.to_f/5).ceil).to_a
=> [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
It's not perfect, but it does come close:
ary = (1..9).to_a
=> [1, 2, 3, 4, 5, 6, 7, 8, 9]
ary.each_slice((ary.length.to_f/2).ceil).to_a
=> [[1, 2, 3, 4, 5], [6, 7, 8, 9]]
ary.each_slice((ary.length.to_f/3).ceil).to_a
=> [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
ary.each_slice((ary.length.to_f/4).ceil).to_a
=> [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
This kind of task is best tackled using a functional approach. Here's a tail-recursive functional implementation (except for the unavoidable << to accumulate efficiently on arrays):
class Array
def bucketize(n, index = 0, acc = [])
return acc if n <= 0 || size <= index
n0 = ((size - index).to_f / n).ceil
bucketize(n - 1, index + n0, acc << self[index, n0])
end
end
(1..9).to_a.bucketize(3)
#=> [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
(1..10).to_a.bucketize(3)
#=> [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]
(1..11).to_a.bucketize(3)
#=> [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11]]
Here's what I ended up doing:
class Array
def bucketize(n)
return [] if (buckets = n.to_i) <= 0
j = length / buckets.to_f
result = each_with_index.chunk { |_, i| (i / j).floor }.map { |_, v| v.map(&:first) }
result << [] until result.length == buckets
result
end
end
Examples:
a = (1..10).to_a
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
a.bucketize(1)
=> [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]
a.bucketize(2)
=> [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]
a.bucketize(3)
=> [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]
a.bucketize(4)
=> [[1, 2, 3], [4, 5], [6, 7, 8], [9, 10]]
...
a.bucketize(9)
=> [[1, 2], [3], [4], [5], [6], [7], [8], [9], [10]]
...
a.bucketize(11)
=> [[1], [2], [3], [4], [5], [6], [7], [8], [9], [10], []]

ruby array iteration

I have four arrays(named array1,2,3,4) each with 8 objects and want to sort them into 8 empty arrays that will consist of 4 objects each, i.e place each object from array 1 into an empty array.
?? << array1.shift until array.empty?
I'm not sure how to iterate over the 8 empty arrays so that each of them recieves an object from array1
e.g
array1 = clubs1-8
array2 = spades1-8
array3 = hearts1-8
array4 = diamonds1-8
8 empty arrays or players, each player is dealt a card from array1,then 1 card from array2 etc.
Thanks for the answers but I wanted to add the objects iteratively so I could add conditions based on what objects had already been added to each array
e.g
distribute array1 among 8 empty arrays
distribute array2 among the 8 arrays but check before that no array contains the same card number (it can't have both the 2 of hearts and the 2 of diamonds)
Did you mean something like this?
require "matrix"
a1 = (0..7).to_a
a2 = (8..15).to_a
a3 = (16..23).to_a
a4 = (24..31).to_a
Matrix[a1, a2, a3, a4].transpose.to_a #=> [[0, 8, 16, 24], [1, 9, 17, 25], [2, 10, 18, 26], [3, 11, 19, 27], [4, 12, 20, 28], [5, 13, 21, 29], [6, 14, 22, 30], [7, 15, 23, 31]]
Added:
In fact it is even more trivial:
a1.zip(a2, a3, a4) #=> [[0, 8, 16, 24], [1, 9, 17, 25], [2, 10, 18, 26], [3, 11, 19, 27], [4, 12, 20, 28], [5, 13, 21, 29], [6, 14, 22, 30], [7, 15, 23, 31]]
Iteration is not the only way. Try this (assuming a1..a8 are your 8 empty arrays):
a1, a2, a3, a4, a5, a6, a7, a8 = array1.zip(array2, array3, array4)
irb(main):001:0> ar1 = [1,2,3,4,5,6,7,8]
=> [1, 2, 3, 4, 5, 6, 7, 8]
irb(main):002:0> ar2 = [2,3,4,1,2,3,2,1]
=> [2, 3, 4, 1, 2, 3, 2, 1]
irb(main):003:0> ar3 = [4,3,5,6,3,3,4,5]
=> [4, 3, 5, 6, 3, 3, 4, 5]
irb(main):004:0> ar4 = [5,2,5,6,7,2,2,5]
=> [5, 2, 5, 6, 7, 2, 2, 5]
irb(main):005:0> ar1.zip(ar2,ar3,ar4)
=> [[1, 2, 4, 5], [2, 3, 3, 2], [3, 4, 5, 5], [4, 1, 6, 6], [5, 2, 3, 7], [6, 3, 3, 2], [7, 2, 4, 2], [8, 1, 5, 5]]

Resources