Created
February 2, 2021 14:54
-
-
Save encap/908578b21464086d0c72b7999aeb0eb0 to your computer and use it in GitHub Desktop.
Algorithm that receives two sequences: A and B of integers and returns one sequence C. Sequence C should contain all elements from sequence A (maintaining the order) except those, that are present in sequence B p times, where p is a prime number.
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
// inputs | |
const A = [2,3,9,2,5,1,3,7,10] | |
const B = [2,1,3,4,3,10,6,6,1,7,10,10,10] | |
const P = 2; | |
// expected results for that inputs | |
// [2,9,2,5,7,10] | |
// test larger input arrays | |
// for (let i = 0; i < 100000; i += 1) { | |
// A.push(Math.floor(Math.random()*1000)) | |
// B.push(Math.floor(Math.random()*1000)) | |
// } | |
const isPrimeNumber = (num) => { | |
// 6k + 1 algorithm based on https://en.wikipedia.org/wiki/Primality_test | |
if (num <= 3) { | |
return num > 1; | |
} | |
if ((num % 2) === 0|| (num % 3) === 0) { | |
return false; | |
} | |
for (let i = 5; (i ** 2) <= num; i += 6) { | |
if ( | |
(num % i) === 0 | |
|| (num % (i + 2)) === 0 | |
) { | |
return false; | |
} | |
return true | |
} | |
} | |
const solveAlgorithm = (p, seqA, seqB) => { | |
if (p > seqB.length) { | |
throw RangeError('First argument must be less or equal than seqB length'); | |
} else if (!isPrimeNumber(p)) { | |
throw RangeError('First argument must be a prime number'); | |
} | |
const cache = { | |
include: [], | |
exclude: [], | |
} | |
const checkCount = (numToCount) => { | |
// indexOf has fast C implemenation in JS engine | |
// but benefits of using it here cancel out 50% of a time with random values | |
// if (seqB.indexOf(numToCount) === -1) { | |
// return false; | |
// } | |
const count = seqB.reduce((acc, num) => num === numToCount ? acc += 1 : acc, 0); | |
if (count === p) { | |
cache.exclude.push(numToCount); | |
return true; | |
} | |
cache.include.push(numToCount); | |
return false; | |
} | |
const retSeq = seqA.filter((num) => { | |
if (cache.exclude.indexOf(num) !== -1) { | |
return false; | |
} else if (cache.include.indexOf(num) !== -1) { | |
return true; | |
} else { | |
return !checkCount(num); | |
} | |
}) | |
return retSeq; | |
} | |
const t0 = Date.now(); | |
const results = solveAlgorithm(P, A, B); | |
const t1 = Date.now(); | |
console.log('*****END******'); | |
console.log(`Results contain ${results.length} numbers, displaying first 20`) | |
console.log(results.slice(0, 20)); | |
console.log(`TOOK ${t1 - t0}ms`); | |
/* | |
I don't have the exact time complexity in Big O notation | |
but here are the execution times in milliseconds | |
on Ryzen 3 2200G @3.7GHz | |
A = 1 000 random, B = 1 000 random, P = 97 | |
without caching: 559 | |
with caching: 15 | |
A = 10 000 random, B = 10 000 random, P = 1229 | |
with caching: 145 | |
A = 100 000 random, B = 100 000 random, P = 64223 | |
without caching: 12000 | |
with caching: 1380 | |
A = original, B = 1 000 000 random, P = 1229 | |
with caching: 100 | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment