Prime number subalgorithms - javascript

Devise an algorithm to receive a positive number, n, and output all prime numbers that are smaller than n
and have a digit 7. For example, if n is 100, the program should output 7, 17, 37, 47, 67, 71, 73, 79, and 97.
Program freezes without giving output
function P6() {
var n = parseInt(prompt("Please enter a value"));
for (var i = 2; i <= n; i++) {
if (prime(i) && has7(i)) {
alert(i);
}
}
}
function prime(s) {
var flag = true;
var d = 2;
while (flag == true && d <= s / 2) {
if (s % d == 0) {
flag = false;
}
d = d++;
}
return flag;
}
function has7(v) {
var has7 = false;
var length = Math.log(v) + 1;
for (var i = 1; i <= length; i++) {
var last = v % 10;
if (last == 7) {
has7 = true;
}
v = v % 10
}
return has7;
}

This line is wrong:
d = d++;
d++ is a post-increment, it increments the variable but evaluates to the old value. So when you assign the result back to the variable, it sets it back to the original value. As a result, you have an infinite loop.
It should be either:
d = d + 1;
or just:
d++;
Another error is:
v = v % 10;
This is supposed to divide v by 10, but it's just setting v to its last digit. It should be:
v = Math.floor(v / 10);
In the code below, I've simplified all your loops. Rather than setting variables and continuing the loops, they return as soon as the loop can determine the answer. If the loop ends without returning, they return the opposite value.
function P6() {
var n = parseInt(prompt("Please enter a value"));
for (var i = 2; i <= n; i++) {
if (prime(i) && has7(i)) {
console.log(i);
}
}
}
function prime(s) {
for (var d = 2; d <= s / 2; d++) {
if (s % d == 0) {
return false;
}
}
return true;
}
function has7(v) {
while (v != 0) {
var last = v % 10;
if (last == 7) {
return true;
}
v = Math.floor(v / 10);
}
return false;
}
P6();

Related

Javascript Function Issues for Prime Numbers

So what I'm trying to do is use a function that prompts to enter a number and then prints all prime numbers up till that number. I have the code as far as I know but I keep getting an error that the bracket following prime(num) is wrong. Not sure what I'm doing wrong here, would appreciate any help.
function p5Bela() {
var num = prompt("Please enter a number: ", "");
for (i = 2; i <= num; i++) {
if (prime(i)==true) {
alert(i);
}
}
prime(num) {
var flag = true;
var d = 2;
while (flag==true && d <= num/2) {
if (num%d == 0) {
flag = false;
}
d++;
}
return flag;
}
}
Simplest Way
function isPrime(num) {
for(var i = 2; i < num; i++)
if(num % i === 0) return false;
return num > 1;
}
With the ES6 syntax:
const isPrime = num => {
for(let i = 2; i < num; i++)
if(num % i === 0) return false;
return num > 1;
}
You can also decrease the complexity of the algorithm from O(n) to O(sqrt(n)) if you run the loop until square root of a number:
const isPrime = num => {
for(let i = 2, s = Math.sqrt(num); i <= s; i++)
if(num % i === 0) return false;
return num > 1;
}

count 9's from 1 to n - 5kyu Kata

I am working on this kata https://www.codewars.com/kata/count-9-s-from-1-to-n/train/javascript
and i have written this code for it, but its not working. This question is similar to this one Count the number of occurrences of 0's in integers from 1 to N
but it is different because searching for 9's is practically very different to searching for 0's.
think part of the problem with this code is that it takes too long to run...
any advice appreciated!
function has9(n) {
var nine = [];
var ninearr = n.toString().split('');
for (var j = 0; j < ninearr.length; j++) {
if (ninearr[j] == '9') {
nine.push(ninearr[j]);
}
}
return nine.length;
}
function number9(n) {
var arr = [];
var arrnew = [];
for (var i = 0; i <= n; i++) {
arr.push(i);
}
for (var l = 0; l < arr.length; l++) {
arrnew.push(has9(l));
}
var sum = arrnew.reduce((a, b) => a + b, 0);
return sum;
}
Why not a regex based solution? (Too slow as well?)
const count9s = num => num.toString().match(/9/g).length
console.log(count9s(19716541879)) // 2
console.log(count9s(919191919191919)) // 8
console.log(count9s(999)) // 3
console.log(count9s(999999)) // 6
I have taken the above hint and completely re written the code, which I now feel should work, and it does for most inputs, but codewars is saying it fails on some of them. any ideas why?
function nines(n){
if(n>=100){
var q= Math.floor(n/100);
var nq= q * 20;
var r = (n%100);
var s = Math.floor(r/9);
if (r<=90){
return s + nq;
}
if (r == 99){
return 20 + nq;
}
if (90 < r < 100 && r!= 99){
var t = (r-90);
return nq + s + t;
}
}
if (n<100){
if (n<=90){
var a = Math.floor(n/9);
return a ;
}
if (n == 99){
return 20
}
if (90 < n < 100 && n!= 99){
var c = (n-90);
return 10 + c;
}
}
}
=== UPDATE ===
I just solved your kata using
function number9Helper(num) {
var pow = Math.floor(Math.log10(num));
var round = Math.pow(10, pow);
var times = Math.floor(num / round);
var rest = Math.abs(num - (round * times));
var res = pow * (round==10 ? 1 : round / 10) * times;
if (num.toString()[0] == '9') res += rest;
if (rest < 9) return res;
else return res + number9Helper(rest);
}
function number9(num) {
var res = number9Helper(num);
res = res + (num.toString().split('9').length-1);
return res;
}
== Function below works but is slow ===
So, could something like this work for you:
for (var nines=0, i=1; i<=n; i++) nines += i.toString().split('9').length-1;
Basically, there are many way to achieve what you need, in the end it all depends how do you want to approach it.
You can test it with
function nines(n) {
for (var nines=0, i=1; i<=n; i++) nines += i.toString().split('9').length-1;
return nines;
}
function number9(n) {
if (n < 8) {
return 0
};
if (n === 9) {
return 1
};
if (n > 10) {
let str = ''
for (let i = 9; i <= n; i++) {
str += String(i)
}
return str.match(/[9]/g).length
}
}

Miller Rabin Primality Test Error on JavaScript

Im working on JavaScript to get three different algorithms to work in the same code, I set up a function for each algorithm. I'm trying to get three Primality testing methods: Trial Division, the Fermat Primality Test, and the Miller-Rabin Primality Test. The first two are working fine but the Miller-Rabin isn't. I'm pretty new to JavaScript and programming in general, so if you can find where I went wrong or can think of a way to make it work, please let me know! Thanks!
// 1531 6389 68819 688889 6388819
// 68883889 688838831 1000000009
// 561 is a Carmichael number; a Fermat pseudoprime with the property a^n-1 = 1 mod n, for any "a" coprime to 561.
input = 5491763;
numTrials = 2000;
document.getElementById("input").innerHTML = input;
function TrialDiv(n) {
if (n === 1) {
return false;
} else if (n === 2) {
return true;
} else {
for (var x = 2; x < n; x++) {
if (n % x === 0) {
return false;
}
}
return true;
}
}
if ((TrialDiv(input)) === true) {
a = "Prime"
} else if ((TrialDiv(input)) === false) {
a = "Composite"
}
//---------------------------------------------------------------------------
function gcd(x, y) {
while (y !== 0) {
var z = x % y;
x = y;
y = z;
}
return x;
}
function getRndInteger(max) {
return Math.floor(Math.random() * (max - 2)) + 2;
}
//--------------------------------------------------------------------------
function Fermat(n) {
for (var t = 0; t = numTrials; t++) {
m = getRndInteger(input);
if (gcd(m, n) !== 1) {
return false;
}
}
return (Math.pow(m, n - 1) % n !== 1);
}
if ((Fermat(input)) === true) {
b = "Prime";
} else if ((Fermat(input)) === false) {
b = "Composite";
}
//---------------------------------------------------------------------------
function genD(n) { // Generates "d" such that "n-1 = 2^s * d"
var p = n - 1;
var d = p / 2;
while (d % 2 === 0) {
d = d / 2;
}
return d;
}
function genS() { // Generates "s" such that "n-1 = 2^s * d"
var s = Math.log2(p / d);
return s;
}
//---------------------------------------------------------------------------
function MillerRabin(n) {
for (var t = 0; t < numTrials; t++) {
m = getRndInteger(input);
if (gcd(m, n) !== 1) {
return false;
} else {
for (var r = 0; r < genS(); r++) {
power = (Math.pow(2, r) * genD(input));
if (Math.pow(m, genD(input)) % n === 1 || Math.pow(m, power) % n === -1) {
return true;
} else {
return false;
}
}
return true;
}
return true;
}
}
if ((MillerRabin(input)) === true) {
c = "Prime";
} else if ((MillerRabin(input)) === false) {
c = "Composite";
}
<body>
<button type="button" onclick='document.getElementById("TrialDivision").innerHTML = a; document.getElementById("FermatTest").innerHTML = b; document.getElementById("MillerRabinTest").innerHTML = c; '>Show</button>
<hr>
<b style="color:rgb(0,0,120)">PRIMALITY TESTS</b>
<p></p>
Input:
<l id="input"></l>
<hr>
<h5 style="color:rgb(160,0,0)">TRIAL DIVISION</h5>
<p></p>
Output:
<i id="TrialDivision"></i>
<hr>
<h5 style="color:rgb(160,0,0)">FERMAT PRIMALITY TEST</h5>
<p></p>
Output:
<i id="FermatTest"></i>
<hr>
<h5 style="color:rgb(160,0,0)">MILLER-RABIN PRIMALITY TEST</h5>
<p></p>
Output:
<i id="MillerRabinTest"></i>
</body>
<script>
That's how I wrote it up, this was purely created by me from the original mathematical algorithms for each test. What happens is that the Miller-Rabin Output doesn't show anything when the input number is prime; the algorithm isn't able to identify it. But it does identify composites correctly.
Please let me know of any improvements you think of!
You have some problems with loops not running. I'm not sure how the algorithm is supposed to work, so I don't if it's working or not, but the immediate problem is cause by leaky variable and variables not declared in functions (which makes them global).
The fix for this immediate problem is to declare the local variables in the functions so you don't depend on having them set by some other function.
function genD(n) { // Generates "d" such that "n-1 = 2^s * d"
var p = n - 1;
var d = p / 2;
while (d % 2 === 0) {
d = d / 2;
}
return d;
}
function genS(n) { // Generates "s" such that "n-1 = 2^s * d"
var p = n - 1
var d = p / 2
var s = Math.log2(p / d);
return s;
}
Once you start fixing the errors that crash there are a few other big problems. For example your fermat() potentially runs for ever:
for (var t = 0; t = numTrials; t++) {
Should be:
for (var t = 0; t == numTrials; t++) {
= sets t to numTrails for every loop
I think you should start at the beginning, put all your functions together and all you other logic code that calls the functions together so you can see what's going on.

finding the nth prime javascript

the functions below are supposed to spit out the nth prime number. However, it keeps on spitting out 3. Can somebody please help? Cheers, Anthony
function Prime(num) {
output = true
for (i=2 ; i<num ; i++) {
if (num%i === 0) {
output = false ; break
}
}
return output
}
function PrimeMover(num) {
var count = 0
for (i=2 ; i<10000 ; i++) {
if (Prime(i) === true) {
count = count + 1
}
if (count === num) {
return i
break
}
}
}
You have created loop counter i in global scope.so both PrimeMover and Prime mutates same global i.In every iteration ,PrimeMover assigns i=2.After that Prime assigns i=2.your i variable's value will be changed between 2 and 3.use local loop counter variable var i=0;
function Prime(num) {
output = true
for (var i=2 ; i<num ; i++) { //var i=2
if (num%i === 0) {
output = false ; break
}
}
return output
}
function PrimeMover(num) {
var count = 0
for (var i=2 ; i<10000 ; i++) { //var i=2
if (Prime(i) === true) {
count = count + 1
}
if (count === num) {
return i
break
}
}
}
For minimal code lovers,
function nthprime(n)
{
var prime=[], i=1
while (i++ && prime.length<n) prime.reduce((a,c)=>(i%c)*a,2) && prime.push(i)
return prime.length?prime.pop():-1
}
[-1,0,1,2,3,5,10,100].forEach(n=>console.log(`nthprime(${n})=${nthprime(n)}`))
function main(inp) {
var count = 0;
for (var i = 2; i <= 100000; i++) {
if (isPrime(i)) count = count + 1;
if (count == inp) return i;
}
}
function isPrime(i) {
for (var j = 2; j < i; j++) {
//instead of `j < i` it can be reduced using other conditions
if (i % j == 0) {
return false
}
}
return true
}
main(5) // any number
This might be a bit more optimal
function nthPrime(n) {
var P = 0;
function isPrime(x) {
var isPrime= true;
for (var d = 2; d <= Math.sqrt(x); d++) {
if((x/d) % 1 == 0) {
isPrime = false;
break;
}
}
return isPrime;
}
for (var i = 1; 0 < n; i++) {
if(isPrime(i)) {
P = i; n--;
}
// we can skip the even numbers
if(3 <= i){
i++;
}
}
return P;
}
Try this
var pos=10001;
console.log(primeNumforPos(pos));
function primeNumforPos(pos){
var num=2,curPos=0;
while(curPos<=pos){
if(isPrime(num)){
curPos++;
}
if(curPos==pos){
return num;
}else{
num++;
}
}
}
function isPrime(num){
for(var i=2;i<=Math.sqrt(num);i++){
if(num%i==0){
return false;
}
}
return true;
}
So, I decided to optimise the hell out of the code (cuz why not). It is almost 6 times as fast as that of ppseprus (297ms vs 1773ms in nth_prime(100000)).
let primes = [2, 3];
const nth_prime = (n) => {
if (n <= primes.length) return primes[n - 1]; // handle values which have been cached
let i = 1;
while (1){
const a = 6 * i - 1, b = 6 * i + 1, a_limit = Math.sqrt(a), b_limit = Math.sqrt(b); // the 6n - 1 and 6n + 1 rule for primes
let a_prime = true, b_prime = true;
i++;
// prime check
for (const prime of primes){
if (prime > a_limit) break;
if (a % prime == 0){
a_prime = false;
break;
}
}
if (a_prime){
if (primes.length + 1 == n) return a;
primes.push(a); // cache
}
for (const prime of primes){
if (prime > b_limit) break;
if (b % prime == 0){
b_prime = false;
break;
}
}
if (b_prime){
if (primes.length + 1 == n) return b;
primes.push(b); // cache
}
}
}
const findPrime = num => {
let i, primes = [2, 3], n = 5
const isPrime = n => {
let i = 1, p = primes[i],
limit = Math.ceil(Math.sqrt(n))
while (p <= limit) {
if (n % p === 0) {
return false
}
i += 1
p = primes[i]
}
return true
}
for (i = 2; i <= num; i += 1) {
while (!isPrime(n)) {
n += 2
}
primes.push(n)
n += 2
};
return primes[num - 1]
}
console.time('Time')
let x = findPrime(9999)
console.timeEnd('Time')
console.log(x)

determine if array is arithmetic or geometric progression (from Coderbyte)

Here is my functional code, as far as coderbyte is concerned.
But I have a feeling it shouldn't be this complicated.
Am I missing a simple trick?
function ArithGeo(arr)
{
var array_type = -1;
if (arr.length <= 2) return true;
var a = arr[1], r = a/arr[0], i;
for (i = 2; i < arr.length; ++i) {
if ((a *= r) == arr[i]){
array_type = "Geometric";
}
else{
array_type = -1;
break;
}
}
if (array_type == "Geometric")
return array_type;
a = arr[1], d = a - arr[0], i;
for (i = 2; i < arr.length; ++i) {
if ((a += d) == arr[i]){
array_type = "Arithmetic";
}
else {
array_type = -1;
break;
}
}
return array_type;
}
ArithGeo([3,9,15,21,27, 28]);
function ArithGeo(arr) {
var diff = arr[1] - arr[0];
var ratio = arr[1] / arr[0];
var arith = true;
var geo = true;
for(var i = 0; i < arr.length - 1; i++)
{
if( arr[i + 1] - arr[i] !== diff )
arith = false;
if(arr[i + 1] / ratio !== arr[i])
geo = false;
}
if(arith === true)
return "arithmetic";
else if(geo === true)
return" geometric";
else
return -1;
}
Here's a simple solution as well. I'm either looking for a geometric pattern, where a given element will be divisible by the previous element, or an arithmetic pattern, where each element increases by a constant amount. Two variables, diff and ratio, contain each pattern to search for throughout the array.
I start by assuming that arith and geo are true, and if I find an example where one is not true, I set its value to false. Note that your code has two for loops, with the exact same conditions. This is a good indication that your code can be condensed into one loop.
With each pass through the loop, I test whether the conditions are present to set either arith or geo to false. Finally, after the loop exits, I will determine if either arith or geo remained true throughout the loop. If not, I return - 1 as the problem from Coderbyte requests.
edit: quick note on my for loop condition. Since I am checking the value of i + 1 with each pass, I make sure that I don't reach out of bounds by setting my exit condition to arr.length - 1. This way, i + 1 can still reach the last element, and will be sure not to overreach.
For arithmetic progression, subtract each element from previous element; their difference should be equal; for geometric, divide each element by the previous element, the ratio should stay the same. As for divide by zero when you meet 0, javascript gives you Inf (and it certainly is not a geometric progression). Because floats are inaccurate, maybe you'd want to store the min and max of these values and then see if they are close enough to each other.
function arithGeo(arr) {
var minRatio = 1/0,
maxRatio = -1/0,
minDiff = 1/0,
maxDiff = -1/0,
epsilon = 0.000001,
i,
ratio,
diff;
if (arr.length <= 2) {
return;
}
for (i = 1; i < arr.length; ++i) {
diff = arr[i] - arr[i - 1];
ratio = arr[i] / arr[i - 1];
minDiff = Math.min(diff, minDiff);
maxDiff = Math.max(diff, maxDiff);
minRatio = Math.min(ratio, minRatio);
maxRatio = Math.max(ratio, maxRatio);
}
if (Math.abs(minDiff - maxDiff) < epsilon) {
return "Arithmetic";
}
if (Math.abs(minRatio - maxRatio) < epsilon) {
return "Geometric";
}
return;
}
alert(arithGeo([3,9,15,21,27,28]));
alert(arithGeo([3,9,15,21,27]));
alert(arithGeo([4,2,1,0.5]));
It might not be the most efficient way to solve the problem, and it doesn't address the epsilon Problem, that Antti Haapala mentioned, but this is my solution to the problem:
function sequenceMatches(arr, fn) {
var compare = fn(arr[0], arr[1]);
for (var i = 2; i < arr.length; i++) {
if (fn(arr[i - 1], arr[i]) !== compare) return false;
}
return true;
}
function ArithGeo(arr) {
if (sequenceMatches(arr, function(a, b) { return b - a; })) return 'Arithemetic';
if (sequenceMatches(arr, function(a, b) { return b / a; })) return 'Geometric';
return -1;
}
I choose to solve that in two different functions, as that helps to clean up the code imho.
function ArithGeo(arr) {
var apCnt = 1;
var gpCnt = 1;
var diff = arr[1] - arr[0]; //ap difference
var div = arr[1]/arr[0]; //gp difference
for(var i=1;i<arr.length-1;i++){ //traverse array
if(arr[i+1] - arr[i] == diff) { //check for ap
apCnt+=1;
}
else if(arr[i+1]/arr[i] == div) { //check for gp
gpCnt+=1;
}
else{
break; //break if not ap or gp
}
}
return apCnt == arr.length-1 ? "Arithmetic": gpCnt == arr.length-1 ? "Geometric": -1; //return if its ap or gp
}
function ArithGeo(arr){
if(arr == null || !Array.isArray(arr)){
return "error";
}
var length = arr.length;
if(length === 0){
return "neither";
}
if(length === 1){
return "both";
}
var arithCount = 0,
geoCount = 0,
d = arr[1] - arr[0],
q = arr[1] / arr[0];
for(var i = length - 1; i > 0; i--){
if((arr[i] - arr[i-1]) === d){
arithCount++;
}
if((arr[i] / arr[i-1]) === q){
geoCount++;
}
}
if(arithCount === length - 1){
return "Arithmetic";
}else if (geoCount === length - 1){
return "Geometric";
}else if((arithCount === length - 1) && (geoCount === length - 1)){
return "both";
}else{
return "neither";
}
}
Sorry, only considered the integer sequence. #Antti Haapala's answer is correct.
Extremely late but I pretty much did the same on my own (novice javascript user).
It calculates the difference between i + 1 and i (or i + 1 / i) and pushes it into a new array. I then use a function to check if every element in the array is the same.
function numberCheck(array) {
var arithResult = null;
var geoResult = null;
var arithCounter = [];
var geoCounter = [];
Array.prototype.allValuesSame = function() {
for(var i = 1; i < this.length; i++) {
if(this[i] !== this[0])
return false;
} return true;
}
for (var b = 0; b < array.length - 1; b++) {
arithCounter.push(array[b + 1] - array[b]);
}
for (var i = 0; i < array.length - 1; i++) {
geoCounter.push(array[i + 1] / array[i])
}
arithResult = arithCounter.allValuesSame();
geoResult = geoCounter.allValuesSame();
if (arithResult === true) { return "Arithmetic";}
else if (geoResult === true) { return "Geometric";}
else { return "-1";}
}
numberCheck([1,2,4,8])

Categories