My results for numbers between 1 and 28321 (limit)
sum of all numbers: 395465626
sum of all abundant numbers: 392188885
sum of all non abundant numbers: 3276741 (correct answer is 4179871)
var divisors = function(number){
sqrtNumber = Math.sqrt(number);
var sum = 1;
for(var i = 2; i<= sqrtNumber; i++)
{
if (number == sqrtNumber * sqrtNumber)
{
sum += sqrtNumber;
sqrtNumber--;
}
if( number % i == 0 )
{
sum += i + (number/i);
}
}
if (sum > number) {return true;}
else {return false;}
};
var abundent = [], k = 0;
var upperLimit = 28123;
for (var i = 1; i <= upperLimit; i++)
{
if (divisors(i))
{abundent[k] = i; k++};
}
var abundentCount = abundent.length;
var canBeWrittenAsAbundant = [];
for (var i = 0; i < abundentCount; i++){
for (var j = i; j < abundentCount; j++){
if (abundent[i] + abundent[j] <= upperLimit){canBeWrittenAsAbundant[abundent[i]+abundent[j]] = true;}
else {
break;
}
}
}
for (i=1; i <= upperLimit; i++){
if (canBeWrittenAsAbundant[i] == true){continue;}
else {canBeWrittenAsAbundant[i] = false;}
}
var sum = 0;
for (i=1; i <= upperLimit; i++)
{
if (!canBeWrittenAsAbundant[i]){
sum += i;
}
}
console.log(sum);
I'm using http://www.mathblog.dk/project-euler-23-find-positive-integers-not-sum-of-abundant-numbers/ as guidance, but my results are different. I'm a pretty big newb in the programming community so please keep that in mind.
You do not need to calculate the sum of all numbers using a cycle, since there is a formula, like this:
1 + 2 + ... + number = (number * (number + 1)) / 2
Next, let's take a look at divisors:
var divisors = function(number){
sqrtNumber = Math.sqrt(number);
var sum = 1;
for(var i = 2; i<= sqrtNumber; i++)
{
if (number == sqrtNumber * sqrtNumber)
{
sum += sqrtNumber;
sqrtNumber--;
}
if( number % i == 0 )
{
sum += i + (number/i);
}
}
if (sum > number) {return true;}
else {return false;}
};
You initialize sum with 1, since it is a divisor. However, I do not quite understand why do you iterate until the square root instead of the half of the number. For example, if you call the function for 100, then you are iterating until i reaches 10. However, 100 is divisible with 20 for example. Aside of that, your function is not optimal. You should return true as soon as you found out that the number is abundant. Also, the name of divisors is misleading, you should name your function with a more significant name, like isAbundant. Finally, I do not understand why do you decrease square root if number happens to be its exact square and if you do so, why do you have this check in the cycle. Implementation:
var isAbundant = function(number) {
var sum = 1;
var half = number / 2;
for (var i = 2; i <= half; i++) {
if (number % i === 0) {
sum += i;
if (sum > number) {
return true;
}
}
}
return false;
}
Note, that perfect numbers are not considered to be abundant by the function.
You do not need to store all numbers, since you are calculating aggregate data. Instead, do it like this:
//we assume that number has been initialized
console.log("Sum of all numbers: " + ((number * (number + 1)) / 2));
var abundantSum = 0;
var nonAbundantSum = 0;
for (var i = 0; i <= number) {
if (isAbundant(i)) {
abundantSum += i;
} else {
nonAbundantSum += i;
}
}
console.log("Sum of non abundant numbers: " + nonAbundantSum);
console.log("Sum of abundant numbers: " + abundantSum);
Code is not tested. Also, beware overflow problems and structure your code.
Below is the Corrected Code for NodeJS..
var divisors = function (number) {
sqrtNumber = Math.sqrt(number);
var sum = 1;
var half = number / 2;
for (var i = 2; i <= half; i++) {
if (number % i === 0) { sum += i; }
}
if (sum > number) { return true; }
else { return false; }
};
var abundent = [], k = 0;
var upperLimit = 28123;
for (var i = 1; i <= upperLimit; i++) {
if (divisors(i)) { abundent[k] = i; k++ };
}
var abundentCount = abundent.length;
var canBeWrittenAsAbundant = [];
for (var i = 0; i < abundentCount; i++) {
for (var j = i; j < abundentCount; j++) {
if (abundent[i] + abundent[j] <= upperLimit) { canBeWrittenAsAbundant[abundent[i] + abundent[j]] = true; }
else {
break;
}
}
}
for (i = 1; i <= upperLimit; i++) {
if (canBeWrittenAsAbundant[i] == true) { continue; }
else { canBeWrittenAsAbundant[i] = false; }
}
var sum = 0;
for (i = 1; i <= upperLimit; i++) {
if (!canBeWrittenAsAbundant[i]) {
sum += i;
}
}
console.log(sum);
Related
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
}
}
I was looking for an answer for a question from Project Euler and I found one here
http://www.mathblog.dk/triangle-number-with-more-than-500-divisors/
int number = 0;
int i = 1;
while(NumberOfDivisors(number) < 500){
number += i;
i++;
}
private int NumberOfDivisors(int number) {
int nod = 0;
int sqrt = (int) Math.Sqrt(number);
for(int i = 1; i<= sqrt; i++){
if(number % i == 0){
nod += 2;
}
}
//Correction if the number is a perfect square
if (sqrt * sqrt == number) {
nod--;
}
return nod;
}
So I tried to implement the same solution in Javascript but it doesn't give me the same result.
var number = 0;
var i = 1;
while (numberOfDivisors(number) < 500) {
number += i;
i++;
}
console.log(number);
function numberOfDivisors(num) {
var nod = 0;
var sqr = Math.sqrt(num);
for (i = 1; i <= sqr; i++) {
if (num % i === 0) {
nod += 2;
}
}
if (sqr * sqr == num) {
nod--;
}
return nod;
}
I tested the other code in C# and it gives the right solution. I was wondering if I made a mistake or whether they work differently in some aspect I'm unaware of.
The problem is that you are testing non-triangle numbers because you forgot one important thing ... scope ...
for (i = 1; i <= sqr; i++) {
screws your (global) value of i ...
see in c# you have
for(int i = 1; i<= sqrt; i++){
^^^
give javascript the same courtesy and try
for (var i = 1; i <= sqr; i++) {
^^^
you should also get the square root as an integer, otherwise you'll be one off in most counts
var sqr = Math.floor(Math.sqrt(num));
i.e.
var number = 0;
var i = 1;
console.time('took');
while (numberOfDivisors(number) < 500) {
number += i;
i++;
}
console.timeEnd('took');
console.log(number);
function numberOfDivisors(num) {
var nod = 0;
var sqr = Math.floor(Math.sqrt(num));
for (var i = 1; i <= sqr; i++) {
if (num % i === 0) {
nod += 2;
}
}
if (sqr * sqr == num) {
nod--;
}
return nod;
}
(added some timing info for fun)
https://codepen.io/aholston/pen/ZJbrjd
The codepen link has commented code as well as actual instructions in HTML
Otherwise.... what I ultimately have to do is write a function that takes two params(a and b) and takes all the numbers between those two params (a-b) and put every number that can be added to the consecutive fowers and be equal to that number into a new array. Ex: 89 = 8^1 + 9^2 = 89 or 135 = 1^1 + 3^2 + 5^3 = 135
function sumDigPow(a, b) {
// Your code here
var numbers = [];
var checkNum = [];
var finalNum = [];
var total = 0;
for (var i = 1; i <= b; i++) {
if (i >= a && i <= b) {
numbers.push(i);
}
}
for (var x = 0; x < numbers.length; x++) {
var checkNum = numbers[x].toString().split('');
if (checkNum.length == 1) {
var together = parseInt(checkNum);
finalNum.push(together);
} else if (checkNum.length > 1) {
var together = checkNum.join('');
var togNumber = parseInt(together);
for (var y = checkNum.length; y > 0; y--) {
total += Math.pow(checkNum[y - 1], y);
}
if (total == togNumber) {
finalNum.push(togNumber);
}
}
}
return finalNum;
}
try this:
function listnum(a, b) {
var finalNum = [];
for (var i = a; i <= b; i++) {
var x = i;
var y = i;
var tot = 0;
j = i.toString().length;
while (y) {
tot += Math.pow((y%10), j--);
y = Math.floor(y/10);
}
if (tot == x)
finalNum.push(i);
}
return finalNum;
}
console.log(listnum(1, 200));
Okay, after debugging this is what I learned.
for (var y = checkNum.length; y > 0; y--) {
total += Math.pow(checkNum[y - 1], y);
}
if (total == togNumber) {
finalNum.push(togNumber);
}
}
}
return finalNum;
}
Everytime this loop happened, I neglected to reset the 'total' variable back to 0. So I was never getting the right answer for my Math.pow() because my answer was always adding to the previous value of total. In order to fix this, I added var total = 0; after i decided whether or not to push 'togNumber' into 'finalNum.' So my code looks like this..
for (var y = checkNum.length; y > 0; y--) {
total += Math.pow(checkNum[y - 1], y);
}
if (total == togNumber) {
finalNum.push(togNumber);}
}
var total = 0;
}
return finalNum;
}
I'm trying to write a simple program to calculate the biggest even number from an array.
An array of 10 elements is used.
function biggestEven(array) {
var numberOfNumbers = array.length;
var biggestYet = 0;
var theNumber;
for (var i = 0; i < numberOfNumbers; i++) {
if(array[i] % 2 = 0) {
biggestYet = array[i];
}
if(array[i] % 2 = 0 && array[i] > biggestYet) {
theNumber = biggestYet;
}
}
return theNumber;
}
var myArray = [];
for (var i = 0; i < 10; i++) {
myArray[i] = window.prompt("Enter number " + (i+1) + "of 10:");
}
console.log("The biggest even number is: " + biggestEven(myArray));
Please help I am stuck. The program won't lead in chrome.
You're giving a value, not comparing:
if(array[i] % 2 = 0) {
biggestYet = array[i];
}
And also you were returning the wrong element:
function biggestEven(array) {
var numberOfNumbers = array.length;
var biggestYet = 0;
var theNumber = 0;
for (var i = 0; i < array.length; i++) {
if (array[i] % 2 === 0) {
biggestYet = array[i];
}
if (array[i] % 2 === 0 && array[i] > biggestYet) {
theNumber = biggestYet;
}
}
return biggestYet;
}
var myArray = [];
for (var i = 0; i < 2; i++) {
myArray[i] = window.prompt("Enter number " + (i+1) + " of 10:");
}
console.log("The biggest even number is: " + biggestEven(myArray));
This might help:
console.log(Math.max(...[267, 306, 108, 307].filter(function(value) { return value % 2 === 0 })));
You need to change
if(array[i] % 2 = 0) {
biggestYet = array[i];
}
to
if(array[i] % 2 == 0) {
biggestYet = array[i];
}
Here is a solution for your problem
function biggestEven(array) {
return Math.max(...array.filter(function(num){
return num%2==0;
}));
}
var myArray = [1,2,36,45,51,16,7];
alert(biggestEven(myArray));
I am trying this code
var sum = 0
for (i = 0; i < 2000000; i++) {
function checkIfPrime() {
for (factor = 2; factor < i; factor++) {
if (i % factor = 0) {
sum = sum;
}
else {
sum += factor;
}
}
}
}
document.write(sum);
I am getting this error:
Invalid left-hand side in assignment
Change if(i % factor = 0) to if( i % factor == 0) and remove the function checkIfPrime() inside the for loop.
var sum = 0
for (i = 0; i < 2000000; i++) {
for (factor = 2; factor < i; factor++) {
if (i % factor == 0) {
sum = sum;
}
else {
sum += factor;
}
}
}
document.write(sum);
The function inside the loop is pointless.
it looks like your code outputs wrong result, for example prime numbers below 6 are 2, 3 and 5, their sum is 10, your code outputs 14 in this case.
Here is another code which outputs sum of primes below max value:
var sieve = [], primes = [], sum = 0, max = 5;
for (var i = 2; i <= max; ++i) {
if (!sieve[i]) {
// i has not been marked -- it is prime
sum += i;
for (var j = i << 1; j <= max; j += i) {
sieve[j] = true;
}
}
}
console.log(sum);
credit to How to find prime numbers between 0 - 100?
function sumPrimes(num) {
var sum = 0;
for (var i = 2; i < num; i++) {
if (isPrime(i)) {
sum += i;
console.log(sum);
}
}
return sum;
}
function isPrime(num) {
if (num <= 1) return false;
else if (num <= 3) return true;
else if (num % 2 == 0 || num % 3 == 0) return false;
var i = 5;
while (i * i <= num) {
if (num % i == 0 || num % (i + 2) == 0) return false;
i += 6;
}
return true
}
console.log(sumPrimes(2000000));
Well, I did with 250 otherwise my screen would have frozen. First of you have to single out the prime numbers after placing them inside an empty Array, which I called primeNumbers from 2 to whatever number you want. Then I create a function that would filter the prime numbers and then add them all with a reduce method inside of another variable called sum and return that variable.
var primeNumbers =[];
for(var i = 2; i < 250; i++){
primeNumbers.push(i);
}//for loop
function isPrime(value){
for(var x=2; x< value; x++){
if(value % x===0){
return false;
}
}//for loop
return true;
}//function isPrime to filter
var sum = primeNumbers.filter(isPrime).reduce(function(acc, val) {
return acc + val;
}, 0);
console.log(sum);
when you are using a variable inside the loop you need to declare them. You have two points in this case
i is not declared
factor is not declare
Your if (i % factor = 0) is wrong, as pointed by some people above.
Also, you never call the checkIfPrime() method. I don't why you created them. Also, I improved your checkIfPrime() method. Please call sumOfPrimes() method in the code below and it should work. You can modify it according to your need
function sumOfPrimes()
{
var sum =0;
for (var i = 0; i < 2000000; i++)
{
var temp = Math.sqrt(i);
for (var factor = 2; factor < temp; factor++)
{
if (i % factor === 0)
{
sum += factor;
}
}
}
console.log(sum);
}
Try changing this line if (i % factor = 0) {
to
if (i % factor == 0) {