how to avoid using recursive function - javascript

I found an question and would like to try if I can write a better function without using recursive function and while loop.
But I found that I have no idea how to write it better. Is there anyone who can give me some hints or inspire me.
function recursivefunction(i, val) {
if (!val) val= 0;
if (i < 2) throw new Error('wrong input');
if (i === 2) return 1 / i + val;
return recursivefunction(i - 1, val+ 1 / (i * (i -1)));
}
Write a program doing the same calculation without
recursion.

function recursivefunction(i, val) {
if (!val) val= 0;
if (i < 2) throw new Error('wrong input');
if (i === 2) return 1 / i + val;
return recursivefunction(i - 1, val+ 1 / (i * (i -1)));
}
function nonRecursiveFunction(i, val) {
if (!val) val = 0;
if (i < 2) throw new Error('wrong input');
while(i > 2) {
val = val + 1 / (i * (i -1));
i--;
}
return 1 / i + val;
}
const recursive = recursivefunction(4, 2);
const nonrecursive = nonRecursiveFunction(4, 2);
console.log(`Recusrive: ${recursive}, nonrecursive: ${nonrecursive}`);
To be honest, I'd replace the return statement with val + 0.5, because we know that i is exactly 2 and we can use a constant value instead of dividing here.

Related

Function in Javascript that inserts dashes or asterisks between each two odd or even numbers

I want to write a function that inserts dashes (' - ') between each two odd numbers and inserts asterisks (' * ') between each two even numbers. For instance:
Input: 99946
Output: 9-9-94*6
Input: 24877
Output: 2*4*87-7
My try
function dashAst (para) {
let stringArray = para.toString().split('');
let numbArray = stringArray.map(Number);
for (let i = 0; i<numbArray.length; i++) {
if (numbArray[i] %2 === 0 && numbArray[i+1] % 2 === 0) {
numbArray.splice(numbArray.indexOf(numbArray[i]), 0, '*')
}
else if (numbArray[i] %2 !== 0 && numbArray[i+1] %2 !== 0) {
numbArray.splice(numbArray.indexOf(numbArray[i]), 0, '-')
}
}
return numbArray
}
When I try to invoke the function it returns nothing. For instance, I tested the splice-command separately and it seems to be correct which makes it even more confusing to me. Thanks to everyone reading, or even helping a beginner out.
Looping through an Array that changes its length during the loop can be very messy (i needs to be adjusted every time you splice). It's easier to create a new result variable:
function dashAst(para) {
const stringArray = para.toString().split('');
const numbArray = stringArray.map(Number);
let result = "";
for (let i = 0; i < numbArray.length; i++) {
const n = numbArray[i], next = numbArray[i + 1];
result += n;
if (n % 2 == next % 2) {
result += n % 2 ? '-' : '*';
}
}
return result;
}
console.log(dashAst(99946)); // "9-9-94*6"
console.log(dashAst(24877)); // "2*4*87-7"
You could map the values by checking if the item and next item have the same modulo and take a separator which is defined by the modulo.
function dashAst(value) {
return [...value.toString()]
.map((v, i, a) => v % 2 === a[i + 1] % 2 ? v + '*-'[v % 2] : v)
.join('');
}
console.log(dashAst(99946)); // 9-9-94*6
console.log(dashAst(24877)); // 2*4*87-7
I hope this helps
var str = '24877';
function dashAst (para) {
let stringArray = para.toString().split('');
let numbArray = stringArray.map(x => parseInt(x));
console.log(numbArray);
var out=[];
for(let i = 0; i < numbArray.length; i++) {
if(numbArray[i] % 2 == 0){
out.push(numbArray[i]);
numbArray[i + 1] % 2 == 0 ? out.push('*') : 0;
}else if(numbArray[i] % 2 != 0) {
out.push(numbArray[i]);
numbArray[i + 1] != undefined ? out.push('-') : 0;
}
}
console.log(out.join(''));
return out;
}
dashAst(str);

Javascript - Better Alternate to Recursive call

I have this following problem.
I need to calculate a number x based on time t, x would be represented as M(t).
We have the following
M(0) = 1
M(1) = 1
M(2) = 2
M(2t) = M(t) + M(t + 1) + t (for t > 1)
M(2t + 1) = M(t - 1) + M(t) + 1 (for t >= 1)
With that being said the first thing i had in mind to implement this is by using recursion
function CalculateForTime(t) {
if (t == 0 || t == 1) {
return 1;
}
else if (t == 2) {
return 2;
}
else if (t % 2 == 0) {
t = t / 2;
return CalculateForTime(t) + CalculateForTime(t + 1) + t;
}
else {
t = (t - 1) / 2;
return CalculateForTime(t - 1) + CalculateForTime(t) + 1;
}
}
This works however it breaks when running on a large number t for example 1^20
I tried looking into tail call recursion or substituting the recursion approach to an iteration approach but couldn't really figure it out.
If tail recursion or iteration is the way to go then please I need help on converting this. If not then I'm open to different methods on making this more optimized.
Thank you,
Omar.
You could use a hash table, because for an array it would generate holes with no value.
function calculateForTime(t) {
var k = t;
if (k in lookup) {
return lookup[k];
}
if (t == 0 || t == 1) {
return lookup[k] = 1;
}
if (t == 2) {
return lookup[k] = 2;
}
if (t % 2 == 0) {
t = t / 2;
return lookup[k] = calculateForTime(t) + calculateForTime(t + 1) + t;
}
t = (t - 1) / 2;
return lookup[k] = calculateForTime(t - 1) + calculateForTime(t) + 1;
}
var lookup = {};
console.log(calculateForTime(1e10));
.as-console-wrapper { max-height: 100% !important; top: 0; }
You could store the values in an array,then theres no need to recalc...
var times=[1,1,2];
function CalculateForTime(t) {
t = Math.floor(t / 2);
return times[t]||(times[t]=CalculateForTime(t) + CalculateForTime(t + 1) + t);
}
console.log(
CalculateForTime(100),
CalculateForTime(1000),
CalculateForTime(10000),
);
console.log(times.slice(0,100));
You could use memoization to avoid recalculating the same values again and again. See https://addyosmani.com/blog/faster-javascript-memoization/
This is the same as what others suggested, except that it separates the algorithm from the caching of values.
function memoize(func){
var cache = {};
return function( arg ){
if(arg in cache) {
return cache[arg];
} else {
return cache[arg] = func( arg );
}
}
}
// Overwrite with a function that remember previous results
CalculateForTime = memoize(CalculateForTime);
Pardon any typos, answered from phone

Greatest Prime Factor

I'm trying to complete an algorithm challenge to find the largest prime factor of 600851475143. I'm not necessarily asking for the answer. Just trying to figure out why this code isn't working. Why does it return 'undefined' instead of a number?
let isPrime = n => {
let div = n - 1;
while (div > 1) {
if (n % div == 0) return false;
div--;
}
return true;
};
let primeFactor = x => {
for (let i = Math.floor(x / 2); i > 1; i--) {
if (x % i == 0 && isPrime(i) == true) {
return i;
}
}
};
console.log(primeFactor(35)); // 7
console.log(primeFactor(13195)); // 29
console.log(primeFactor(600851475143)); // undefined
The problem is not your algorithm it is perfectly valid, check the below slightly modified algorithm, all I've done is replaced your starting point Math.floor(x/2) with a parameter that you can choose:
let isPrime = n => {
let div = n - 1;
while (div > 1) {
if (n % div == 0) return false;
div--;
}
return true;
};
function primeFactor(x, n){
for (let i = n; i > 1; i--) {
if (x % i == 0 && isPrime(i) == true) {
return i;
}
}
}
console.log(primeFactor(35, 35));
console.log(primeFactor(13195, 13195));
console.log(primeFactor(600851475143, 100000))
Using the above you'll get an answer that proves your implementation works, but the loop is too big to do the entire thing(i.e. from Math.floor(600851475143/2)). Say your computer can do 500million loops per second, going through every one from 300,425,737,571 down to 1 would take 167 hours, even at 5 billion loops per second it would take 16 and a half hours. Your method is extremely inefficient but will return the correct answer. The reason you're not getting an answer on JSBin is more likely to do with browser/service limitations.
Spoilers on more efficient solution below
The following implementation uses a prime sieve(Sieve of Eratosthenes) in order to generate any list of primes requested and then checks if they fully factor into the given number, as long as you use a large enough list of primes, this will work exactly as intended. it should be noted that because it generates a large list of primes it can take some time if ran incorrectly, a single list of primes should be generated and used for all calls below, and the cached list of primes will pay off eventually by having to perform less calculations later on:
function genPrimes(n){
primes = new Uint32Array(n+1);
primes.fill(1)
for(var i = 2; i < Math.sqrt(n); i++){
if(primes[i]){
for(var j = 2*i; j < n; j+=i){
primes[j] = 0;
}
}
}
primeVals = []
for(var i = 2; i < primes.length; i++){
if(primes[i]){
primeVals.push(i);
}
}
return primeVals;
}
function primeFactor(x, primes){
var c = x < primes.length ? x : primes.length
for (var i = c; i > 1; i--) {
if(x % primes[i] == 0){
return primes[i];
}
}
}
primes = genPrimes(15487457);
console.log(primeFactor(35, primes));
console.log(primeFactor(13195, primes));
console.log(primeFactor(600851475143, primes));
console.log(primeFactor(30974914,primes));
let primeFactor = x => {
if (x === 1 || x === 2) {
return x;
}
while (x % 2 === 0) {
x /= 2;
}
if (x === 1) {
return 2;
}
let max = 0;
for (let i = 3; i <= Math.sqrt(x); i += 2) {
while (x % i === 0) {
x /= i;
max = Math.max(i, max);
}
}
if (x > 2) {
max = Math.max(x, max);
}
return max;
};
console.log(primeFactor(35));
console.log(primeFactor(13195));
console.log(primeFactor(27));
console.log(primeFactor(1024));
console.log(primeFactor(30974914));
console.log(primeFactor(600851475143));
Optimizations
Dividing the number by 2 until it's odd since no even number is prime.
The iteration increment is 2 rather than 1 to skip all even numbers.
The iteration stops at sqrt(x). The explanation for that is here.

Undefined in associative array lookup

var candidates = {
"1":"Barack Obama",
"2":"Mitt Romney",
"3":"Dennis Kucinich",
"4":"Quentin Tarantino",
"5":"Count Dracula"
};
function getRandomInt(min, max){
return Math.floor(Math.random() * (max - min + 1)) + min;
}
Object.size = function(obj) {
var size = 0, key;
for (key in obj) {
if (obj.hasOwnProperty(key)) size++;
}
return size;
};
function getRandomPresident(){
var num = getRandomInt(1, Object.size(candidates));
if (num!=5){
alert(num);
var key = num.toString();
var res = candidates[key];
return res;
} else {
getRandomPresident();
}
}
alert(getRandomPresident());
This code works, but sometimes after generating random value it outputs "undefined" instead of the name - http://jsbin.com/uriwal/edit#source Why?
When trying again (the else block), you don't return the new value. You should pass the return value through:
return getRandomPresident();
Currently, you're picking a new item, but as the function doesn't return it, the return value is undefined.
I'm guessing the getRandomInt() function can return 0, which your associative array does not have. Just create a tighter check in the if clause:
if (num >= 1 && num <= 5) {
// do stuff
}
EDIT:
Scratch that, you have getRandomInt(1, max). In any case, why even have a recursive function? Just do this:
var num = 0;
while ((num = getRandomInt(1, ...)) > 5) {
num = getRandomInt(1, ...);
}
// return the resource
Hope this helps
Change function to this:
function getRandomInt(min, max){
return Math.floor(Math.random() * (max - min)) + min;
}

finding sum of prime numbers under 250

