Perfect squares from odd numbers - javascript

In JavaScript, is there a more efficient way of calculating perfect squares working from odd numbers than this (the last perfect square stored in the array perfectSqrs is console.logged):
let n = 999,
oddNums = [],
i;
for (i = 3; i < n; i += 1) {
if (i % 2 !== 0) {
oddNums.push(i);
}
}
let oddLength = oddNums.length;
let perfectSqrs = [1],
j = 0;
while (j < oddLength - 1) {
perfectSqrs[j + 1] = perfectSqrs[j] + oddNums[j];
j += 1;
}
console.log(perfectSqrs[perfectSqrs.length - 1]);

Looks like you just want to generate an array of perfect squares? Perhaps you can do something like this:
var squares = [1];
var numSquares = 100;
for (var i=3; i<numSquares*2; i+=2) {
squares.push(squares[squares.length - 1] + i);
}
console.log(squares);
For people unclear about this algorithm, basically:
1
4 (1+3)
9 (1+3+5)
16 (1+3+5+7)
25 (1+3+5+7+9)
Perfect square is essentially the sum of odd numbers

Nothing to do with JS more with algorithms and logic. You can totally avoid the first loop and also avoid storing (memory efficiency) odd numbers. Start your second loop with 1 and iterate by incrementing by 2 instead of 1 (1,3,5,7,...).

Related

How come it doesn't slice a number until the end despite including the number's length

I made a code to extract every odd numbers from one number, and it works for numbers that are not too long such as "1341" (which give me the numbers "1,13,1341,341,41,1") but oddly doesn't work for very long numbers.
function solve(s) {
var newarray = [];
for (var i = 0; i <= s.length; i++) {
for (var j = 0; j <= s.length; j++) {
var slicing = s.slice(i, j);
if (slicing % 2 !== 0) {
newarray.push(slicing);
}
}
}
return newarray.length;
}
Despite putting s.length, it slices until a certain point. For example:
With "93711892377292643581488317", it slices until "9371189237729", then when it starts from 3 it slices until "93711892377292643" (until the next odd number)
With "65266112954758467", from the start it slices until "6526611295475", then when it starts from 5, it slices until "65266112954758467" (until the next odd number).
What's going on?
slicing % 2 doesn't work properly when slicing is large. Javascript treats large numbers as floating-point numbers, which means it's not accurate to know the value to the nearest integer - in binary, the units bit becomes 0, so it's a multiple of 2.
You want to count all odd numeric substrings within a numeric string.
First, consult the documentation of str.slice(beginIndex[, endIndex]).
Then, in order to gain a better understanding of your code, it is helpful to slowly iterate through a few steps of your loops and write down the expected vs. the observed output.
I recommend to use the debugger built into all modern browsers:
Add a debugger; statement into the inner for-loop:
function solve(s) {
var newarray = [];
for (var i = 0; i <= s.length; i++) {
for (var j = 0; j <= s.length; j++) {
var slicing = s.slice(i, j);
debugger; // <-- we want to break here and check our values
if (slicing % 2 !== 0) {
newarray.push(slicing);
}
}
}
return newarray.length;
}
Press [F12] and run this code in your browser's console for some exemplary input.
The debugger tab should now pop up. Press [F8] to step through your code and keep track of the value of your slicing variable.
You will probably notice that slicing is empty at the beginning. You should start your inner loop from j = i + 1 to fix that.
Also, you might notice that your i iterates one time too many, so that slicing is empty during the final iterations of the inner for-loop. You need to terminate your outer loop one step earlier.
Then, for the problematic input "93711892377292643581488317" you will notice that large numeric slices such as "93711892377292643" will not be recognized as odd. "93711892377292643" % 2 evaluates to 0 instead of 1. In order to understand this, you need to know that JavaScript numbers are internally represented as limited precision floating point values. If you put 93711892377292643 into your browser console, it will evaluate to 93711892377292640 - an even number! JavaScript can only handle integer numbers up to Number.MAX_SAFE_INTEGER == 9007199254740991 without introducing such truncation errors.
Now, how to solve this issue? Well, a number is odd if and only if the last digit is odd. So we don't have to inspect the full number, just the last digit:
function solve(s) {
var newarray = [];
for (var i = 0; i < s.length; i++) {
for (var j = i; j < s.length; j++) {
var digit = s.slice(j, j + 1);
if (digit % 2 !== 0) {
var slicing = s.slice(i, j + 1);
newarray.push(slicing);
}
}
}
return newarray.length;
}
console.log(solve("1234567890")); // 25
Once you have sufficient understanding of this code, you could start improving it. You could for example replace the newarray with a simple counter, as you are only interested in the number of off digits, not the digits themselves.
A faster solution could be written down as follows:
function solve(str) {
let count = 0;
for (let i = 0; i < str.length; i++) {
if (str[i] % 2) count += i + 1;
}
return count;
}
console.log(solve("1234567890")); // 25
Or, written in a more declarative way:
const solve = (str) =>
str.split('').reduce((count, chr, i) => chr % 2 ? count + i + 1 : count, 0);
console.log(solve("1234567890")); // 25

How to Create a For-Loop that calculates 6Factorial

To do this you must multiply 6*5*4*3*2*1. To verify your loop is working correctly, the value you are looking for as a result is: 720
var dvDDG = document.querySelector("#ddg");
for(var i = 0; i < 7; i++) {
//remainder..
if( (i*7) == 720 ) {
dvDDG.innerHTML += i + "<br />";
}
}
I'm not entirely certain what you're trying to do with the code you have, it will simply check all numbers zero through six inclusive, and output the value which, when multiplied by seven, is equal to 720.
Since the highest value you'll get is 6 x 7 = 42 (nowhere near 720), you'll see nothing.
The pseudo-code for what you're after would be along the lines of:
fact = 1
for i = 2 to N inclusive:
fact = fact * i
print fact
Turning that into Javascript (or any procedural language for that matter) should be fairly simple, such as with:
function fact(n) {
res = 1
for (var i = 2; i <= n; i++) {
res = res * i;
}
return res
}
alert(fact(6))
It's fairly simple:
var factorial = 1;
var num = 6;
for (var i = 1; i <= num; i++){
factorial *= i;
}
There you go, your answer is the variable factorial. Just copy it into any output function you want. Be careful though, factorial can get pretty huge very fast. Try not to experiment on numbers that much larger that 6.

Javascript Euler Fibonacci for loop

I'm doing the Euler project problem 2 in which the objective is to sum the even numbers of the fibonacci sequence that have a value of less than 4 million. I've searched a bit and I've seen several solutions using a while loop but nothing simple using a for loop. I'm curious why I'm returning zero with the following code:
var array = [];
array[0] = 0;
array[1] = 1;
var total = 0;
for(var i=2;total<=4000000;i++) {
array[i] = array[i-1] + array[i-2];};
for(var x=0;x<array.length;x++){
if(array[x]%2 === 0){
total += array[x]};};
alert(total);
I'm guessing the problem is in my for loop using the total variable. I couldn't get it to work using array[i]<=4000000 either and I'm really curious behind the why here. Anyone know why this is? What can I change in the for loop condition (second statement) to get a correct total here?
First of all there is an infinite loop at first for. Your condition must be array[i-1] < 4000000. After that your second for loop will find the correct result.
Also for the problem, you don't need to store all fibonacci numbers then find sum of even numbers.
You can calculate sum when calculating fibonacci.
var first = 0;
var second = 1;
var sum = 0;
for(var current=first+second; current < 4000000; current = first+second){
if(current%2 === 0){
sum+=current;
}
first = second;
second = current;
}
I fixed it for you.
var i, data = [ 0, 1 ], total = 0;
for (i = 2; i <= 4000000; i++)
{
data[i] = data[i - 1] + data[i - 2];
if (data[i] % 2 === 0)
{
total += data[i];
}
}
alert(total);
I'm not sure what you termination condition should be like, you say have a value of less than 4 million, but this is ambiguous. Maybe it should be total <= 4000000 or data[i] <= 4000000. Your phrasing is not precise enough.
Sorry but for me your code going in a dead loop. first "for" use total as check but it's never incremented. If you want This is a solution for fibonacci sequence based on dinamic programming with memoization tecnic.
var f1 = 1;
var f2 = 1;
for(var i = 2; i < 40000; i++){
console.info(i, f1, f2);
var temp = f1 + f2;
f1 = f2;
f2 = temp;
}
alert(f2);

Get index of array at equal points

Let's say you have an array of length 20. You want to access 3 equally spaced indices: 0, 9, 19.
How can you do this with any length of array and any number of sections?
I feel like there must be an elegant way of doing it, but the only way I can think of is finding the section size (var len = 20 / (3 -1)), iterating over the total number of sections (for (var i = 0; i < 3; i++) { var row = data[len * i]; }), and then subtracting one for non-zero indices.
You could try something like this (where console.log is used now you can call your array):
var amount = 3;
var total = 20;
var size = (total - 1) / (amount - 1);
for(var i = 0; i < amount; i++) {
console.log(Math.floor(size * i));
}
There isn't realy a more elegant solution.

string addition I coderbyte completely stumped

Can anyone explain the solution to me like a 6 year old? I haven't been able to make sense of the solutions. Maybe some code comments?
Thank you.
I've spent the last 2 hours on coderbyte trying to solve this one. Here's the question:
Have the function ArrayAdditionI(arr) take the array of numbers stored
in arr and return the string true if any combination of numbers in the
array can be added up to equal the largest number in the array,
otherwise return the string false. For example: if arr contains [4, 6,
23, 10, 1, 3] the output should return true because 4 + 6 + 10 + 3 =
23. The array will not be empty, will not contain all the same elements, and may contain negative numbers.
I've scoured the internet, read through a bunch of people's solutions from the people's answers on coderbyte itself, but without any comments I'm really struggling to figure out how this is done. I've started over countless times, so I'm not even sure if this last attempt is any better or not.
I understand that I'll need to loop through somehow and test every combination index 5, index 4, index 3, index 2, index 1, AND every combination of less than all of those (ie just index 5 and index 3). I just can't figure out how to do that. If I knew the list would always be an array of 5 numbers, and it required all 5, I would write 5 loops all equally nested inside of one big one, right? However, with the added complexity of not requiring all numbers and not knowing the length of the array for all cases, I am completely stumped. I tried using Math.floor(Math.random() * array.length); to generate a list of numbers... but that didnt work either.
function ArrayAdditionI(arr) {
var longest = arr.sort( function(a,b) { return a-b });
var longest = longest[longest.length - 1];
var sumArr = function (arrb) {
var sum = 0;
for (var z = 0; z < arrb.length; z++){
sum += arrb[z];
}
return sum;
};
for (var i = 0; i > arr.length; i++) {
for (var y = 0; y > arr.length; i++) {
testArr.push(arr[i]);
if (sumArr(testArr) === longest) {
return true;
}
testArr.push(... its 4am and I'm stumped!...)
}}
// code goes here
return false;
}
// keep this function call here
// to see how to enter arguments in JavaScript scroll down
ArrayAdditionI(readline());
A fairly simple to understand and common solution to the problem is as follows. It basically starts by looping forward through the array (loop i) by adding each subsequent number (loop j). If loop j finishes without a solution, loop k begins and removes each subsequent number. Then i increments and the loops start over.
function ArrayAdditionI(arr) {
arr.sort(function(a,b){return a - b})
var largest = arr.pop(); // Set largest to last (largest) array value
var sum = 0;
for (var i = 0; i < arr.length; i++){ // Start outer loop
sum += arr[i];
for (var j = 0; j < arr.length; j++){ // Start inner to begin sum
if (i != j) { // Ensure we don't add the same array index to itself
sum += arr[j];
console.log(sum);
if (sum == largest) {
return true;
}
}
}
for (var k = 0; k < arr.length; k++) { // If no match, start 2nd loop to re-iterate removing index values
if (i != k) {
sum -= arr[k];
console.log(sum);
if (sum == largest) {
return true;
}
}
}
sum = 0; // Reset sum for outer loop
}
return false;
}
The comment by thefourtheye basically told you the name of the problem and what to search for on google.
Solutions in java code would be the following...
1) find all subsets that sum to a particular value
This is the theory and pseudocode.
2) How to implement the Sum of Subsets problem in Java
Change the code to return what you wish if number of sets > 0 .
3) Modify GetAllSubsetByStack in below code to stop when a set is found:
https://codereview.stackexchange.com/questions/36214/find-all-subsets-of-an-int-array-whose-sums-equal-a-given-target
We did a similar recursion for a "MakeChange" algorithm at a meetup I went to last night. This morning I took a look at this problem with fresh eyes after not looking at it for a few weeks. Here's what I came up with.
Essentially: sort the array to biggest to smallest, shift that one off and declare it "goal", then recursively reduce an array by slicing it smaller and smaller each recurse, when the array reaches 0 length, randomize the original array and begin reducing again.
return true if goal = total (ie the reduce)
return false if ive randomized the array more than 1000 times.
function ArrayAdditionI(arr) {
var originalArr = arr.sort(function(a,b) {return b-a});
var goal = arr.shift();
var counter = 0;
function randomArray(array) {
for (var i = array.length - 1; i > 0; i -= 1){
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
function recurse(arr) {
if (arr.length == 0){
counter++
var newArr = randomArray(originalArr);
return recurse(newArr);
} else {
var total = arr.reduce(function(a,b) {return a+b});
if (goal == total){
return true
} else if (counter == 1000) {
return false
} else {
newArr = arr.slice(1);
return recurse(newArr);
}
}
}
// code goes here
return recurse(originalArr);
}

Categories