leandro (owner)

Revisions

gist: 200887 Download_button fork
public
Public Clone URL: git://gist.github.com/200887.git
Embed All Files: show embed
tmp.rb #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
require 'matrix'
 
module FixnumExt
  def square?
    sqrt = self ** (1.0/2)
    (sqrt - sqrt.to_i).zero?
  end
end
 
module MatrixDeterminant
 
  def det2
    return nil unless self.square?
    return self[0,0] if self.row_size == 1
    return self[0,0] * self[1,1] - self[0,1] * self[1,0] if self.row_size == 2
    return self[0,0] * self[1,1] * self[2,2] + self[1,0] * self[2,1] * self[0,2] + self[2,0] * self[0,1] * self[1,2] -
      self[0,2] * self[1,1] * self[2,0] - self[0,0] * self[1,2] * self[2,1] - self[0,1] * self[1,0] *
      self[2,2] if self.row_size == 3
 
    # calculating determinant for 4x4 or bigger
    most_zeros_line = self.lowest_cost_line
    _row = most_zeros_line > 0
    line_index = _row ? most_zeros_line - 1 : most_zeros_line.abs - 1
    line = (_row ? self.row(line_index) : self.column(line_index)).to_a
    sum = 0
    line.each_index {|k| sum += line[k].zero? ? 0 : line[k] * (_row ? self.minor2(line_index, k).det2 : self.minor2(k, line_index).det2)}
    sum
  end
 
  def lowest_cost_line
    rows = self.to_a.map {|e| e - [0]}
    cols = self.transpose.to_a.map {|e| e - [0]}
 
    lowest_row = rows.index(rows.inject(rows.first) {|lowest, e| lowest.size > e.size ? e : lowest})
    lowest_col = cols.index(cols.inject(cols.first) {|lowest, e| lowest.size > e.size ? e : lowest})
    rows[lowest_row].size <= cols[lowest_col].size ? lowest_row + 1 : - (lowest_col + 1)
  end
 
  def cofactor(modulus = nil)
    return nil unless self.row_size == self.column_size && self.row_size > 1
    r = []
 
    self.row_size.times do |i|
      r << (crow = [])
      self.column_size.times do |j|
        value = ((i + j + 2) * -1) * self.minor2(i, j).det2
        value = value % modulus if modulus
        crow << value
      end
    end
    Matrix[*r]
  end
 
  def minor2(row, col)
    r = []
 
    self.row_size.times do |i|
      next if i == row
      r << (crow = [])
 
      self.column_size.times do |j|
        next if j == col
        crow << self[i,j]
      end
 
    end
    Matrix[*r]
  end
end
 
module MatrixCoreExt
 
  def self.included(base)
    base.extend ClassMethods
  end
 
  module ClassMethods
    def square_from_rows *members
      return nil unless members.size.square?
 
      msize = (members.size ** (1.0/2)).to_i
      matrix = []
      members.each_slice(msize) {|s| matrix << s}
      Matrix[*matrix]
    end
  end
 
  def % num
    r = []
 
    self.row_size.times do |i|
      r << (crow = [])
      self.column_size.times do |j|
        crow << self[i,j] % num
      end
    end
    Matrix[*r]
  end
 
end
 
module Main
 
  class ::Matrix
    include MatrixDeterminant
    include MatrixCoreExt
  end
 
  class ::Fixnum
    include FixnumExt
  end
 
end
 
include Main
Matrix.square_from_rows(0,6,0,0,0,0,7,0,0,5,4,5,1,2,1,6,2,1,4,2,3,2,0,2,1).det2