Created
January 21, 2020 01:31
-
-
Save mrlubos/0e867cfd3032c76859c6d1e9ae1e64b7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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