I need to remove items from array until there is only one - javascript

I have made array and all but i only need function that clears every second item from list and doing that job until there is only 1 item left for example i need something to do in array from 1-10 including 1 and 10 the result need to be 5?
Any sugestions it is similar like this but only need it for javascript not python
How to delete elements of a circular list until there is only one element left using python?
I am using this inside html body tag
var num = prompt("type num");
var array = [];
for (i = 1; i <= num; i++) {
array.push(i);
}
document.write(array + "<br>");
I tried this so far but this does not finish jobs great
while (i--) {
(i + 1) % 2 === 0 && array.splice(i, 1)
}
It does only first time deleting and leave array 1 3 5 7 9 i need it to be only 5 in this case because prompt is 10 in my case

The circular part makes it pretty tricky. Your loop condition should be on array length > 1, and within the loop you have to manually mess with the counter once it exceeds the length of the array - 2. If it's equal to arr.length, you want to skip the first element of the array the next time around, otherwise begin with the first element. Sorry I'm not explaining it better, here is the code.
var arr = [1,2,3,4,5,6,7,8,9,10];
var i = 1;
while (arr.length > 1) {
console.log("removing " + arr[i]);
arr.splice(i, 1);
var left = arr.length - i;
if (left == 0)
i = 1;
else if (left == 1)
i = 0;
else
i++;
}
console.log("result " + arr[0]);
Edit - This is almost exactly The Josephus Problem or see the episode from Numberphile on Youtube
There is a short recursive way to solve it. The parameter n is the largest number (similar to an array of n numbers from 1 to n), and k being the number of positions to skip at a time, (every other being 2).
var josephus = (n, k) => {
if (n == 1) return 1;
return (josephus(n - 1, k) + k-1) % n + 1;
};
console.log(josephus(10, 2));

while(array.length > 1) {
array = array.filter((_, index) => index % 2 === 0);
}
Basically, get rid of every second index as long as the length is greater than 1. The callback for filter allows value as the first parameter and index as the second, per MDN.

Related

Fibonacci sequence generator not working for 1 or 2 as inputs but it works for the rest of the sequence?

Can someone explain to me why my fibonacciGenerator function doesn't work with this code? I understand why it works with the second code tho but I just don't get why the first one doesn't.
function fibonacciGenerator(n) {
if (n > 0) {
var fArray = [];
fArray.push(0);
if (n >= 2) {
fArray.push(1);
}
for (var i = 0; i < n; i++) {
fArray.push(fArray[i] + fArray[i + 1]);
}
console.log(fArray);
}
}
fibonacciGenerator(1);
fibonacciGenerator(2);
Second code working :
function fibonacciGenerator(n) {
if (n > 0) {
var fArray = [];
fArray.push(0);
if (n >= 2) {
fArray.push(1);
}
for (var i = 2; i < n; i++) {
fArray.push(fArray[i - 1] + fArray[i - 2]);
}
console.log(fArray);
}
}
fibonacciGenerator(1);
fibonacciGenerator(2);
The first code is printing 2 extra Fibonacci number this is because:
you are first pushing 0 and 1 into the array as:
var fArray = [];
fArray.push(0);
if (n >=2 ){
fArray.push(1);
}
and then you loop over again till n times. Because of this reason it prints two extra Fibonacci numbers.
the solution is to either loop over n-2 time or to use the second code.
var fArray = [];
fArray.push(0);
if (n >= 2) {
fArray.push(1);
}
The initial condition is to cover n=1: [0] and n=2: [0,1]
The 2nd code is working because the loop only starts when n is greater than i, so means it skips the loop with n < 2.
For your problem, you don't skip the loop when n < 2.
for (var i = 0; i < n; i++) {
fArray.push(fArray[i] + fArray[i + 1]);
}
You can imagine the result will be like below when n < 2 with your loop.
Note that the inital value is fArray = [0]
fArray.push(fArray[0] + fArray[1]); //fArray[1] is undefined because you only have 1 item in your array
In this case fArray[0] + fArray[1] ==> 0 + undefined = NaN
So that's why your logic does not work when n < 2
To correct it, you need to avoid the loop if n < 2
//if n=1 or n=2, it won't trigger the loop due to `i < n-2`
for (var i = 0; i < n-2; i++) {
fArray.push(fArray[i] + fArray[i + 1]);
}
The idea to have i start with 0 instead of 2, and to adjust the body of the loop accordingly, is fine, but there is one thing that the first version didn't adjust: the stop condition of the loop.
By setting i=0, the first version loops 2 times more than the second version. You should also alter the end condition in the same way: instead of i < n, it should have i < n - 2, so to ensure the number of iterations is the same as in the second version.
Not related to your question, but the console.log should better be placed outside of the function. The job of the function should be to return the array, not to print it. So also, when n > 0 is false, it should return an empty array.
function fibonacciGenerator(n) {
var fArray = [];
if (n > 0) {
fArray.push(0);
if (n >= 2) {
fArray.push(1);
}
for (var i = 0; i < n - 2; i++) {
fArray.push(fArray[i] + fArray[i + 1]);
}
}
return fArray;
}
console.log(fibonacciGenerator(1));
console.log(fibonacciGenerator(2));
First you have to identify the pattern.
Fibonacci series -> 0 1 1 2 3 5 8 13 21
Term -> 0 1 2 3 4 5 6 7 8
0th term =0, 1st term =1
From the second term,
2nd = 1st term + 0th term = 1+0 = 1
3rd = 2nd term + 1st term = 1+1 = 2
4th = 3rd term + 2nd term = 2+1 = 3
5th = 4th term + 3rd term = 3+2 = 5
nth = (n-1) + (n-2)
since the first 2 terms are fixed, you have to start for loop from i= 2.
Also, according to the above shown pattern, you have to use following code inside the for loop.
fArray.push(fArray[i - 1] + fArray[i-2]);

How does one, within a sequence of digits, count how many times a digit appears thats value is exactly one less than the previous digit's one?

code:
function OneDecremented(num) {
num = num.toString()
var count = 0
for(i = 1; i < num.length; i++) {
if(num[i - 1] - num[i] === 1){
count++
}
}
return count
}
console.log(OneDecremented(9876541110))
so I'm struggling to understand two things:
what's the difference between i and num[i]
I don't understand how the calculation is happening inside the if statement, could someone break it down?
sorry if these questions sound too silly, I'm new to JS and couldn't really get my head around the arithmetic calculations. Thank you for you time.
That code is poorly written for few reasons, but most importantly, it leaks the i reference globally so, let's start with a better version:
function OneDecremented(num) {
var str = num.toString();
var count = 0;
for(var i = 1; i < str.length; i++) {
if(str[i - 1] - str[i] === 1)
count++;
}
return count;
}
Strings, in modern JS, can be accessed like arrays, and the index returns the char at the index position:
if(str[i - 1] - str[i] === 1)
// is the same as
if ((str.charAt(i - 1) - str.charAt(i)) === 1)
Once retrieved each char, the code does an implicit "char to number" conversion, thanks to the - operator, but if it was a + instead, it would've concatenated the two chars as string instead (so, be careful).
It's always better to be explicit, but if you know how - works, it does the job for this task.
The loop starts from 1, and it checks that the char at i - 1, which is in the first iteration the char at index 0, minus the current char, is 1, meaning the current char is one less the previous.
When that's the case, the counter sums up.
Andrea and Mitya already nailed it.
The next step could be switching to a first class based approach like using a specific Array method such as reduce.
Such an approach, if implemented correctly, usually improves readability/maintainability of code and allows for better code-reuse.
For the example provided by the OP one could write two functions, the actual method, which gets the count and the above mentioned first class reducer functionality. Since reduce is a standard way of how arrays can be processed the arguments-precedence of the reducer/callback is well specified too ...
[/* ... */].reduce(function(accumulator, currentValue, currentIndex, currentlyProcessedArray) {
// implement reducer/aggregation/accumulator logic here.
// the return value serves as the
// new `accumulator` value within
// the next iteration step.
// thus, always return something! ... e.g ...
return (accumulator + currentValue);
});
function aggregatePrecursorAndDecrementedSuccessorCount(count, char, idx, arr) {
const precursorValue = Number(arr[idx - 1]);
const incrementedCurrentValue = (Number(char) + 1);
const isValidCount = (precursorValue === incrementedCurrentValue);
return (count + (isValidCount ? 1 : 0));
//return (count + Number(isValidCount)); // cast boolean value to either 1 or 0.
}
function getPrecursorAndDecrementedSuccessorCount(int) {
return String(int) // - assure/typecast always a/into string value.
.split('') // - split string value into an array of single characters.
.reduce(aggregatePrecursorAndDecrementedSuccessorCount, 0);
}
console.log(getPrecursorAndDecrementedSuccessorCount(9876541110));
.as-console-wrapper { min-height: 100%!important; top: 0; }
what's the difference between i and num[i]
i is the iteration key, i.e. 0, 1, 2 etc, for as many characters are in the stringified number. num[i] is the character at the index i in the string, i.e. num[i] where i is 0 == 9 (the character in the string at index 0).
I don't understand how the calculation is happening inside the if statement, could someone break it down?
That says: If the calculation of the number at index i-1 of the string, minus the current number being considered (at index i in the string) minus is 1, then increment count.
Step by step for the actual number used:
9 - has no previous character; calculation (undefined - 9) does not equate to 1
8 - previous char is 9; (9 - 8) == 1; increment count
7 - ditto
6 - ditto
5 - ditto
4 - ditto
1 - previous char is 4; calculation (4 - 1) does not equate to 1
1 - previous char is 1; calculation (1 - 1) does not equate to 1
1 - ditto
0 - previous char is 1; (1 - 0) == 1; increment count

I'm trying to replace every third element in an array

I'm trying to replace every third element in an array, but my code doesn't work.
//Calling of the first array
//first array
var numbers = new Array();
var go = true;
while (go) {
var n = parseFloat(prompt("Number please", ""));
numbers.push(n);
go = confirm("One more number?");
}
document.write("<p>" + numbers.toString() + "</p>");
// Array to change elements
// second array
for (var i = 0; i < numbers.length; i++)
if (numbers[i] % 3 == 0) {
(numbers *= 2);
}
else {
(numbers *= 1);
}
document.write("<p>" + numbers.toString() + "</p>");
//document.write("<p>");
Change numbers[i] % 3 to just i % 3. You're currently testing if the number in the array is a multiple of three instead of if its position in the array is a multiple of 3.
You also need to change your statements like numbers *= 2. numbers is an array, so multiplying it doesn't work well. If you want to update the individual array entry that should be numbers[i] *= 2;
You have missed the index in (numbers[i] *= 2) and in (numbers[i] *= 1);
And to check the third element you need to check the index (i+1)%3 == 0 because your array starts from index 0;
There are 2 mistakes apparent in your code:
numbers[i] % 3 == 0: this implies execute if block for any number a multiple of 3, not at every number on 3rd index
Solution: (i + 1) % 3 == 0
numbers *= 2 : you are trying to multiply an array not array element. You will get NaN.
Solution : numbers[i] *= 2;
Here's however another way of doing it using map:
numbers = numbers.map(function (i, idx) {
return (idx + 1) % 3 == 0 ? 2*i : i
})
Here's a doc to map function:
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/map?v=example
You want to check for index, I suppose not number value.
in for loop instead of
number[i] % 3
use
i % 3
You were using numbers[i] i.e the actual number instead of the index. So replace if(number[i]%3==0) to if(i%3==0).
Secondly, you are updating the whole array instead of an element of array in the if else condition. So use numbers[i] *=2 instead of number *= 2.
Use the below code snippet to change the array:
for (var i = 1; i <= numbers.length; i++)
if (i % 3 == 0) {
numbers[i] *= 2;
}
else {
numbers[i] *= 1;
}
}
Your logic here is wrong. Instead of taking the modulus of the value you should take the modulus of the index. Instead if if (numbers[i] % 3 == 0) this what you should have done is if (i % 3 == 0). Hope this helps.
You could change the whole program a bit, without using another variable for go.
As in comments mentioned, you could iteratig with a step length of 3 and omit the check with the remainder operator %.
Aor an assignment to an element of an array, you need the reference to the array with the variable name and the index on the left hand side and an assignment operator and the expression for getting the wanted result.
numbers[i] *= 2;
var n,
i,
numbers = [];
do {
n = parseFloat(prompt("Number please"));
numbers.push(n);
} while (confirm("One more number?"))
console.log(numbers);
for (i = 0; i < numbers.length; i += 3) {
numbers[i] *= 2;
}
console.log(numbers);
You can use the mathematical Modulus operator. Every third mean % 3.
https://www.w3schools.com/js/js_arithmetic.asp
If you use it in a condition, your index % 3 will return 0 when true.
if (index % 3 == 0)

Algorithm that involves rounding and multiples

So I have a problem where I have an array of some length (usually long). I have an initial start index into that array and a skip value. So, if I have this:
var initial = 5;
var skip = 10;
Then I'd iterate over my array with indexes 5, 15, 25, 35, etc.
But then I may get a new start value and I need to find the closest value to the initial plus or minus a multiple of the skip and then start my skip. So if my new value is 23 then I'd iterate 25, 35, 45, etc.
The algorithm I have for this is:
index = (round((start - initial) / skip) * skip) + initial
And then I need a check to see if index has dropped below zero:
while(index < 0) index += skip;
So my first question is if there's a name for this? A multiple with random start?
My second question is if there's a better way? I don't think what I have is terribly complicated but if I'm missing something I'd like to know about it.
If it matters I'm using javascript.
Thanks!
Edit
Instead of
while(index < 0) index += skip;
if we assume that both initial and skip are positive you can use:
if (index < 0) index = initial % skip;
To get the closest multiple of a number to a test number: See if the modulo of your test number is greater than number/2 and if so, return number - modulo:
function closestMultiple(multipleTest,number)
{
var modulo = multipleTest%number;
if(0 == modulo )
{
return multipleTest;
}
else
{
var halfNumber = number/2;
if(modulo >= halfNumber)
{
return multipleTest + (number-modulo);
}
else
{
return multipleTest - modulo;
}
}
}
To check if a number is a multiple of another then compare their modulo to 0:
function isMultiple(multipleTest,number)
{
return 0 == multipleTest%number;
}
You might want to add some validations for 0 in case you expect any inside closestMultiple.
The value of index computed as you put it
index = round((start - initial)/skip) * skip + initial
is indeed the one that minimizes the distance between the sequence with general term
aj = j * skip + initial
and start.
Therefore, index can only be negative if start lies to the left of
(a-1 + a0)/2 = initial - skip/2
in other words, if
start < initial - skip/2.
So, only in that case you have to redefine index to 0. In pseudo code:
IF (start < (initial - skip/2))
index = 0
ELSE
index = round((start - initial)/skip) * skip + initial
Alternatively, you could do
index = round((start - initial)/skip) * skip + initial
IF index < 0 THEN index = 0
which is the same.
No while loop required:
function newNum(newstart, initial, skip) {
var xLow = newstart + Math.abs(newstart - initial) % skip;
var xHi = newstart + skip;
var result = (xLow + xHi) / 2 > newstart ? xLow : xHi;
if (result < 0) result += skip;
return result;
}
Take the distance between your new starting point and your initial value, and find out what the remainder would be if you marched towards that initial value (Modulus gives us that). Then you just need to find out if the closest spot is before or after the starting point (I did this be comparing the midpoint of the low and high values to the starting point).
Test:
newNum(1, 20, 7) = 6
newNum(-1, 20, 7) = 6
newNum(180, 10, 3) = 182
(Even though you stated in your comments that the range of the new starting point is within the array bounds, notice that it doesn't really matter).

JavaScript - Multiplying Even Indexed Array Elements by 2 and Odd Indexed by 3

I've been trying to write code that multiplies even indexed elements of an array by 2 and odd indexed elements by 3.
I have the following numbers stored in the variable number, which represents an array of numbers
numbers = [1,7,9,21,32,77];
Even Indexed Numbers - 1,9,32
Odd Indexed Numbers - 7, 21, 77
Please keep in mind that arrays are Zero Indexed, which means the numbering starts at 0. In which case, the 0-Indexed element is actually 1, and the 1-Indexed element is 7.
This is what I expected the output to be
[2,21,18,63,64,231]
Unfortunately, I got this output
[2,14,17,42,64,154]
Here is the code for my method
numbers = numbers.map(function(x) {
n = 0;
while (n < numbers.length) {
if (n % 2 == 0) {
return x * 2;
}
else {
return x * 3;
}
n++;
}});
return numbers;
Here I created a while loop, that executes code for every iteration of the variable n. For every value of the variable n, I'm checking if n is even, which is used by the code n % 2 == 0. While it's true that 0 % 2 == 0 it's not true that 1 % 2 == 0. I'm incrementing n at the end of the while loop, so I don't understand why I received the output I did.
Any help will be appreciated.
You created a global property called n, by doing
n = 0;
and then,
while (n < numbers.length) {
if (n % 2 == 0) {
return x * 2;
} else {
return x * 3;
}
}
n++; // Unreachable
you always return immediately. So the, n++ is never incremented. So, n remains 0 always and so all the elements are multiplied by 2 always.
The Array.prototype.map's callback function's, second parameter is the index itself. So, the correct way to use map is, like this
numbers.map(function(currentNumber, index) {
if (index % 2 === 0) {
return currentNumber * 2;
} else {
return currentNumber * 3;
}
});
The same can be written succinctly, with the ternary operator, like this
numbers.map(function(currentNumber, index) {
return currentNumber * (index % 2 === 0 ? 2 : 3);
});
To complement the other answer, the source of OP's confusion is on how "map" works. The map function is already called for each element - yet, OP attempted to use a while loop inside it, which is another way to iterate through each element. That is a double interaction, so, in essence, if OP's code worked, it would still be modifying each number n times! Usually, you just chose between a loop or map:
Using a loop:
var numbers = [1,7,9,21,32,77];
for (var i=0; i<numbers.length; ++i)
numbers[i] = i % 2 === 0 ? numbers[i] * 2 : numbers[i] * 3;
Using map:
var numbers = [1,7,9,21,32,77];
numbers.map(function(number, index){
return number * (index % 2 === 0 ? 2 : 3);
});
Or, very briefly:
[1,7,9,21,32,77].map(function(n,i){ return n * [2,3][i%2]; });
Basically you want to return a modified array that if the elements of the initial one is:
in even position, then multiply the element by 2.
in odd position, then multiply the element by 3.
You can use map with arrow functions and the conditional (ternary) operator to get this one-liner
console.log([1,7,9,21,32,77].map((num,ind) => num * (ind % 2 === 0 ? 2 : 3)));
This will output the desired
[2, 21, 18, 63, 64, 231]

Categories