1

I have an array with many arrays inside (2d) (in this example there are four of them):

[
[13, 15, 18, 23, 23, 11, 14, 19, 19, 5, 10, 10, 8, 8], 
[8, 15, 19, 21, 21, 12, 16, 18, 18, 11, 13, 13, 6, 6], 
[9, 15, 21, 23, 23, 7, 13, 15, 15, 12, 14, 14, 8, 8], 
[2, 8, 14, 16, 16, 7, 13, 15, 15, 12, 14, 14, 8, 8]
]

I need to find if any element on any of these arrays is the same and at the same index as in other array. I need to get all those numbers and their indexes.

For ex. First_array[1] = 15, as well as second_array[1] = 15 and third_array[1] = 15. So I need these, with their indexes.

Also all needed values must come from arrays that are to the left or to the right to the array. For ex. - array_one[3] = 23, array_two[3] = 21 and array_three[3] = 23. I dont need these since array_two has a different value and it separates array_one from array_three.

And What I can get is the length of arrays (they all the same length) and the number of arrays, as variables.

I hope you got my point :)


Looks like I am abit closer to my goal. It seems this checks well for the second array (so only two first arrays being checked, but if this was done, the rest should be much easier). And do not judge me, judge just the code :D I know its ugly, its just a prototype:

array.each do |c|
   c.each do |v|
    c.each_with_index do |k, i|
      next_array = array[i + 1]
          if next_array.include? v 
            its_index = next_array.index(v) 
            if c.index(v) == its_index
            p v
          end
          end
        break
    end
   end 
   return
end
11
  • 2
    you did a good job describing what you need! however, you haven't posted any code showing your initial attempt. we're happy to help you get over a mental block or to find a bug in your code, but we don't give free from-scratch answers to prompts. Commented Apr 3, 2017 at 17:54
  • 2
    There are no multi-dimensional arrays in Ruby (unless you count Matrix from the standard library), just arrays of arrays and such. Commented Apr 3, 2017 at 18:05
  • @muistooshort: Technically, I guess you're correct. But what's wrong in considering an array of arrays as a 2D array? Commented Apr 3, 2017 at 18:23
  • Thanks all, my code is a bit messy - comments are all over etc, so will try to solve this by myself... But thanks anyway Commented Apr 3, 2017 at 18:24
  • 1
    @EricDuminil "AoA" == "array of arrays", "AoAoA" == "array of arrays of arrays", ... Commented Apr 3, 2017 at 19:26

4 Answers 4

3
arr = [[13, 15, 18, 23, 23, 11, 14, 19, 19,  5, 10, 10, 8, 8], 
       [ 8, 15, 19, 21, 23, 12, 16, 18, 19, 11, 13, 13, 6, 8], 
       [ 9, 15, 21, 23, 16, 12, 13, 15, 15, 12, 14, 14, 8, 8], 
       [ 2, 8,  14, 21, 16,  7, 13, 15, 15, 12, 14, 14, 8, 8]]

I've modified arr in a few places.

arr.transpose.each_with_index.with_object({}) do |(col,j),h|
  i = 0
  h[j] = col.chunk(&:itself).each_with_object({}) do |(x,arr),g|
    count = arr.size
    g.update(i=>{ value: x, number: count }) if count > 1
    i += count
  end
end
  #=> {0=>{},
  #    1=>{0=>{:value=>15, :number=>3}},
  #    2=>{},
  #    3=>{},
  #    4=>{0=>{:value=>23, :number=>2}, 2=>{:value=>16, :number=>2}},
  #    5=>{1=>{:value=>12, :number=>2}}
  #    6=>{2=>{:value=>13, :number=>2}},
  #    7=>{2=>{:value=>15, :number=>2}},
  #    8=>{0=>{:value=>19, :number=>2}, 2=>{:value=>15, :number=>2}},
  #    9=>{2=>{:value=>12, :number=>2}},
  #   10=>{2=>{:value=>14, :number=>2}},
  #   11=>{2=>{:value=>14, :number=>2}},
  #   12=>{2=>{:value=> 8, :number=>2}},
  #   13=>{0=>{:value=> 8, :number=>4}}} 

