From: "Jens Häßler" <vikingjens@gmx.de>
Date: August 22, 2007 9:30:51 AM CDT
To: submission@rubyquiz.com <submission@rubyquiz.com>
Subject: Solution for RubyQuiz 131I really liked thinking about these arrays even if I am a little late...
After a few tries, which compared all possible subarrays, I found a O(n) solution. I like my solution, because it is written in a quite simple style.
The algorithm does add the numbers until the sum is getting smaler then 0. If thats the case, then it would make no sence to add this subarray with following subarrays, because they would become smaller.Thats the idea and because that it is so simple, it quite fast.
def max_subarray(array)
total=array[0]
borders=0..0first=0
subtotal=0
for last in 0..(array.length-1) do
subtotal+=array[last]
if subtotal>total then
total=subtotal
borders=first..last
endif subtotal<=0 then
first=last+1
subtotal=0
end
endreturn [total, borders]
endI also had some ideas about the matrices. First, of course, I compared all possible submatrices. Fast programmed but extreme slow, especially with larger matrices.
So the idea is, to create an algorithm, that uses the max_subarray method within. I'm generating the rows by adding rows together and I'm doing this with all possible combination of the rows.
(with 3 rows: 0, 0+1, 0+1+2, 1, 1+2, 2)def max_submatrix(matrix)
total=matrix[0][0]
borders_row=0..0
borders_column=0..0for first in 0..(matrix.length-1) do
array=Array.new(matrix[first].length){0}
for last in (first)..(matrix.length-1) do
for index in 0..(matrix[last].length-1) do
array[index]+=matrix[last][index]
endsubtotal=max_subarray(array)
if subtotal[0]>total then
total=subtotal[0]
borders_row=subtotal[1]
borders_column=first..last
end
end
endreturn [total, borders_row, borders_column]
endBecause I use all combinations of the colums, the algorithm slows extremly down when the matrix consists of one large column like (1, 500). In that case, the max_subarray method is not going into action (its just comparing the rows, consisting of one number) and we are comparing all possible combinations.
So what I decided to do is to tell the algorithm to reverse the matrix. A (1, 500) matrix would become a (500, 1) matrix and the max_subarray method only has to run one time through the matrix. I reverse the matrix when there are more rows than columns. The less rows the faster comparing.
I did not reverse the matrix manually. I did more tell the programm which indices had to be permuted.def max_submatrix_2(matrix)
if matrix.length<=matrix[0].length then
row=matrix.length
column=matrix[0].length
reverse=false
else
row=matrix[0].length
column=matrix.length
reverse=true
endtotal=matrix[0][0]
borders_row=0..0
borders_column=0..0for first in 0..(row-1) do
array=Array.new(column){0}
for last in (first)..(row-1) do
if reverse then
for index in 0..(column-1) do
array[index]+=matrix[index][last]
endsubtotal=max_subarray(array)
if subtotal[0]>total then
total=subtotal[0]
borders_row=first..last
borders_column=subtotal[1]
end
else
for index in 0..(column-1) do
array[index]+=matrix[last][index]
endsubtotal=max_subarray(array)
if subtotal[0]>total then
total=subtotal[0]
borders_row=subtotal[1]
borders_column=first..last
end
end
end
endreturn [total, borders_row, borders_column]
endIts nice to see, that these ones are so fast.
For a (1000, 80) matrix, max_submatrix_2(matrix) needs 14sec, for (1000000, 1) 4sec and for (1, 1000000) also 4sec.Was fun programming this.
--
GMX FreeMail: 1 GB Postfach, 5 E-Mail-Adressen, 10 Free SMS.
Alle Infos und kostenlose Anmeldung: GMX E-Mail ✉ sichere & kostenlose E-Mail-Adresse ✉
···
Begin forwarded message: