Thanks to Raul for pointing out the Rosetta Stone entries at

https://rosettacode.org/wiki/Greatest_subsequential_sum#J

I tried

   ts ' maxss q16' [q16 =: 2#8000$ '

but gave up waiting,  seeing Windows' Task Manager's display of total memory

climbing towards 15GB.

Then I spotted maxSS and maxSS2 in the Rosetta posting,  both of which are

much faster than my mxsa and mxsasum, though they use more space:

   ts'mxsasum q16'
0.033302 134208

   ts'mxsa q16'
0.115605 265216

   ts'maxSS q16'    NB. Rosetta
0.00455016 1.15693e6

   ts'maxSS2 q16'   NB. Rosetta
0.00405449 1.15757e6

   ts'f q16'  NB. Jon Hough's post
2.63228 3.48282e6

I had second thoughts about a crude but simple approach - this isn't as bad

as all that:

mxsasumcrude =: >./@:(+/\)\

    ts'mxsasumcrude q16'

1.10747 263616


Still not too bad for space,  but pretty slow.

Cheers,

Mike

On 24/02/2019 14:06, 'Mike Day' via Programming wrote:
OK, Jon - I looked at wiki and implemented Kadane,  with mxsasum (explicit) and mxsasumt (tacit)

returning just the best sum,  while mxsa returns the subarray.


NB. Kadane's algorithm as presented in wiki
NB. def max_subarray(A):
NB.     max_ending_here = max_so_far = A[0]
NB.     for x in A[1:]:
NB.         max_ending_here = max(x, max_ending_here + x)
NB.         max_so_far = max(max_so_far, max_ending_here)
NB.     return max_so_far

NB. returns maximal subarray sum only, not subarray
mxsasum =: 3 : 0
mxeh =. mxsf =. {. a =. y
for_x. }.a do.
   mxeh =. x + 0 >. mxeh
   mxsf =. mxsf >. mxeh
end.
)

NB. first pass at a tacit form of the above - a bit rough!
NB. bolts on mxeh and mxsf to the front of }. of array
NB. and then works through until no array left...
mxsasumt =: ({.`(((2&{+0>.{.)>./\@:,(1&{)),3&}. ) @.(2<#))^:_@: (,~{.)

NB. returns maximal subarray - only the last if more than one!
mxsa =: 3 : 0
mxeh =. mxsf =. {. a =. y
ii =. i =. j =. 0
for_x. }.a do.
   ii   =. >: ii
   i    =. (ii, i) {~ ok =. 0 < mxeh
   mxeh =. x + ok * mxeh
   j    =. (ii, j) {~ ok =. mxeh < mxsf
   mxsf =. ok { mxeh, mxsf
end.
NB. could just return i,j !

a {~ i ([ + i.@>:@-~  ) j

)

Some timings

   ts
6!:2 , 7!:2@]

   q =: 8000$3 4 _5 2 1 1 1

   ts'mxsasum q'
0.0168 68672

   ts'mxsasumt q'
0.11534 1.25056e6

   ts'mxsa q'
0.0590112 134144

   ts'f q'   NB. Jon's one-liner
0.696457 1.74189e6

   ts'>./;(+/\)\. q'   NB. NOT THE WAY TO DO IT!
1.98149 8.82859e8

   >./;(+/\)\. q
8001

   mxsasum q
8001

I very much doubt the book is closed on this one!

Mike


On 24/02/2019 11:39, 'Jon Hough' via Programming wrote:
Reference: https://en.wikipedia.org/wiki/Maximum_subarray_problem

This is the problem:
Given an array of numbers, find the contiguous subset of maximum sum. i.e. find the maximum sum subarray.
Example:
R=: 3 4 _5 2 1 1
The maximum subarray is 3 4

Kadane's algorithm is a linear time algorithm to solve this. Rather than explicitly implementing this, I wanted a J verb to solve this, using J primitives.

I wrote a horrendously long one-liner to solve this:
f=: ({.@:I.@:(= >./)@:>@:({:&.>) { ])@:(>:@:i.@:# (({.@:I.@:(= >./) ([ , {) ])@:(+/\) <@,~ [)"0 _ ]) ((i.@:{. + {:)@:}:@:,@:>@:[ { ]) ]

Empirically, I found this to be O(n) in time. e.g.
For an array of length 8000
timespacex gives:              0.25468 3.40134e6
For array of length 16000: 1.03293 6.80102e6
For array of length 32000: 4.09139 1.36004e7
For array of length 64000: 16.3896 2.71991e7

Any better solutions (faster, and more elegant)?

Thanks,
Jon
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm

---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus

----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm

Reply via email to