Problem 23: Non-abundant sums

I do not understand the reason why this is not working. I am testing until 100 manually and it is operating correctly.

let sumOfProperDivisors = 0;
let number = 0;
let arrayOfAbundantNumbers = [];
let sumOfDeficientNumbers = 0;
let sumOfAbundantNumbers = 0;
let sumOfNumbersWhichCannotBeAdded = 0;
let arrayOfNumbersWhichCannotBeAdded = [];
let limit = 100;
      
      while(number<limit){

			for(let i = 1;i<number;i++){
				
					if(number%i==0){
				    
				           sumOfProperDivisors = sumOfProperDivisors + i; 
												              	
				   		          };
					  };

			if(sumOfProperDivisors>number){
							         arrayOfAbundantNumbers.push(number);
							         sumOfAbundantNumbers=sumOfAbundantNumbers + number; 
							}else{
			                         sumOfDeficientNumbers = sumOfDeficientNumbers + number;
							};

			for(let i = 0;i<arrayOfAbundantNumbers.length;i++){
			        		for(let j = 0;j<arrayOfAbundantNumbers.length;j++){
			        				if(number==arrayOfAbundantNumbers[i] + arrayOfAbundantNumbers[j]){
			                                    arrayOfNumbersWhichCannotBeAdded.push(number);
			                                    sumOfNumbersWhichCannotBeAdded = sumOfNumbersWhichCannotBeAdded + number; 
			                                    //console.log("we cannot add this number to sumOfDeficientNumbers ");

									};	
									break;
                            };
			        };

			    number = number + 1; 
                sumOfProperDivisors = 0;

			};

			total = sumOfDeficientNumbers + sumOfAbundantNumbers  - sumOfNumbersWhichCannotBeAdded;

That nesting makes me suspicious of you timing out

1 Like

No, the nest is not causing me problems. I am getting less than 2 seconds with 28123. The problem is that I am getting a high sum of integers and I do not understand the reason why.

2 seconds is pretty long. That’s a problem.

1 Like

Let me solve that first, then I will come back with a question. Thanks!

I am getting the results with the code, but I am unsure how to optimize it. Do you have any suggestions?

while(number<limit){
		for(let i = 0;i<number;i++){
    
    	  if(number%i==0){
            
            listOfDivisors.push(i);
    	  	sumOfDivisors = sumOfDivisors + i ; 

      	};

	};

	if(sumOfDivisors>number){

        listOfAbudantNumbers.push(number);
	
	};

	sumOfDivisors = 0;
	number = number + 1;

	};			

	for(let i = 0;i<listOfAbudantNumbers .length;i++){
		for(let j = 0;j<listOfAbudantNumbers .length;j++){
                            listOfNumbersThatAreTheSumOfTwoAbundantNumbers.push(listOfAbudantNumbers[i] + listOfAbudantNumbers[j]);
		};

	};

    for(let i = 0;i<limit;i++){

         listOfNumbersUntilLimit.push(i);     
    
    };

    const difference1 = listOfNumbersUntilLimit.filter(item => !listOfNumbersThatAreTheSumOfTwoAbundantNumbers.includes(item));
	
	for(let i = 0 ;i<difference1.length;i++){

      sumOfIntegerThatAreNotTheSumOfTwoAbudantNumbers = sumOfIntegerThatAreNotTheSumOfTwoAbudantNumbers + difference1[i];   
	
	};	

    console.log(sumOfIntegerThatAreNotTheSumOfTwoAbudantNumbers);

Dynamically creating a huge array on each iteration is going to be super slow

1 Like

I made it a little faster with the abundant number feature that indicates every number after 20161 is abundant.

But it is not enough to pass the tests because it is too slow yet.

Do you have any suggestions?

let divisorsOfAnumber=0;
				let number=1;
				let abudantNumber=0;
				let upperBoundLimit=20161;
			    let arrayOfAbundantNumbers=[];
				let iteration = 1;
				let arrayOfIntegerNumbers = [];
				let sumOfAllNumbers = 0;
				let arrayOfTwoAbundantSum = [];
				
				
				
						 while(number<=upperBoundLimit){
								for(let i = 0;i<number;i++){
									if(number%i==0){
										
										divisorsOfAnumber= divisorsOfAnumber + i;
									};
				
								};
				
								if(divisorsOfAnumber>number){
									abudantNumber=number;
			                        arrayOfAbundantNumbers.push(abudantNumber);						
								//console.log("The number "+abudantNumber+" is an abundant number");
								};

								number = number + 1;
								divisorsOfAnumber = 0;

							};

							for(let i = 0;i<arrayOfAbundantNumbers.length;i++){
								for(let j = 0;j<arrayOfAbundantNumbers.length;j++){
									arrayOfTwoAbundantSum.push(arrayOfAbundantNumbers[i]+arrayOfAbundantNumbers[j]);
								};

							};

							//console.log(arrayOfTwoAbundantSum);



							for(let i = 1;i<=upperBoundLimit;i++){
								arrayOfIntegerNumbers.push(i);
							};

							//console.log(arrayOfIntegerNumbers,arrayOfAbundantNumbers);

							let res = arrayOfIntegerNumbers.filter((e) => !arrayOfTwoAbundantSum.includes(e))
							//console.log(res);
						    for(let i = 0;i<res.length;i++){
								sumOfAllNumbers = sumOfAllNumbers + res[i];
							};

							console.log(sumOfAllNumbers);

You’re still dynamically creating the arrays

1 Like

I do not understand the reason why I sum all abundant combinations without duplicates and I sum all natural numbers from 1 to 28123, I get the difference of both of them, and the result is equal to the one in the test.

It should work.

 let cycle = 0;
let outboundLimit = 28123;
let number = 0;
let summatoryOfEveryProperDivisorsOfTheNumber = 0;
let arrayOfNumbersFrom1ToOutboundLimit=[];
let arrayOfAbudantNumberMultiples = [];
let arrayOfAbudantNumbers = [];
let arrayOfAbudantNumberMultiplesWithoutZero=[];
let arrayOfTwoAbundantNumberSums = [];
let arrayOfTwoAbundantNumberSumsSumatory = 0;
let uniqueArrayOfTwoAbundantNumberSums = [];
let deficientAndPerfectNumbersSummatory = 0;
let pivotAbudantNumber = 0;
let positionOfPivotAbudantNumberInArray=0;
let summatoryOfIntegersFrom1tOoutboundLimit = 0;
let arrayOfTwoAbundantNumberSumsSummatory = 0;
while(cycle<=outboundLimit){
		
	number=cycle;
	
	for(let i = 0;i<number;i++){
		if( number % i == 0){
			
			summatoryOfEveryProperDivisorsOfTheNumber=summatoryOfEveryProperDivisorsOfTheNumber+i;
		};
		  
	};
	//console.log("Number: ",number,"Cycle:",cycle,"Summatory Of Every Proper Divisors Of The Number: ",summatoryOfEveryProperDivisorsOfTheNumber);
	if(summatoryOfEveryProperDivisorsOfTheNumber>number){
		arrayOfAbudantNumbers.push(number);
        arrayOfAbudantNumberMultiples.push(number);
		
	};
  
	cycle=cycle+1;
	number = 0;
	summatoryOfEveryProperDivisorsOfTheNumber=0;

   };

   for(let i = 0;i<arrayOfAbudantNumberMultiples.length;i++){
	for(let j = 0;j<arrayOfAbudantNumbers.length;j++){
		   if(arrayOfAbudantNumberMultiples[i]==arrayOfAbudantNumbers[j]){
					 break;
		   }else if(arrayOfAbudantNumberMultiples[i]%arrayOfAbudantNumbers[j]==0){
		     	arrayOfAbudantNumberMultiples[i]=0;
		   };
	};
};

	for(let i = 0;i<arrayOfAbudantNumberMultiples.length;i++){
			if(arrayOfAbudantNumberMultiples[i]>0){
				arrayOfAbudantNumberMultiplesWithoutZero.push(arrayOfAbudantNumberMultiples[i]);
			};
	};

	for(let i = 0;i<arrayOfAbudantNumberMultiplesWithoutZero.length;i++){
		for(let j = 0;j<arrayOfAbudantNumberMultiplesWithoutZero.length;j++){
			       arrayOfTwoAbundantNumberSums.push(arrayOfAbudantNumberMultiplesWithoutZero[i]+arrayOfAbudantNumberMultiplesWithoutZero[j]);
		};
    };

	for(let i = 0;i<uniqueArray.length;i++){
		arrayOfTwoAbundantNumberSumsSumatory = arrayOfTwoAbundantNumberSumsSumatory + uniqueArray[i];
	};
	
	for(let i=0;i<outboundLimit;i++){
		summatoryOfIntegersFrom1tOoutboundLimit = summatoryOfIntegersFrom1tOoutboundLimit + i;
	};
	        console.log(arrayOfTwoAbundantNumberSumsSumatory)
		 console.log(summatoryOfIntegersFrom1tOoutboundLimit)

I realized it. Thanks!

Do you have an idea for simplifying this?

I do not how to pass the last test.

function sumOfNonAbundantNumbers(n) {
let cycle = 0;
let outboundLimit = n;
let number = 0;
let summatoryOfEveryProperDivisorsOfTheNumber = 0;
let arrayOfAbudantNumbers = [];
let arrayOfTwoAbundantNumberSums = [];
let summatoryOfIntegersFrom1tOoutboundLimit = 0;
let arrayOfTwoAbundantNumberSumsSummatory = 0;
while(cycle<outboundLimit){
		
	number=cycle;
	
	for(let i = 0;i<number;i++){
		if( number % i == 0){
			
			summatoryOfEveryProperDivisorsOfTheNumber=summatoryOfEveryProperDivisorsOfTheNumber+i;
		};
		  
	};

	if(summatoryOfEveryProperDivisorsOfTheNumber>number){
		arrayOfAbudantNumbers.push(number);
        
		
	};
  
	cycle=cycle+1;
	number = 0;
	summatoryOfEveryProperDivisorsOfTheNumber=0;

   };

   for(let i =0;i<arrayOfAbudantNumbers.length;i++){
		for(let j =0;j<arrayOfAbudantNumbers.length/2;j++){
			if(arrayOfAbudantNumbers[i]+arrayOfAbudantNumbers[j]<outboundLimit){
					
                        arrayOfTwoAbundantNumberSums.push(arrayOfAbudantNumbers[i]+arrayOfAbudantNumbers[j]);
					
					
	            };
	       };
	};

   const uniqueArray = [...new Set(arrayOfTwoAbundantNumberSums)];

	for(let i = 0;i<uniqueArray.length;i++){

			arrayOfTwoAbundantNumberSumsSummatory = arrayOfTwoAbundantNumberSumsSummatory +  uniqueArray[i];

	};

	for(let i = 0;i<outboundLimit;i++){
		summatoryOfIntegersFrom1tOoutboundLimit = summatoryOfIntegersFrom1tOoutboundLimit + i;
	};
  
 
	return summatoryOfIntegersFrom1tOoutboundLimit - arrayOfTwoAbundantNumberSumsSummatory;
}

sumOfNonAbundantNumbers(10000);

You still have the nested loops and dynamic array allocations?

1 Like

Yes, I have it. I did not know how to make an algorithm to determine if a number were the sum of two abundant numbers.

Array(n).fill(0) allocates an array of size n so you don’t have to waste time changing the size of the array on every push.

Simpler is better in many cases here.

If you have an array that has a boolean flag to show if every number is abundant, then could you make a simple double loop to check for numbers that are the sum of two abundant numbers?

Edit: Also, it may help you to make some atomic helper functions. Though be careful, because sometimes that’s an approach that makes it harder to see where you’re adding unnecessary complication.

Don’t peak until you’re ready, but here’s my stab

// Check if single number is abundant
function isAbundantNumber(n) {
  let divisorSum = 1;

  const limit = Math.sqrt(n);
  for (let i = 2; (i < limit) && (divisorSum <= n); i++) {
    if (n % i === 0) {
      divisorSum += i + (n / i);
    }
  }
  if ((n % limit === 0) && (limit < n)) divisorSum += limit;
  return divisorSum > n;
}

// Check if number is sum of 2 abundant
function isSumOfTwoAbundant(n, isAbundant) {
  for (let i = 1; i <= n / 2; i++) {
    if (isAbundant[i] && isAbundant[n - i]) return true;
  }
  return false;
}

// Find sum of all numbers not a sum of 2 abundant numbers
function sumOfNonAbundantNumbers(n) {
  const isAbundant = Array(n + 1)
                       .fill(0)
                       .map((_, i) => isAbundantNumber(i));

  let sum = 0;
  for (let i = 1; i <= n; i++) {
    if (!isSumOfTwoAbundant(i, isAbundant)) sum += i;
  }
  return sum;
}

console.log(sumOfNonAbundantNumbers(10000));
1 Like

I took a suggestion from this source:

“avoid checking both a + b and b + a by ensuring that b is always >= a”

So, I implemented it in the loop where you told me that it was creating too many operations.

It is not multiplying all iterations. It only operates when the number inner of the inner loop is equal or larger of the outer loop.

I need to study more your solution because I do not how to this without arrays.

Your solution is clever!

function sumOfNonAbundantNumbers(n) {
let cycle = 0;
let outboundLimit = n;
let number = 0;
let summatoryOfEveryProperDivisorsOfTheNumber = 0;
let arrayOfAbudantNumbers = [];
let arrayOfTwoAbundantNumberSums = [];
let summatoryOfIntegersFrom1tOoutboundLimit = 0;
let arrayOfTwoAbundantNumberSumsSummatory = 0;
while(cycle<outboundLimit){
		
	number=cycle;
	
	for(let i = 0;i<number;i++){
		if( number % i == 0){
			
			summatoryOfEveryProperDivisorsOfTheNumber=summatoryOfEveryProperDivisorsOfTheNumber+i;
		};
		  
	};

	if(summatoryOfEveryProperDivisorsOfTheNumber>number){
		arrayOfAbudantNumbers.push(number);
        
		
	};
  
	cycle=cycle+1;
	number = 0;
	summatoryOfEveryProperDivisorsOfTheNumber=0;

   };

   for(let i =0;i<arrayOfAbudantNumbers.length;i++){
		for(let j =0;j<arrayOfAbudantNumbers.length;j++){
      if(arrayOfAbudantNumbers[i]>=arrayOfAbudantNumbers[j]){
            if(arrayOfAbudantNumbers[i]+arrayOfAbudantNumbers[j]<outboundLimit){
					
                            arrayOfTwoAbundantNumberSums.push(arrayOfAbudantNumbers[i]+arrayOfAbudantNumbers[j]);
					
					
	                };

      };
  			
	       };
	};

   const uniqueArray = [...new Set(arrayOfTwoAbundantNumberSums)];

	for(let i = 0;i<uniqueArray.length;i++){

			arrayOfTwoAbundantNumberSumsSummatory = arrayOfTwoAbundantNumberSumsSummatory +  uniqueArray[i];

	};

	for(let i = 0;i<outboundLimit;i++){
		summatoryOfIntegersFrom1tOoutboundLimit = summatoryOfIntegersFrom1tOoutboundLimit + i;
	};
  
 
	return summatoryOfIntegersFrom1tOoutboundLimit - arrayOfTwoAbundantNumberSumsSummatory;
}

I used arrays, but just one. For something like this, its better to use a single array allocation instead of continually pushing onto the array though.

Also, you’ve still got tripply nested lops, and you generally want to start getting suspicious the deeper your loop nesting gets.

1 Like

Let me try to solve that. I use loops because it is one of the ways I understand the problems, but I need to explore other ways to solve problems. I appreciate your feedback a lot, and I will work on it.