「CodeWars」Matrix

Published on:
Tags: ruby CodeWars

本文为「CodeWars」6ku级别的题: Matrix

我在QQ群:222359552 里发起一个每周不定时活动:答题送视频优惠码, 这是我自己的解答。。


关于题的描述

Write a function that accepts two square matrices (nxn two dimensional arrays), and return the sum of the two. Both matrices being passed into the function will be of size nxn (square), containing only integers.

How to sum two matrices:
Take each cell [n][m] from the first matrix, and add it with the [n][m] cell from the second matrix.> This will be cell [n][m] in the solution matrix.

Visualization:
|1 2 3|
|3 2 1|
|1 1 1|
+
|2 2 1|
|3 2 3|
|1 1 3|

result =:

|3 4 4|
|6 4 4|
|2 2 4|

Example function call:
matrixAddition( [ [1, 2, 3], [3, 2, 1,], [1, 1, 1] ], [ [2, 2, 1], [3, 2, 3], [1, 1, 3] ] );
returns [ [3, 4, 4], [6, 4, 4], [2, 2, 4] ]

本题是给出一个矩阵,让你计算矩阵的和。

背景知识

矩阵(Matrix),是数学中最重要的基本概念之一,关于其具体的数学概念及其应用,可以去查维基百科

在Ruby中,可以用一个二维数组来表示矩阵。比如:

[
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
]

而Ruby的标准库中,也实现了一个Matrix类,来帮助你方便的操作矩阵。

而对于这次CodeWars的题,我自己实现了一个简单的矩阵类。

自己实现的矩阵类Matrix

class Matrix
  class CantCreateMatrixError < ::StandardError; end

  attr_accessor :matrix

  def initialize(*arr)
    begin
      arr.each do |a|
        raise CantCreateMatrixError, "Does not meet specifications" if a.size != arr[0].size
      end
      @matrix = arr
    end
  end

  def self.[](*arr)
    new(*arr)
  end

  def +(other)
    other.matrix.each_index.inject([]) do |arr, index|
      matrix_row = self.row(index)
      arr << matrix_row.size.times.inject([]) do |new_row, i|
        new_row << matrix_row[i] + other.row(index)[i]
      end
    end
  end

  def cloumn(index=0)
    matrix.map{|arr| arr[index]}
  end

  def row(index=0)
    matrix[index]
  end

  def cloumns
    s = []
    matrix[0].size.times do |index|
      s << cloumn(index)
    end
    s
  end
end

用法:

# 创建矩阵

matrix1 = Matrix[
                 [1, 2, 3], 
                 [3, 2, 1], 
                 [1, 1, 1]
                ]
matrix2 = Matrix[
                 [2, 2, 1],
                 [3, 2, 3], 
                 [1, 1, 3]
                ]
                
                
# 如果你创建的矩阵不符合规范,则会报错

error_matrix = Matrix[
                        [1, 2],
                        [3, 4, 5],
                        [1, 3, 5, 6]
              ]
#=> Matrix::CantCreateMatrixError: Does not meet specifications



# 获取矩阵行数组

matrix1.row(0)
matrix1.row(1)
matrix1.row(2)

# 获取矩阵列数组

matrix2.cloumn(0)
matrix2.cloumn(1)
matrix2.cloumn(2)

# 按列获取矩阵,返回数组

matrix2.cloumns

# 求两个矩阵之和

matrix1 + matrix2



以上代码可以扩展各种操作, 比如乘除减等。 当然这段代码还有很多改进空间。

至此,Codewars的题就迎刃而解了:

def matrixAddition(a, b)
  Matrix[*a] + Matrix[*b]
end

Test.assert_equals(matrixAddition([[1, 2], [1, 2]], [[2, 3], [2, 3]]),[[3, 5], [3, 5]]);
#=> true

其他解法

Codewars上面很多其他解法,利用了Ruby提供的内建方法,也值得一看:

def matrixAddition(a, b)
  a.zip(b).map { |r| r.transpose.map { |c| c.reduce(:+) } }
end

利用了内建的Array#transpose方法。

def matrixAddition(a, b)
  new_array = []  
  a.each_with_index do |array, index|
    new_array << a[index].zip(b[index]).map{|pair| pair.reduce(&:+)}
  end
  new_array
end
def matrixAddition(a, b)
  (0...a.length).map do |i|
    (0...a[0].length).map do |j|
      a[i][j] + b[i][j]
    end
  end
end
def matrixAddition(a, b)
  b = b.flatten
  sum = a.flatten.map.with_index {|v,i| v + b[i] }.each_slice(a.length).to_a  
end

还有很多, 大体思路都差不多,像我那样写一个类,还是比较少的,大家的目的不同。

不知道你们的解题思路是哪一种呢?

Comments

comments powered by Disqus