Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrlubos/0e867cfd3032c76859c6d1e9ae1e64b7 to your computer and use it in GitHub Desktop.
Save mrlubos/0e867cfd3032c76859c6d1e9ae1e64b7 to your computer and use it in GitHub Desktop.
const inputs = [
[0, 1, 2, -10, 5],
[1, 2, -90, 7, 9, -10],
[-120, -50, 0, 1],
[-100, -20, -37],
[10, 2, 1, -10],
[1, 2, -1, 10, -100, 8],
[1, 2, -1, 10, -100, 8, 90],
[100, 400, -100, -200, 400, -100, -100],
[1, 2, -1, 0, 10, -100, 8],
[1, 2, -10, 1, 2],
];
const options = {
excludeLeadingZero: false, // When true, max series won't start with zero.
excludeNegativeNumbers: false, // When true, max series won't contain negative numbers.
excludeZero: false, // When true, max series won't contain zero at any position.
firstMatch: false, // When true and there are 2 max series, return the first one. By default, we return the last one.
increasingNumbersOnly: false, // When true, max series will be ordered from the smallest to the largest number.
};
const resultIndexOutput = 0;
const resultIndexTemp = 1;
const addValueToSeries = (value, series) => ({
index: series.index,
numbers: immutablePush(series.numbers, value),
sum: series.sum + value,
});
const getMaxSeries = (values, options) => {
const result = values.reduce((series, value, index) => {
series = updateTempSeries(series, options, value, index);
series = updateOutputSeries(series, options);
return series;
}, getResultInitialState());
return result[resultIndexOutput];
};
const getResultInitialState = () => [
getSeriesInitialState(),
getSeriesInitialState(),
];
const getSeriesInitialState = () => ({
index: -1,
numbers: [],
sum: -Infinity,
});
const getSeriesOperation = (...args) => {
if (isValueIgnored(...args)) {
return getSeriesInitialState;
}
return isValueNetPositive(...args) && isSeriesNetNegative(...args)
? setValueToSeries
: addValueToSeries;
};
const immutablePush = (arr, value) => [...arr, value];
const immutableSet = (arr, value, index) => [
...arr.slice(0, index),
value,
...arr.slice(index + 1),
];
const isSeriesInitial = (series) => !series.numbers.length;
// Net negative series can be directly replaced with net positive value.
const isSeriesNetNegative = (value, series) => isSeriesInitial(series)
|| series.sum < 0;
const isValueIgnored = (value, series, options) => {
const args = [value, series, options];
const isZero = value === 0;
return (options.excludeNegativeNumbers && !isValueNetPositive(...args))
|| (options.excludeZero && isZero)
|| (options.excludeLeadingZero && isSeriesNetNegative(...args) && isZero)
|| (options.increasingNumbersOnly && !isValueLargerThanPrevious(...args));
};
const isValueLargerThanPrevious = (value, series) => {
const { numbers } = series;
return isSeriesInitial(series) || value > numbers[numbers.length - 1];
};
// Adding net positive value to series doesn't decrease its sum.
const isValueNetPositive = (value, series, options) => (!options.excludeNegativeNumbers && value >= series.sum)
|| value >= 0;
const setValueToSeries = (value, series, options, index) => ({
index,
numbers: [value],
sum: value,
});
const updateOutputSeries = (series, options) => {
const condition = options.firstMatch
? series[resultIndexTemp].sum > series[resultIndexOutput].sum
: series[resultIndexTemp].sum >= series[resultIndexOutput].sum;
return condition
? immutableSet(series, series[resultIndexTemp], resultIndexOutput)
: series;
};
const updateTempSeries = (series, options, value, index) => {
const args = [value, series[resultIndexTemp], options, index];
const seriesOperation = getSeriesOperation(...args);
const nextTempSeries = seriesOperation(...args);
return immutableSet(series, nextTempSeries, resultIndexTemp);
};
const outputs = inputs.map((input) => getMaxSeries(input, options));
console.log(outputs);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment