How do I find the location of an integer in an array of arrays in ruby? - ruby

Given:
a = [[1,2,3,4],
[1,2,3,7],
[1,2,3,4]]
What do I need to do to output the location of the 7 as (1,3)?
I've tried using .index to no avail.

require 'matrix'
a = [[1, 2, 3, 4],
[1, 2, 3, 7],
[1, 2, 3, 4]]
Matrix[*a].index(7)
=> [1, 3]

If your sub-arrays are all the same width, you can flatten it into a single array and think of the position as row_num * row_width + col_num:
idx = a.flatten.index(7)
row_width = a[0].length
row = idx / row_width
col = idx - (row * row_width)
puts [row, col] # => [1, 3]
Or you could just iterate it to find all matches:
def find_indices_for(array, value)
array.with_object([]).with_index do |(row, matches), row_index|
matches << [row_index, row.index(value)] if row.index(value)
end
end
find_indices_for(a, 7) # => [[1, 3]]
find_indices_for(a, 2) # => [[0, 1], [1, 1], [2, 1]]

each_with_index works pretty well here:
def locator(array, number)
locations = Array.new
array.each_with_index do |mini_array, index|
mini_array.each_with_index do |element, sub_index|
locations << [index, sub_index] if element == number
end
end
locations
end
Now, locator(array, number) will return an array of containing all the locations of number in array.

def locs2D(a,e)
a.size.times.with_object([]) do |row,arr|
row.size.times { |col| arr << [row,col] if a[row][col] == e }
end
end
locs2D(a,7) #=> [[1, 3]]
locs2D(a,3) #=> [[0, 2], [1, 2], [2, 2]]

Related

Another efficient way to write a nested "for" in ruby?

I have an exercise from HackerRank, that can easy resolve as the follow:
def divisibleSumPairs(n, k, ar)
validPairs = 0
for i in 0..ar.size-1
for j in i+1..ar.size-1
validPairs += 1 if (ar[i]+ar[j]) % k == 0
end
end
validPairs
end
n, k = gets.strip.split(' ')
n = n.to_i
k = k.to_i
ar = gets.strip
ar = ar.split(' ').map(&:to_i)
result = divisibleSumPairs(n, k, ar)
puts result;
But that nested for is bothering me. Is there any other way to do that in Ruby?
Yes. You can use combination method from Array class:
a = [1,2,3,4,5]
a.combination(2).to_a #=> [[1, 2], [1, 3], [1, 4], [1, 5], [2, 3], [2, 4], [2, 5], [3, 4], [3, 5], [4, 5]]
Then you can iterate on those pairs, so the code should look like that (haven't run it, though):
def divisibleSumPairs(n, k, ar)
validPairs = 0
ar.combination(2).each do |pair|
validPairs += 1 if (pair[0]+pair[1]) % k == 0
end
validPairs
end

leetcode first (the easiest) - two_sum

I wanted to practise some algorithms... Why doesn't my solution work on leetcode website?!?!
PS: Would be grateful for other resources to learn algorithms and practise interview questions.
# #param {Integer[]} nums
# #param {Integer} target
# #return {Integer[]}
def two_sum(nums, target)
i,j = 0,nums.length-1
output = []
while i < nums.length-1
while j > i
if nums[i] + nums[j] == target
output << i << j
end
j-=1
end
i+=1
end
output
end
Result from the website:
Input:
[3,2,4]
6
Output: []
Expected:[1,2]
Now that your question has been answered, I would like to suggest a more Ruby-like method.
Code
def two_sum(nums, target)
(0...nums.size).to_a.combination(2).find { |i,j| nums[i]+nums[j] == target }
end
Example
nums = [1,5,2,3,4]
target = 8
two_sum(nums, target)
#=> [1,3]
Explanation
For the example above, the steps are as follows:
a = nums.size
#=> 5
b = a.times
#=> #<Enumerator: 5:times>
c = b.to_a
#=> [0, 1, 2, 3, 4]
d = c.combination(2)
#=> #<Enumerator: [0, 1, 2, 3, 4]:combination(2)>
We can see the elements that are generated by the enumerator d by converting it to an array.
d.to_a
#=> [[0, 1], [0, 2], [0, 3], [0, 4], [1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]
d.find { |i,j| nums[i]+nums[j] == target }
#=> [1, 3]
Note that (0...nums.size).to_a could be replaced by any of the following.
[*0...nums.size]
nums.each_index.to_a
nums.size.times.to_a
0.upto(nums.size-1).to_a
Array.new(nums.size) { |i| i }
Array.new(nums.size, &:itself)
Your error is that you don't reinitialize j when it reaches i which means that your algorithm just tries (0,n-1), (0,n-2), …, (0, 2), (0, 1) and then stops.

Find combinations in Ruby that are less than a certain number

Say I have an array [1,2,3] and I want every combination of these numbers that don't exceed 4. So I would have [1,2,3].someMethod(4) and it would give me:
[1,1,1,1]
[1,1,2]
[1,3]
[2,2]
So far I have:
(1..4).flat_map{|size| [1,2,3].repeated_combination(size).to_a }
but this gives me every possible combinations, including the ones that exceed my given limit. Is there an good way to either only get combinations that add up to my limit?
arr = [1,2,3]
(arr+[0]).repeated_combination(4).select { |a| a.reduce(:+) == 4 }.map { |a| a - [0] }
#=> [[1, 3], [2, 2], [1, 1, 2], [1, 1, 1, 1]]
Change == to <= if desired.
This answer, like the others, assumes arr contains natural numbers, including 1.
results = (1..4).each.with_object([]) do |size, results|
[1,2,3].repeated_combination(size) do |combo|
results << combo if combo.reduce(:+) == 4
end
end
p results
--output:--
[[1, 3], [2, 2], [1, 1, 2], [1, 1, 1, 1]]
Parameterizing the algorithm:
def do_stuff(values, target_total)
(1..target_total).each.with_object([]) do |size, results|
values.repeated_combination(size) do |combo|
results << combo if combo.reduce(:+) == 4
end
end
end
p do_stuff([1, 2, 3], 4)
You can filter out the arrays you don't want by using the select method. Just select all the arrays that have a sum == 4 (the sum is calculated by the inject method).
all_arrs = (1..4).flat_map do |size|
[1,2,3].repeated_combination(size).to_a
end
valid_arrs = all_arrs.select do |arr|
arr.inject { |a, b| a + b } == 4
end
print valid_arrs
# Output:
# [[1, 3], [2, 2], [1, 1, 2], [1, 1, 1, 1]]
A recursive approach.
def some_method(a, n)
return [[]] if n == 0
a.select { |e| e <= n }.\
flat_map { |e| some_method(a,n-e).map { |es| ([e] + es).sort } }.\
sort.\
uniq
end
p some_method([1,2,3], 4)
# => [[1, 1, 1, 1], [1, 1, 2], [1, 3], [2, 2]]
EDIT: Here is another recursive version without filtering duplicates but with opposite order. I added comments to make it clearer.
def some_method(a, n)
return [[]] if n == 0 # bottom (solution) found
return [] if a.empty? || n < 0 # no solution
max = a.max
# search all solutions with biggest value
l = some_method(a, n-max).map { |e| [max] + e }
# search all solutions without biggest value
r = some_method(a-[max],n)
l + r
end
p some_method([1,2,3], 4)
# => [[3, 1], [2, 2], [2, 1, 1], [1, 1, 1, 1]]

Returning all maximum or minimum values that can be multiple

Enumerable#max_by and Enumerable#min_by return one of the relevant elements (presumably the first one) when there are multiple max/min elements in the receiver. For example, the following:
[1, 2, 3, 5].max_by{|e| e % 3}
returns only 2 (or only 5).
Instead, I want to return all max/min elements and in an array. In the example above, it would be [2, 5] (or [5, 2]). What is the best way to get this?
arr = [1, 2, 3, 5]
arr.group_by{|a| a % 3} # => {1=>[1], 2=>[2, 5], 0=>[3]}
arr.group_by{|a| a % 3}.max.last # => [2, 5]
arr=[1, 2, 3, 5, 7, 8]
mods=arr.map{|e| e%3}
find max
max=mods.max
indices = []
mods.each.with_index{|m, i| indices << i if m.eql?(max)}
arr.select.with_index{|a,i| indices.include?(i)}
find min
min = mods.min
indices = []
mods.each.with_index{|m, i| indices << i if m.eql?(min)}
arr.select.with_index{|a,i| indices.include?(i)}
Sorry for clumsy code, will try to make it short.
Answer by #Sergio Tulentsev is the best and efficient answer, found things to learn there. +1
This is the hash equivalent of #Serio's use of group_by.
arr = [1, 2, 3, 5]
arr.each_with_object(Hash.new { |h,k| h[k] = [] }) { |e,h| h[e%3] << e }.max.last
#=> [2, 5]
The steps:
h = arr.each_with_object(Hash.new { |h,k| h[k] = [] }) { |e,h| h[e%3] << e }
#=> {1=>[1], 2=>[2, 5], 0=>[3]}
a = h.max
#=> [2, [2, 5]]
a.last
#=> [2, 5]

Idiomatic ruby for generating permutations?

I'm wondering what the idiomatic version of this function for generating permutations would look like in Ruby. I understand that [1,2,3].permutation.to_a will generate the same result, but I'm more interested in learning Ruby and how to approach a recursive problem like this in Ruby.
def permutations(seq)
if seq.empty? || seq.count == 1
seq
else
seq.map { |x|
permutations(seq.select { |e| e != x }).map { |p|
if p.class == Fixnum
[x, p]
else
p.unshift(x)
end
}
}.flatten(1)
end
end
Thanks!
class Array
def permutations
return [self] if size < 2
perm = []
each { |e| (self - [e]).permutations.each { |p| perm << ([e] + p) } }
perm
end
end
[1, 2, 3].permutations #=> [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
Source: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/32844
Edit: To avoid monkey-patching, put it into a module:
module ArrayExtensions
def permutations
#snip
end
end
Array.send :include, ArrayExtensions
It's pretty common in Ruby (esp. Rails) to add functionality like this directly to the core class.
One alternative to that approach would be a separate, static utility module:
module ArrayUtils
def self.permute(array)
return [array] if array.size < 2
array.flat_map do |elem|
permute(array - [elem]).map do |perm|
([elem] + perm)
end
end
end
end
ArrayUtils.permute [1, 2, 3]
# => [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]

Resources