var sum = 0
for (i = 0; i < 250; i++) {
function checkIfPrime() {
for (factor = 2; factor < i; factor++) {
if (i % factor = 0) {
sum = sum;
}
else {
sum += factor;
}
}
}
}
document.write(sum);
I am trying to check for the sum of all the prime numbers under 250. I am getting an error saying that i is invalid in the statement if (i % factor = 0) I know was creating in the original for statement, but is there any way to reference it in the if statement?
With the prime computation, have you considered using Sieve of Eratosthenes? This is a much more elegant way of determining primes, and, summing the result is simple.
var sieve = new Array();
var maxcount = 250;
var maxsieve = 10000;
// Build the Sieve, marking all numbers as possible prime.
for (var i = 2; i < maxsieve; i++)
sieve[i] = 1;
// Use the Sieve to find primes and count them as they are found.
var primes = [ ];
var sum = 0;
for (var prime = 2; prime < maxsieve && primes.length < maxcount; prime++)
{
if (!sieve[prime]) continue;
primes.push(prime); // found a prime, save it
sum += prime;
for (var i = prime * 2; i < maxsieve; i += prime)
sieve[i] = 0; // mark all multiples as non prime
}
document.getElementById("result").value =
"primes: " + primes.join(" ") + "\n"
+ "count: " + primes.length + "\n"
+ "sum: " + sum + "\n";
#result {
width:100%;
height:180px
}
<textarea id="result">
</textarea>
(EDIT) With the updated algorithm, there are now two max involved:
maxcount is the maximum number of prime numbers you wish to find
maxsieve is a guess of sieve large enough to contain maxcount primes
You will have to validate this by actually checking the real count since there are two terminating conditions (1) we hit the limit of our sieve and cannot find any more primes, or (2) we actually found what we're looking for.
If you were to increase the number to numbers much greater than 250, than the Sieve no longer becomes viable as it would be consume great deals of memory. Anyhow, I think this all makes sense right? You really need to play with the Sieve yourself at this point than rely on my interpretation of it.
You can equally use this
let sum = 0;
let num = 250;
for (let i = 2; i < num; i++) {
let isPrime = true;
for (let j = 2; j < i; j++) {
if (i % j === 0) {
isPrime = false;
}
}
if (isPrime) {
sum += i;
}
}
console.log(sum);
i % factor === 0
Use === for comparison. = is for assignment. Yeah I said triple equals. Type coercion is annoying.
You need a == or ===: if (i % factor == 0)
Here's a pretty decent way to do it. It's not as advanced as the sieve but it's a decent starting point. NOTE: I'm using ES6 syntax.
/*
* Sum the first n prime numbers
*
* #param n (integer)
* #return integer
*
*/
function sumNprimes(n){
const arr = [];
let i = 2
while (arr.length < n) {
if (isPrime(i)) {
arr.push(i)
}
i++
}
return arr.reduce( (x,y) => x+y );
/*
* #param n (integer)
* #return Boolean
*
*/
function isPrime(n) {
if ( n < 2 ) {
return false
}
for ( let i = 2; i <= Math.sqrt(n); i++ ) {
if ( n % i === 0 ) {
return false;
}
}
return true
}
}
So i had to face a similar challenge and here is my solution, i hope you find it helpful:
function sumPrimes(num) {
// determine if a number is prime
function isPrime(n) {
if (n === 2) return true;
if (n === 3) return true;
if (n % 2 === 0) return false;
if (n % 3 === 0) return false;
var i = 5;
var w = 2;
while (i * i <= n) {
if (n % i === 0) {
return false;
}
i += w;
w = 6 - w;
}
return true;
}
// subtract 1 for 'not being prime' in my context
var sum = isPrime(num) ? num - 1 : -1;
for (var x = 0; x < num; x++) {
if (isPrime(x) === true) {
sum += x;
}
}
return sum;
}
As per the "Sieve of Eratosthenes", I have implemented the code using JS:
function isPrime(n){
return ((n/2 === 1 || n/3 === 1 || n/5 === 1 || n/7 === 1)?true:(n%2===0 || n%3 === 0 || n%5 ===0 || n%7 === 0)?false:true);
};
var val = 250;
let outArr = [];
for(let i=2;i<val;i++){
if(isPrime(i)){
outArr.push(i);
}
}
console.log("Prime number between 0 - "+val+" : "+outArr.join(","));
Here is a simple way of looping through array and implementing the sieve of Eratosthenes...
function sumPrimes(num) {
var t, v = [],
w = [],
x = [],
y = [],
z = 0;
//enumerating Vee array starts at 2 as first prime number
for (let a = 2; a <= num; a++) {
v.push(a)
}
//creating a moving loop by splicing its first index
for (let i = 0; i < v.length; i) { //ensure all items spliced
t = v[i]; // t as prime to be removed from Vee array
x.push(t); // x storage of primes
z += t // total of peculiar primes
w.push(v.splice(i, 1)) //tested to move all one by one
// prompt(v) //tested that v loses its v[i] every iteration
//= now trying to remove others using remainder (%) vs prime t
for (let vi in v) {
v[vi] % t === 0 ? y.push(v.splice(vi, 1)) : ""; //recursive removal of composite items by prime t
}
}
return z // returns sum of primes
}
sumPrimes(250);
You generate the array beginning with 2 as first prime,
You sieve the array removing items by the remainder of prime using % === 0.
The you loop through the remaining array by using the next prime until the last remaining prime is pushed to the prime arrays. Add all primes to get the Sum.
If the question is purely academical, earlier answers are better suited.
The example below uses modern libraries, in case you need an efficient and elegant solution.
import {generatePrimes} from 'prime-lib';
import {from, reduce, takeWhile} from 'rxjs';
from(generatePrimes())
.pipe(takeWhile(p => p < 250), reduce((a, c) => a + c))
.subscribe(sum => {
// sum = 5830
});
Performance-wise, it will take significantly less than 1ms.
How would it affect the code if I wanted say the sum of the first 250 prime numbers instead of the prime numbers under 250?
You would just replace takeWhile(p => p < 250) with take(250):
import {generatePrimes} from 'prime-lib';
import {from, reduce, take} from 'rxjs';
from(generatePrimes())
.pipe(take(250), reduce((a, c) => a + c))
.subscribe(sum => {
// sum = 182109
});
P.S. I am the author of prime-lib.

Categories