The keys of this hash are indices of columns of arr. The values are hashes that contain the locations and counts of all vertically-adjacent elements which appear at least twice. The columns at indices 0, 2 and 3, are the only ones that contains no vertically-adjacent duplicate values. The column at index 1 contains 3 15's beginning at row index 0; the column at index 4 contains 2 23's, beginning at row index 0 and 2 16's, beginning at row index 2.

Sign up to request clarification or add additional context in comments.

3 Comments

sorry, but, this answer is wrong, in position 3 should not have return... Take attention in the question's example. "For ex. - array_one[3] = 23, array_two[3] = 21 and array_three[3] = 23. I dont need these since array_two has a different value and it separates array_one from array_three." probably he is working in a image processing algorithm, maybe border detection or something like that
@Frederic, I think it is OK now.
Cary, now it seems ok.. very nice code btw. I did learnt alot with your code
1
matrix = [
  [13, 15, 18, 23, 23, 11, 14, 19, 19,  5, 10, 10, 8, 8], 
  [ 8, 15, 19, 21, 21, 12, 16, 18, 18, 11, 13, 13, 6, 6], 
  [ 9, 15, 21, 23, 23,  7, 13, 15, 15, 12, 14, 14, 8, 8], 
  [ 2,  8, 14, 16, 16,  7, 13, 15, 15, 12, 14, 14, 8, 8]
]

equal_surround = matrix
  .each_with_index.map do |v,i| 
    v.each_with_index.map do |k,j| 
      if (i-1>=0 && k == matrix[i-1][j])
         k
      elsif (i+1 < matrix.length && k == matrix[i+1][j]) 
         k 
      else
         nil  
      end
    end
  end
=> [
  [nil,  15, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil], 
  [nil,  15, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil], 
  [nil,  15, nil, nil, nil,   7,  13,  15,  15,  12,  14,  14,   8,   8], 
  [nil, nil, nil, nil, nil,   7,  13,  15,  15,  12,  14,  14,   8,   8]
]

Comments

0

You didn't show any code, so I won't write any either.

I can tell you that array#transpose should make this problem much more manageable, though.

You'll just need to iterate on the rows (former columns) and look for any repeating number.

You can either do it FORTRAN style with a loop or with fancier Enumerable methods, like each_with_index, map or chunk.

1 Comment

Thx, your advices will be written down and examined :)
0
test_array = [
[13, 15, 18, 23, 23, 11, 14, 19, 19, 5, 10, 10, 8, 8], 
[8, 15, 19, 21, 21, 12, 16, 18, 18, 11, 13, 13, 6, 6], 
[9, 15, 21, 23, 23, 7, 13, 15, 15, 12, 14, 14, 8, 8], 
[2, 8, 14, 16, 16, 7, 13, 15, 15, 12, 14, 14, 8, 8]
]
final_res = Hash.new {|h,k| h[k] = Array.new }

test_array.each_cons(2).to_a.each_with_index  do |(a,b),i|

    final_match = Hash.new {|h,k| h[k] = Array.new }

    res = a & b

    res.each do |ele|

        a_index = a.each_index.select{|i| a[i] == ele}
        b_index = b.each_index.select{|i| b[i] == ele}

        (a_index &  b_index).size > 0 ? final_match[ele] << (a_index &  b_index) : ''

    end

    final_match.each_value {|v| v.flatten!}

    final_res[:"Match Values Between Array #{i+1} amd Array #{i+2}"] << final_match

end 

final_res.each do |a|

puts a

end

OUTPUT:

Match Values Between Array 1 amd Array 2 {15=>[1]}

Match Values Between Array 2 amd Array 3 {15=>[1]}

Match Values Between Array 3 amd Array 4 {15=>[7, 8], 7=>[5], 13=>[6], 12=>[9], 14=>[10, 11], 8=>[12, 13]}

3 Comments

Thx, I will examine it more tomorrow, but at first sight, seems its not quite working. But maybe I am wrong
map is creating multiple unnecessary Array's in this code since all you are retaining is final_match. I did not vet this code any further other than each could be used in place of map to avoid needless overhead
shoot..! I missed the index part of the question ,was thinking to get the values alone. Have updated the code to include index too. @engineersmnky as per you suggestion have updated the map with each. would like suggestion on the code if there are issues.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.