Sub-arrays of maximal sum
Another puzzle problem from this blog. "You are given an array of n integers, each of which may be positive, negative or zero. Give an algorithm to identify the start and end index, i and j, of the interval whose elements form the maximal sum of all possible intervals. Assume j >=i. e.g. {1 3 -8 2 -1 10 -2 1} -> i=3, j=5 - sum=11.
Python
'''Find sub-arrays of maximal sum
e.g. {1 3 -8 2 -1 10 -2 1} -> i=3, j=5 - sum=11
http://basicalgos.blogspot.com/2012/05/52-find-sub-array-of-max-sum.html
'''
import functools
#Compute all the intervals of the sequence t per the definition
#above. e.g. for [1, 2, 3] compute [[1], [1, 2], [1, 2, 3], [2],
#[2, 3], [3]].
#Decorate the intervals with their start and end indices and the
#interval sum.
def intervals (t):
def f (acc, i):
def row (i, t):
s = t[i:]
def f (acc, j):
indices=(i, i+j-1)
interval=s[0:j]
return acc + [(indices, interval, sum (interval, 0))]
return functools.reduce (f, list (range (1, len (s) + 1)), [])
return acc + row (i, t)
return functools.reduce (f, list (range (0, len (t))), [])
#x, the input sequence.
x=[1, 3, -8, 2, -1, 10, -2, 1]
#Print the intervals of x with maximal sum.
res = intervals (x)
def f (m, t):
(_,_,n)=t ; return max (m, n)
maxsum = functools.reduce (f, res, 0)
for t in res:
(indices, interval, total)=t
if (total == maxsum):
print (str(t)) #An interval of maximal sum.
C++
#include <vector>
#include <numeric>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <functional>
typedef std::pair<std::size_t, std::size_t> indicies_t;
inline std::size_t& fst (indicies_t& i) { return i.first; }
inline std::size_t& snd (indicies_t& i) { return i.second; }
inline std::size_t fst (indicies_t const& i) { return i.first; }
inline std::size_t snd (indicies_t const& i) { return i.second; }
void print_indicies (indicies_t const& p);
typedef std::vector<int> interval_t;
inline std::size_t len (interval_t const& i) { return i.size(); }
interval_t take (int k, interval_t const& lst);
interval_t drop (int k, interval_t const& lst);
inline int sum (interval_t const t)
{
int tot=std::accumulate (t.begin(), t.end(), 0, std::plus<int>());
return tot;
}
interval_t range (int begin, int end);
void print_interval (interval_t const& s);
struct interval_info_t
{
indicies_t indicies; //(0, 2)
interval_t interval; //e.g. [1, 2, 3]
int total; //6
};
void print_interval_info (interval_info_t const& i);
typedef std::vector<interval_info_t> interval_info_set_t;
struct inner_f
{
interval_t s;
std::size_t i;
inner_f (interval_t const& s, std::size_t i)
: s (s), i (i)
{}
interval_info_set_t operator()
(interval_info_set_t acc, std::size_t j)
{
indicies_t indicies;
fst (indicies) = i;
snd (indicies) = i + j - 1;
interval_t interval = take (j, s);
int total = sum (interval);
interval_info_t interval_info;
interval_info.indicies = indicies;
interval_info.interval = interval;
interval_info.total = total;
acc.push_back (interval_info);
return acc;
}
};
interval_info_set_t row (std::size_t i, interval_t const& t)
{
interval_t s = drop (i, t);
interval_t rg = range (1, len (s) + 1);
return std::accumulate (
rg.begin(), rg.end(), interval_info_set_t(), inner_f (s, i));
}
struct outer_f
{
interval_t t;
outer_f (interval_t const t) : t (t) {}
interval_info_set_t operator()
(interval_info_set_t acc, std::size_t i) const
{
interval_info_set_t res=row (i, t);
std::copy (res.begin(), res.end(), std::back_inserter (acc));
return acc;
}
};
interval_info_set_t intervals (interval_t const& t)
{
interval_t rg = range (0, len (t));
return std::accumulate (
rg.begin(), rg.end(), interval_info_set_t (), outer_f (t));
}
inline int find_max (int m, interval_info_t const& t)
{
return (std::max)(m, t.total);
}
//--driver
int main ()
{
int data[] = {1, 3, -8, 2, -1, 10, -2, 1};
interval_t input(data, data + sizeof(data)/sizeof(int));
interval_info_set_t ivals = intervals (input);
int maxsum = std::accumulate (ivals.begin(), ivals.end(), 0, find_max);
for (std::size_t i = 0; i < ivals.size(); ++i)
{
if (ivals[i].total==maxsum)
print_interval_info (ivals[i]); //An interval of maximal sum.
}
return 0;
}
//-- tools
interval_t take (int k, interval_t const& lst)
{
if (k <= 0) return interval_t ();
if (lst.size() == std::size_t (0)) return interval_t ();
interval_t t = take (k-1, interval_t (++(lst.begin()), lst.end()));
interval_t res (t.size()+1);
res[0] = lst[0];
for (std::size_t i = 0; i < len (t); ++i)
res [i+1] = t[i];
return res;
}
interval_t drop (int k, interval_t const& lst)
{
if (k <= 0) return lst;
if (lst.size () == 0) return interval_t ();
return drop (k - 1, interval_t (++(lst.begin()), lst.end()));
}
interval_t range (int begin, int end)
{
interval_t buf;
for(int i = begin; i < end; ++i) buf.push_back (i);
return buf;
}
void print_indicies (indicies_t const& p)
{
std::cout << "(" << fst (p) << ", " << snd (p) << ")";
}
void print_interval (interval_t const& s)
{
std::cout << "[";
std::ostream_iterator<int> out_it (std::cout, ", ");
std::copy (s.begin(), s.end(), out_it);
std::cout << "],";
}
void print_interval_info (interval_info_t const& i)
{
std::cout << "(";
print_indicies (i.indicies);
print_interval (i.interval);
std::cout << i.total;
std::cout << ")\n";
}