คำตอบสำหรับคำถามที่ผมตั้งเอง http://www.codenone.com/node/74
อันนี้เขียนแบบไร้ความสวยงามเลย แก้ class Matrix นิดหน่อย
require "Matrix" class Matrix def []=(i, j, v) @rows[i][j] = v end def gauss! n = column_size nn = row_size for i in 0..(n-2) p = -1 for k in i..(nn-1) if @rows[i][k] != 0 p = k break end end raise "No Solution" if p == -1 if p != i for h in i..(nn-1) @rows[h][i],@rows[h][p] = @rows[h][p],@rows[h][i] end end for j in (i+1)..nn-1 multiplier = @rows[j][i] / @rows[i][i] for k in 0..n-1 @rows[j][k] -= multiplier * @rows[i][k] end end end self end def gauss return clone.gauss! end def solve a = gauss() n = row_size()-1 x = Array.new x[n] = a[n,n+1]/a[n,n] (n-1).downto(0) { |i| sum = 0 i.upto(n) do |j| sum += a[i, j] *( ( x[j].nil? ) ? 0 : x[j]); end x[i] = (a[i,n+1]-sum) / a[i, i] } return x end end
มันน่าเกลียดน่ากลัวจัง
เวลาใช้ก็ประมาณนี้ครับ
m = Matrix[[8, 7.4, 8.225342], [7.4, 8.72, 10.731329]] m.solve >>[-0.512456823999999, 1.66554008]
กระทู้เก่าๆ จะย้ายตามไปในภายหลัง ตอนนี้ปิดการโพสต์กระทู้ไว้ เหลือไว้เฉพาะอ้างอิงเท่านั้น
ยากแฮะ ยังคิด version haskell ไม่ถึงไหนเลย (อยู่แถวๆ swap matrix)
เอา version ruby ไปก่อน
เขียนครั้งแรกหน้าตาคล้ายๆของ wiennat
ก็เลยปรับให้เป็น recursive
ไอ้ method solve นี่วิธีแบบเดียวกับ wiennat (ควรจะปรับให้สวยขึ้นได้ แค่ยังคิดไม่ออก)
แต่ method triangular นี่เป็นแบบ recursive
ส่วน class Matrix นี่เพิ่ม method อื้อเลย
ตรง swap_row นี่น่าจะเหลือแค่นี้ได้นะครับ
พอซาบซึ้งกับ algorithm แล้ว
เชียนอย่างนี้ก็ดี ไม่ต้องไปยุ่งกับ class Matrix
ตรง back_substitution ก็ทดลองใช้ zip กับ inject
ประมาณว่า
[1,2,3].zip([4,5,6]) => [[1,4],[2,5],[3,6]]
=> 1*4 + 2*5 + 3*6
ผมว่าแล้วว่ามันต้องมีคำสั่งประมาณนี้อยู่ ทั้ง inject ทั้ง zip เลย
เปิดหูเปิดตา ท่า zip ;-)