'how do i reverse individual (and specific) columns in a 2d array (RUBY)

RUBY the goal is to get the max value from each of the four zones and get their sum.

UPDATE I came up with a solution, I'm sorry about the mixup. It turned out that the matrix is a 2n x 2n matrix so it could have been greater or smaller than 4x4 in fact it. The solution i wrote below worked on all of the test cases. Here is a link to the problem

enter image description here

I tried doing matrix.transpose then I tried reversing the specific array, that didn't work for all edge cases. Here is the code for that

def flippingMatrix(matrix)
    2.times do
        matrix = matrix.transpose
        matrix = matrix.map do |array|
            if (array[-1] == array.max) || (array[-2] == array.max)
                array.reverse
            else
                array
            end
        end    
    end
    return matrix[0][0] + matrix[0][1] + matrix[1][0] + matrix[1][1]
end

I gave up and tried the below, which in my mind works, it also works for most edge cases but not all. But i'm getting an error (undefined method `[]' for nil:NilClass (NoMethodError)) keep in mind when I print the results or spot_1, spot_2, spot_3, or spot_4 I get the correct answer. does anyone have an idea why this is happening?

Here is a matrix that FAILED

[
[517, 37, 380, 3727], 
[3049, 1181, 2690, 1587], 
[3227, 3500, 2665, 383], 
[4041, 2013, 384, 965]
]
**expected output: 12,881 (this fails)**
**because 4041 + 2013 + 3227 + 3500 = 12,881**

Here is a matrix that PASSED

[
[112, 42, 83, 119],
[56, 125, 56, 49],
[15, 78, 101, 43],
[62, 98, 114, 108],
] 
**expected output: 414 (this passes)**

Here is the code

def flippingMatrix(matrix)
    # Write your code here 
    spot_1 = [matrix[0][0] , matrix[0][3] , matrix[3][0] , matrix[3][3]].max
    spot_2 = [matrix[0][1] , matrix[0][2] , matrix[3][1] , matrix[3][2]].max
    spot_3 = [matrix[1][0] , matrix[1][3] , matrix[2][0] , matrix[2][3]].max
    spot_4 = [matrix[1][1] , matrix[1][2] , matrix[2][1] , matrix[2][2]].max
    return (spot_1 + spot_2 + spot_3 + spot_4)
end 


Solution 1:[1]

I will answer your question and at the same time suggest two other ways to obtain the desired sum.

Suppose

arr = [
  [  1,   30,   40,   2],
  [300, 4000, 1000, 200],
  [400, 3000, 2000, 100],
  [  4,   10,   20,   3]
]

First solution

We see that the desired return value is 4444. This corresponds to

A B B A
C D D C
C D D C
A B B A

First create three helper methods.


Compute the largest value among the four inner elements

def mx(arr)
  [arr[1][1], arr[1][2], arr[2][1], arr[2][2]].max
end
mx(arr)
  #=> 4000

This is the largest of the "D" values.


Reverse the first two and last two rows

def row_flip(arr)
  [arr[1], arr[0], arr[3], arr[2]]
end
row_flip(arr)
  #=> [[300, 4000, 1000, 200],
  #    [  1,   30,   40,   2],
  #    [  4,   10,   20,   3],
  #    [400, 3000, 2000, 100]]

This allows us to use the method mx to obtain the largest of the "B" values.


Reverse the first two and last two columns

def column_flip(arr)
  row_flip(arr.transpose).transpose
end
column_flip(arr)
  #= [[  30,   1,   2,   40],
  #   [4000, 300, 200, 1000],
  #   [3000, 400, 100, 2000],
  #   [  10,   4,   3,   20]]

This allows us to use the method mx to obtain the largest of the "C" values.


Lastly, the maximum of the "A" values can be computed as follows.

t =  row_flip(column_flip(arr))
  #=> [[4000, 300, 200, 1000],
  #    [  30,   1,   2,   40],
  #    [  10,   4,   3,   20],
  #    [3000, 400, 100, 2000]]   
mx(column_flip(t))
  #=> 4

The sum of the maximum values may therefore be computed as follows.

def sum_max(arr)
  t = column_flip(arr) 
  mx(arr) + mx(row_flip(arr)) + mx(t) + mx(row_flip(t))
end
sum_max(arr)
  #=> 4444

Second solution

Another way is the following:

[0, 1].product([0, 1]).sum do |i, j|
  [arr[i][j], arr[i][-j-1], arr[-i-1][j], arr[-i-1][-j-1]].max
end
  #=> 4444

To see how this works let me break this into two statements add a puts statement. Note that, for each of the groups A, B, C and D, the block variables i and j are the row and column indices of the top-left element of the group.

top_left_indices = [0, 1].product([0, 1])
  #=> [[0, 0], [0, 1], [1, 0], [1, 1]]
top_left_indices.sum do |i, j|
  a = [arr[i][j], arr[i][-j-1], arr[-i-1][j], arr[-i-1][-j-1]]
  puts a
  a.max
end
  #=> 4444

The prints the following.

[1, 2, 4, 3]
[30, 40, 10, 20]
[300, 200, 400, 100]
[4000, 1000, 3000, 2000]

Solution 2:[2]

ahhh I came up with an answer that answers all edge cases. I originally saw something like this in Javascript and kind of turned it into Ruby. Apparently some of the hidden edge cases (that were hidden) weren't all 4 by 4 some were smaller and some larger, that was the cause of the nil error.

Here is the solution:

def flippingMatrix(matrix)
    total = []   
    (0...(matrix.length/2)).each do |idx1|
        (0...(matrix.length/2)).each do |idx2|
            total << [matrix[idx1][idx2], 
            matrix[(matrix.length - 1)-idx1][idx2], 
            matrix[idx1][(matrix.length - 1)-idx2], 
            matrix[(matrix.length - 1)-idx1][(matrix.length - 1)-idx2]].max
        end 
    end
    total.sum
end

Thank you all for your support! I hope this helps someone in the near future.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2