Last active
November 13, 2019 00:01
-
-
Save macabeus/ae1b513e0c3e2791b5d25d29f63c3c87 to your computer and use it in GitHub Desktop.
This algorithm returns the biggest sequence from an array that repeats at least two times.
This file contains hidden or 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
/** | |
* This algorithm returns the biggest sequence from an array that repeats at least two times. | |
* | |
* Example: | |
* - [1, 1, 2, 2, 1, 1] -> ['1,1', 2] | |
* - [1, 1, 1, 1, 1, 1, 1, 1] -> ['1,1,1,1,1,1,1', 2] | |
* - [1, 1, 1, 1, 2, 1, 1, 1, 2, 2, 2, 4, 5, 5, 5] -> ['1,1,1,2', 2] | |
* | |
* The idea is very simple: | |
* - firstly, we should split the array on all subsequences with at least two elements; | |
* - so, we should to aggregate on a map the frequence for each sequence; | |
* - and finally, we should find which sequence is the biggest and most frequent. | |
* | |
* Hey, just for simplify, this code only works for numeric array and with numbers between 0 and 9. | |
*/ | |
const listSequences = (array) => { | |
const sequences = [] | |
const nextStep = (initialIndex, lastIndex) => { | |
if (initialIndex === array.length - 1) { | |
return 'finish' | |
} | |
if (lastIndex + 1 > array.length) { | |
return 'reset' | |
} | |
return 'grow' | |
} | |
const splitArray = (currentInitialIndex, currentLastIndex) => { | |
sequences.push( | |
array.slice(currentInitialIndex, currentLastIndex) | |
) | |
switch (nextStep(currentInitialIndex, currentLastIndex)) { | |
case 'finish': | |
return | |
case 'reset': | |
const nextInitialIndex = currentInitialIndex + 1 | |
const nextLastIndex = nextInitialIndex + 2 | |
splitArray(nextInitialIndex, nextLastIndex) | |
return | |
case 'grow': | |
splitArray(currentInitialIndex, currentLastIndex + 1) | |
return | |
} | |
} | |
splitArray(0, 2) | |
return sequences | |
} | |
const calcSequenceFrequence = sequences => sequences.reduce((acc, i) => { | |
if (acc[`${i}`] === undefined) { | |
acc[`${i}`] = 0 | |
} | |
acc[`${i}`] += 1 | |
return acc | |
}, {}) | |
const getMostFrequentSequence = frequences => Object.entries(frequences).reduce( | |
([maxSequence, maxAmount], [sequence, amount]) => { | |
if (amount < 2) { | |
return [maxSequence, maxAmount] | |
} | |
if (sequence.length > maxSequence.length) { | |
return [sequence, amount] | |
} | |
if ( | |
(sequence.length === maxSequence.length) && | |
(amount > maxAmount) | |
) { | |
return [sequence, amount] | |
} | |
return [maxSequence, maxAmount] | |
}, | |
['', 0] | |
) | |
/////////// | |
const array = [2, 2, 2, 1, 2, 1, 1, 1, 2, 2, 2, 4, 5, 2, 2] | |
const sequences = listSequences(array) | |
const sequencesFrequences = calcSequenceFrequence(sequences) | |
const mostFrequentSequence = getMostFrequentSequence(sequencesFrequences) | |
console.log(mostFrequentSequence) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment