Related
I am trying to solve a problem that takes an array and moves all of the zeros to the end, preserving the order of the other elements.
This isn't iterating through the entire array, any ideas on what I'm doing wrong would be greatly appreciated.
let moveZeros = function (arr) {
let newArr = [];
for (let i = 0; i < arr.length; i++) {
if (arr[i] === 0) {
newArr.push(arr[i]);
arr.splice(i, 1);
}
}
return arr.concat(newArr);
};
moveZeros([9, 0, 9, 1, 2, 1, 1, 3, 1, 9, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0]);
// expexted to return [9,9,1,2,1,1,3,1,9,9,0,0,0,0,0,0,0,0,0,0]
// currently returns [9,9,1,2,1,1,3,1,9,0,9,0,0,0,0,0,0,0,0,0]
// Strangely... sending a smaller array to the function seems to work.
//moveZeros([false,1,0,1,2,0,1,3,"a"])
// correctly returns[false,1,1,2,1,3,"a",0,0]
The problem isn't related to the length, it occurs when you have more than one consecutive 0. For example [0,0,9,0,0,9] will come out [0,9,0,9,0,0].
In the first iteration of the loop (i=0), you remove the first 0 from the array, leaving you with [0,9,0,0,9]. On the second iteration (i=1), it's now looking at the second element in the array, which is 9. The first 0 is skipped. This will happen later in the array too as the loop progresses.
In general it can be problematic to modify an array as you loop through it. There are a number of ways you could perform a sort like this. But to keep it close to your original you could do this:
let moveZeros = function(arr) {
let arrA = [];
let arrB = [];
for (let i = 0; i < arr.length; i++) {
if (arr[i] === 0) {
arrB.push(arr[i]);
} else {
arrA.push(arr[i]);
}
}
return arrA.concat(arrB);
};
Now the function keeps the original array intact as it goes through it. Non-0 items are pushed to arrA, and 0s are pushed to arrB, and then those two are concatenated.
You could keep the array and move all not zero values to the start and fill the rest with zeroes.
let moveZeros = function(array) {
let i = 0,
j = 0;
while (i < array.length) {
if (array[i] !== 0) array[j++] = array[i];
i++;
}
while (j < array.length) array[j++] = 0;
return array;
};
console.log(...moveZeros([9, 0, 9, 1, 2, 1, 1, 3, 1, 9, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0]));
console.log(...moveZeros([false, 1, 0, 1, 2, 0, 1, 3, "a"]));
I'm trying this quiz on Codewars: Smallest unused ID
You've got much data to manage and of course you use zero-based and non-negative ID's to make each data item unique!
Therefore you need a method, which returns the smallest unused ID for your next new data item...
Note: The given array of used IDs may be unsorted. For test reasons there may be duplicate IDs, but you don't have to find or remove them!
In short, You are given an array. What the quiz requires is to find the smallest unused number.
For example:
[0,1,2,3,5] // Output: 4
[1,2,3,5] // Output: 0
[0,1,2,3,4,5] // Output: 6
[0,0,0,0,0,0] // Output: 1
[0,1,0,2,0,3] // Output: 4
My code can't pass some tests. Inputs for the tests are hidden, so I am unable to figure out the causes. What is causing the issue?
const nextId = ids => {
let lowestId;
if (Math.max(...ids) + 1 === ids.length) {
lowestId = Math.max(...ids) + 1;
} else {
let sortedIds = ids.sort((a, b) => a - b);
for (let i = 0; i < sortedIds.length; i++) {
if (i !== sortedIds[i]) {
lowestId = i;
break;
}
}
}
return lowestId
}
console.log(nextId([0, 1, 2, 3, 5])) // 4
console.log(nextId([1, 2, 3, 5])) // 0
console.log(nextId([0, 1, 2, 3, 4, 5])) // 6
console.log(nextId([0, 0, 0, 0, 0, 0])) // 1
console.log(nextId([0, 1, 0, 2, 0, 3])) // 4
You're over complicating it
function doStuff(stuff)
{
for(let i = 0; i < stuff.length + 1; i++)
{
if(stuff.indexOf(i) == -1)
return i;
}
}
It looks like you missed this line of the instructions:
"Note: The given array of used IDs may be unsorted. For test reasons there may be duplicate IDs, but you don't have to find or remove them!"
With the logic of your code, if there's a duplicate then the value won't match the index. You need to actually compare the values to account for duplicates.
function nextId(ids) {
let lowestId = 0;
let sortedIds = ids.sort((a, b) => a - b);
for (let i = 0; i < sortedIds.length; i++) {
if (lowestId === sortedIds[i] && lowestId !== sortedIds[i + 1]) {
lowestId++;
}
else if (lowestId !== sortedIds[i + 1]) {
return lowestId;
}
}
return lowestId
}
This approach takes an object for seen values.
The start node is -1, because the first missing id could be zero.
Performance:
To collect all nodes: O(n).
To find the missing smallest id: smaller than O(n).
function nextId(ids){
const seen = {};
let id = -1;
for (const id of ids) seen[id] = true;
while (seen[++id]) ;
return id;
}
console.log(nextId([0, 1, 2, 3, 5])); // 4
console.log(nextId([1, 2, 3, 5])); // 0
console.log(nextId([0, 1, 2, 3, 4, 5])); // 6
console.log(nextId([0, 0, 0, 0, 0, 0])); // 1
console.log(nextId([0, 1, 0, 2, 0, 3])); // 4
I want to write a function with for-loops that finds the index of the number 1 in an array and returns the difference to the index of the number 2 that is closest to number 1 (number 1 only appears once). For instance:
Input: [1, 0, 0, 0, 2, 2, 2]
Output: 4
Input: [2, 0, 0, 0, 2, 2, 1, 0, 0 ,2]
Output: 1
My try
function closest (array) {
let elem=array.findIndex(index=>index === 1)
let numberplus=0;
let numberminus=0;
for (let i=elem; i<array.length; i++){
if (array[elem+1] === 2)
{numberplus+=array[elem+1]-elem;}
break;
}
for (let i=elem; i>=0; i--) {
if (array[elem-1] ===2)
{numberminus+=array[elem-1]-elem;}
break;
}
if (numberplus < numberminus) {
return numberplus
} else {
return numberminus}
}
When invoked, the function just returns '0'. Thanks for reading!
Take the position of 1 as starting point and loop up and (if necessary) down the array:
const log = (arr, d) => console.log(`mimimal distance [${arr.join()}]: ${d}`);
const arr = [2, 0, 0, 0, 2, 2, 1, 0, 0, 2];
const arr2 = [1, 0, 0, 0, 2, 2, 2];
const arr3 = [2, 0, 1, 0, 2, 2, 2];
const arr4 = [2, 1, 0, 0, 2, 2, 2];
log(arr, clostes(arr));
log(arr2, clostes(arr2));
log(arr3, clostes(arr3));
log(arr4, clostes(arr4));
function clostes(arr) {
// determine position of 1
const indxOf1 = arr.indexOf(1);
// create array of distances
const distances = [0, 0];
// forward search
for (let i = indxOf1; i < arr.length; i += 1) {
if (arr[i] === 2) {
break;
}
distances[0] += arr[i] !== 2 ? 1 : 0;
}
// if 1 is # position 0 backwards search
// is not necessary and minimum equals the
// already found maximum
if (indxOf1 < 1) {
distances[1] = distances[0];
return Math.min.apply(null, distances);
}
// backwards search
for (let i = indxOf1; i >= 0; i -= 1) {
if (arr[i] === 2) {
break;
}
distances[1] += arr[i] !== 2 ? 1 : 0;
}
return Math.min.apply(null, distances);
}
Something like this will do the job. You could make the code shorter but I've tried to make it clear. Once we find 1, start at that index and keep checking adjacent indices. We also do bounds checking to ensure we don't overflow either end.
function closest(arr) {
const index = arr.findIndex(n => n === 1);
const len = arr.length;
let offset = 1;
while (true) {
const before = index - offset;
const after = index + offset;
const beforeBad = before < 0;
const afterBad = after >= len;
// It's necessary to check both, we could exceed the bounds on one side but not the other.
if (beforeBad && afterBad) {
break;
}
if ((!beforeBad && arr[before] === 2) || (!afterBad && arr[after] === 2)) {
return offset;
}
++offset;
}
return -1;
}
You could approach this using entries and reduce.
const arr = [2, 0, 0, 0, 2, 2, 1, 0, 0 ,2];
const goal = arr.indexOf(1);
const indices = [];
// Find all the indices of 2 in the array
for (let x of arr.entries()) {
if (x[1] === 2) indices.push(x[0]) ;
}
// Find the index that is closest to your goal
const nearestIndex = indices.reduce((prev, curr) => {
return (Math.abs(curr - goal) < Math.abs(prev - goal) ? curr : prev);
}); // 5
console.log(Math.abs(goal - nearestIndex)); // 1
How about this:
Output = Input.map((cur,idx,arr)=>cur==2?Math.abs(idx-arr.indexOf(1)):Infinity).sort()[0]
You could avoid for loops here in favor of a more functional style. The function minDist takes m, n, and array as arguments, and returns the minimum distance between the first occurrence of m and any occurrence of n in an array.
First, map is used to create an array with pairs for each element containing the distance to the target m element and the value of the current element. Then filter is used to keep only the pairs representing n elements. Then sort is used so that the pairs representing the closest elements are at the beginning of the array. Finally, the [0] pair of the sorted array represents the closest element, and the [0] element of this closest pair is the minimum distance.
function minDist(m, n, array) {
let index = array.indexOf(m);
return array
.map((x, i) => [Math.abs(i - index), x])
.filter(p => p[1] === n)
.sort()[0][0];
}
console.log(minDist(1, 2, [1, 0, 0, 0, 2, 2, 2]));
console.log(minDist(1, 2, [2, 0, 0, 0, 2, 2, 1, 0, 0, 2]));
Hello and here is my problem.I have a task,i need to remove elements from an array and push them into another array and then return the array with removed elements. For example, in this case i have to remove all 0 values, and push them into 'a' array and then return 'a' array with there 0 values. I removed 0 values from the array by using splice method and loop, but i don't realy know how to push removed elemts into 'a' array, i've tried to use push method but i does not work for me. Hope you'll help me.Thank you everyone.
function moveZeros(array) {
var a = [];
for (var i = array.length - 1; i--;) {
if (array[i] == "0") {
array.splice(i, 1);
}
}
return a;
}
moveZeros([1, 2, 0, 1, 0, 1, 0, 3, 0, 1]);
Array.splice() returns an array of removed elements, and you can use Array.concat() to add them to the a array.
Notes:
Init i to array.length without the -1, since the condition i--
is checked before the execution of the loop's body.
Since the the array is iterated from end to starts, concat a to the removed
elements to maintain the original order.
function moveZeros(array) {
var a = [];
for (var i = array.length; i--;) {
if (array[i] === 0) {
a = array.splice(i, 1).concat(a);
}
}
return a;
}
var result = moveZeros([1, 2, 0, 1, 0, 1, 0, 3, 0, 1, 0]); // I've added a last 0 to the array to show that all items were removed
console.log(result);
Using push should work. The .splice method will return an array with the removed elements, and you can use the spread operator ... to pass it as a set of arguments to push:
function moveZeros(array) {
var a = [];
for (var i = array.length - 1; i >= 0; i--) {
if (array[i] == "0") {
a.push(...array.splice(i, 1));
}
}
return a;
}
const array = [0, 1, 2, 0, 1, 0, 1, 0, 3, 0, 1, 0, 0];
console.log(moveZeros(array));
console.log(array)
Finally, you should put the i-- as the final part of the loop so that it only executes when each iteration finishes (instead of as they begin). Then, change your condition to be i >= 0 so that you don't miss a zero at the front of the array.
You could iterate from the end and splice the array if necessary. This solution mutates the array.
function moveZeros(array) {
var i = array.length,
a = [];
while (i--) {
if (array[i] === 0) {
a.push(array.splice(i, 1)[0]);
}
}
return a;
}
var array = [1, 2, 0, 1, 0, 1, 0, 3, 0, 1];
console.log(moveZeros(array));
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Without using .indexOf, I'm trying to loop through an array from the end to find the last occurrence of a specific value. This is what I have so far but it keeps returning undefined.
var lastIndexOf = function (array, index) {
for (i=array.length-1; i < 0; i--) {
if (array[i] === index) {
return i;
}
}
}
console.log(lastIndexOf([ 0, 1, 4, 1, 2 ], 1); //should return 3
console.log(lastIndexOf([ 0, 1, 4, 1, 2 ], 2); //should return 4
Yor check is wrong, i is never smaller than zero for an index.
By the way, if you check against a value, you could use the name value instead of index, which leads to wrong assumptions and declare all variables in advance.
var lastIndexOf = function(array, value) {
var i;
for (i = array.length - 1; i >= 0; i--) {
if (array[i] === value) {
return i;
}
}
return -1; // standard default value for not found indices
};
console.log(lastIndexOf([0, 1, 4, 1, 2], 1)); // 3
console.log(lastIndexOf([0, 1, 4, 1, 2], 2)); // 4
console.log(lastIndexOf([0, 1, 4, 1, 2], 42)); // -1
A shorter approach with a while loop.
var lastIndexOf = function(array, value) {
var i = array.length
while (i--) {
if (array[i] === value) {
return i;
}
}
return -1;
};
console.log(lastIndexOf([0, 1, 4, 1, 2], 1)); // 3
console.log(lastIndexOf([0, 1, 4, 1, 2], 2)); // 4
console.log(lastIndexOf([0, 1, 4, 1, 2], 42)); // -1
Your loop condition is wrong. i will never be less than 0 unless the array is empty.
Use this instead:
(i=array.length-1; i >= 0; i--) {
You should change the check you make in the for statement. We start from the last index and we go down to the 0 index. So you loop while index >=0 and not when index<0.
I used different names for some parameters and arguments, in order to make the code more readable.
var lastIndexOf = function (array, number) {
for (var index = array.length-1; index>=0; index--) {
if (array[index] === number) {
return index;
}
}
};
console.log(lastIndexOf([ 0, 1, 4, 1, 2 ], 1)); //should return 3