Loop not looping inside array & comparing elements of an array - javascript

In this function I am trying loop into an array, and then return the following thing: if the year is formed by all different digits, then it's a happy year and should be stored where it belongs, in the happy array. If not, it should go in the notHappy array.
Now the problems:
1) The IF condition I tried returns nothing, []. I am quite sure it's not the right way of doing it.
for (var i = 0; i <= t.length; i++) {
if (i[0] != i[1] && i[0] != i[2] && i[0] != i[3]) {
o.happy.push(i++);
} else {
o.notHappy.push(i++)
}
}
2) I tried the same loop with a simple i%2 === 0 condition and I found out that the loop ignores my arr altogether and returns [0, 2, 4] instead of the actual numbers. It's like it would start looping from 0 itself. How come?
function nextHappyYear(arr){
var o = {
happy: [],
notHappy: []
};
var t = arr.map(e => e.toString().split(""));
for (var i = 0; i <= t.length; i++) {
if (i%2 === 0) {
o.happy.push(i++);
} else { o.notHappy.push(i++)}
}
return console.log(o.happy)
}
nextHappyYear([1021, 1022, 1023, 1024]) // returns [0, 2, 4] instead of [1022, 1024]

Your code has some issues
1-for (var i = 0; i <= t.length; i++)
Arrays indexes start from 0 and ends with length - 1. So your condition i <= t.length makes an error. Change it to i < t.length.
2-if (i%2 === 0)
This is not your question condition. You must get all digits in a year and check equality of them.
3-o.happy.push(i++);
This part have 2 problem. First, you push into happy array the index of that year, not the year. Second, i++ increase i by one and one year will get skipped!
4-if (i[0] != i[1] && i[0] != i[2] && i[0] != i[3])
You check just the first digit with others and you don't check second with third and fourth, third digit with forth also.
Try this
function hasDuplicate(arr) {
arr.sort()
for (var i = 0; i < arr.length - 1; i++) {
if (arr[i + 1] == arr[i]) {
return true;
}
}
return false;
}
function happyYear1(arr) {
var o = {
happy: [],
notHappy: []
};
for (var i = 0; i < arr.length; i++) {
if (!hasDuplicate((arr[i] + '').split(""))) {
o.happy.push(arr[i]);
} else {
o.notHappy.push(arr[i]);
}
}
return o;
}
var output = happyYear1([1021, 1022, 1023, 1024]); // returns [0, 2, 4] instead of [1022, 1024]
console.log(output);

Related

Checking for duplicates within an array

I am trying to check for matching instances of arrays within a larger array. To do this, I am implementing a condition where if two of three numbers in an array match two of the three members of any of the arrays within a larger array, there is a continue statement to go back to a previous loop:
var threeSum = function (nums) {
let result = [];
for (let i = 0; i < nums.length - 2; i++) {
for (let j = i + 1; j < nums.length - 1; j++) {
loop1: for (let k = j + 1; k < nums.length; k++) {
if (nums[i] + nums[j] + nums[k] === 0) {
let smallArray = [nums[i], nums[j], nums[k]].sort((a, b) => a - b);
for (let l = 0; l < smallArray.length && result[l]; l++) {
if (
smallArray[0] == result[l][0] &&
smallArray[1] == result[l][2]
) {
console.log("we already have this array")
continue loop1;
}
}
result.push(smallArray);
}
}
}
}
return result;
};
Thus, for example threeSum([-1, 0, 1, 2, -1, -4]) should return [[-1, 0, 1], [-1, -1, 2]] when is instead is returning [[-1, 0, 1], [-1, -1, 2], [-1, 0, 1]]. I have checked using the console.log in the inner most conditional, and the if statement is never returning as true, so it is never entering the continue command. But the first and third arrays should meet the requirements of this, so it seems as if when checking the third array, the function should kick back the command.
I am a bit puzzled as to what is going wrong.
A single loop approach but with recursion and filtering for arrays with same values.
function threeSum(array, temp = [], sum = 0, i = 0) {
if (temp.length === 3) return sum ? [] : [temp];
const result = [];
while (i < array.length) {
result.push(...threeSum(array, [...temp, array[i]], sum + array[i], ++i));
}
return result.filter((s => a => (b => !s.has(b) && s.add(b))([...a].sort().join('|')))(new Set));
}
console.log(threeSum([-1, 0, 1, 2, -1, -4]));

Remove Duplicates from Sorted Array JS

I'm trying to understand why my solution to this problem is only partially working.
Problem:
Given a sorted array nums, remove the duplicates in-place such that each element appears only once and returns the new length.
Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.
My Solution:
var removeDuplicates = function(nums) {
if (nums.length === 0) return 0;
for (let i = 1; i <= nums.length; i++){
if(nums[i] === nums[i-1]){
nums.splice(nums[i], 1);
}
}
return nums.length;
};
This is the outcome I'm getting on leetcode but I don't understand why my solution stops working and the '3s' are not removed?
Output screenshot:
When you splice an array while iterating over it, the whole array will change in-place. For example, let's say that indexes 0 and 1 are duplicates (i is 1). Then, if you remove index 1 from the array, what used to be at index 2 will now be at index 1, and what used to be at index 3 will now be at index 2, etc.
So, you need to subtract 1 from i when an element is removed, otherwise the next element will be skipped.
You also have an off-by-one-error - iterate i from 1 to i < nums.length so you don't go past the end of the array.
You also need to pass the index to remove to splice, not the value to remove.
var removeDuplicates = function(nums) {
for (let i = 1; i < nums.length; i++){
if(nums[i] === nums[i-1]){
nums.splice(i, 1);
i--;
}
}
return nums.length;
};
console.log(removeDuplicates([0, 0, 0]));
Simple version. Using functions already created
let array = new Set(nums);
let values = array.values();
return Array.from(values);
This'd also pass just fine on constant memory:
const removeDuplicates = function (nums) {
let count = 0;
nums.forEach(function (num) {
if (num !== nums[count]) {
nums[++count] = num;
}
});
return nums.length && count + 1;
};
function removeDuplicates(nums) {
let i = 0;
while(i < nums.length - 1) {
i += 1 - ((nums[i] === nums[i+1]) && nums.splice(i, 1).length)
}
return nums.length;
}
C# simple solution:
public int RemoveDuplicates(int[] nums) {
if (nums.Length == 0)
return 0;
var i = 0;
var start = 0;
var end = 0;
while (end < nums.Length)
{
if (nums[start] != nums[end])
{
nums[++i] = nums[end];
start = end;
}
end++;
}
return i + 1;
}

Javascript, Merging two sorted arrays: Can someone please tell me why this isn't giving the correct mergeSort?

I've tried merging the two arrays but the output i get is [ 0, 3, 3, 4, 4 ]
function mergeSortedArrays(arr1, arr2) {
var i = 0;
var j = 0;
var arr3 = [];
if (arr1 === undefined || arr1.length == 0) {
return arr2;
}
if (arr2 === undefined || arr2.length == 0) {
return arr1;
}
while (i < arr1.length - 1 && j < arr2.length - 1) {
if (arr1[i] < arr2[j]) {
arr3.push(arr1[i]);
i++;
} else {
arr3.push(arr2[j]);
j++;
}
}
return arr3;
}
console.log(mergeSortedArrays([0, 3, 4, 31], [3, 4, 6, 30]));
For this example, i know i haven't accounted for the case in which arrays are of different size but that is for a later problem. The code currently isn't even working for the basic case. It does not iterate all the way through and breaks midway. Can someone please address this problem. I've worked around with the while loop but the code still doesnt work.
You are making two mistakes.
In the while loop condition check of length of array not length - 1. This will not add last elements of both array.
Your while loop will end when one of the array will be completely loop because of &&. So after while add the remaining elements of other array.
function mergeSortedArrays(arr1, arr2) {
var i = 0;
var j = 0;
var arr3 = [];
if (arr1 === undefined || arr1.length == 0) {
return arr2;
}
if (arr2 === undefined || arr2.length == 0) {
return arr1;
}
while (i < arr1.length && j < arr2.length) {
if (arr1[i] < arr2[j]) {
arr3.push(arr1[i]);
i++;
} else {
arr3.push(arr2[j]);
j++;
}
}
if(i === arr1.length){
return arr3.concat(arr2.slice(j))
}
else if(j === arr2.length){
return arr3.concat(arr1.slice(i))
}
}
console.log(mergeSortedArrays([0, 3, 4, 31], [3, 4, 6, 30]));
First of all, the loop needs to iterate till arr1.lenght and arr2.lenght not till lenght - 1,
while (i < arr1.length && j < arr2.length )
Also, after the loop breaks, the reason being either one of the array loop variables has a false condition, before returning the array, you need to check if there are values left which are not yet inserted. This is important.
You can do this:
arr3.concat(arr1.slice(i)).concat(arr2.slice(j));
Hope it helps.
There are two things missing in your code:
The while loop is running for i < arr1.length - 1 for arr1 and j < arr2.length - 1 for arr2. That means it will run till 3rd index of arr1 and arr2. So the last index will not be executed in the loop. So you should refactor the loop as i < arr1.length for arr1 and j < arr2.length for arr2.
Next missing thing, you need to add the loop for remaining elements of remaining array. That means when you execute the code then all the elements of one loop will be pushed in the arr3 then one elements of another array will be missed and it will not be pushed in the arr3 (for same length of both array) and/or more than one elements of another array will be missed (for different length of both array). So you need to push the remaining elements of another array to the arr3.
I have added the refactored code of your code.
function mergeSortedArrays(arr1, arr2) {
var i = 0;
var j = 0;
var arr3 = [];
if (arr1 === undefined || arr1.length == 0) {
return arr2;
}
if (arr2 === undefined || arr2.length == 0) {
return arr1;
}
while (i < arr1.length && j < arr2.length) {
if (arr1[i] < arr2[j]) {
arr3.push(arr1[i]);
i++;
} else {
arr3.push(arr2[j]);
j++;
}
}
while (i < arr1.length) {
arr3.push(arr1[i]);
i++;
}
while (j < arr2.length) {
arr3.push(arr2[j]);
j++;
}
return arr3;
}
OR
you can use spread operator to merge both array and then you can use sort method of JS.
function mergeTwo(arr1, arr2) {
let result = [...arr1, ...arr2];
return result.sort((a,b) => a-b);
}
There is a simple one line solutions that does involve a resort. Using default parameters to deal with undefined arrays, and the spread operator to populate a new array with the two merging arrays. The result array just needs to be sorted and then returned.
const mergeSorted = (a1 = [], a2 = []) => [...a1, ...a2].sort((a, b) => a - b);
Example
const mergeSorted= (a1 = [], a2 = []) => [...a1, ...a2].sort((a, b) => a - b);
console.log(mergeSorted([0, 3, 4, 31], [3, 4, 6, 30]).join(", "));
Or without the sort and using parameter defaults to avoid needing to test arrays for undefined
function mergeSorted(a1 = [], a2 = []) {
const res = [];
var idx1 = 0, idx2 = 0;
while (idx1 < a1.length || idx2 < a2.length) {
if (idx1 < a1.length && idx2 < a2.length) {
res.push(a1[idx1] < a2[idx2] ? a1[idx1++] : a2[idx2++]);
} else {
res.push(idx1 < a1.length ? a1[idx1++] : a2[idx2++]);
}
}
return res;
}
Example
function mergeSorted(a1 = [], a2 = []) {
const res = [], l1 = a1.length, l2 = a2.length;
var i1 = 0, i2 = 0;
while (i1 < l1 || i2 < l2) {
if (i1 < l1 && i2 < l2) { res.push(a1[i1] < a2[i2] ? a1[i1++] : a2[i2++]) }
else { res.push(i1 < l1 ? a1[i1++] : a2[i2++]) }
}
return res;
}
console.log(mergeSorted([0, 3, 4, 31, 99], [3, 4, 6, 30]).join(", "));
In the while condition when i or j indexes reach the length of the corresponding array finishes the loop returning an array of the lower length.
This works:
function mergeTwoSortedArrays(arr1, arr2) {
let merged = [];
let index1 = 0;
let index2 = 0;
let current = 0;
while (current < (arr1.length + arr2.length)) {
let isArr1Depleted = index1 >= arr1.length;
let isArr2Depleted = index2 >= arr2.length;
if (!isArr1Depleted && (isArr2Depleted || (arr1[index1] < arr2[index2]))) {
merged[current] = arr1[index1];
index1++;
} else {
merged[current] = arr2[index2];
index2++;
}
current++;
}
return merged;
}
Fore more info : https://wsvincent.com/javascript-merge-two-sorted-arrays/

Print two elements from array with for loop

I'm new in JavaScript and i am trying to print only two elements from array with FOR LOOP and brake & continue statements
for example i want to be printed 3 and 8
I tried this:
var array= [1,2,3,4,5,6,7,8];
for (var i = 0; i < array.length; i++) {
if (i == 3) {
alert(i);
continue;
}
if ( i == 8) {
alert(i);
}
}
All arrays start at the first position of 0 and go up from there. So in your code you are thinking you are comparing 3 == 3 in but really you are comparing 2 == 3. If you compare the array position value instead of the loop value your problem is fixed.
var array = [1, 2, 3, 4, 5, 6, 7, 8];
for (var i = 0; i < array.length; i++) {
if (array[i] == 3) {
alert(array[i]);
}
else if (array[i] == 8) {
alert(array[i]);
}
}
Try this one if you need to check for values in array and not index. Imo, values in array need not be similar as index values,they can be anything.
var array= [1,2,3,4,5,6,7,8];
for(var i = 0; i < array.length; i++)
{
if (array[i]== 3 || array[i] == 8)
{
alert(array[i]);
}
}
What about using a filter?
const array = [1,2,3,4,5,6,7,8];
const matches = array.filter(a => a === 3 || a === 8);
console.log(matches[0], matches[1]);
// The filter uses the lambda function. It's the same thing as the following:
const matches = array.filter(function(a) {
return a === 3 || a === 8;
});

Having trouble getting rid of duplicates in JavaScript.

var numberArray = [1,2,3,4, 5,6,7,8,9, 9, 4];
var newArray = [];
function primeChecker(arrayCheck){
for (var i = 0; i < arrayCheck.length; i++){
if (Math.sqrt(arrayCheck[i]) % 1 === 0) {
newArray.push(arrayCheck[i]);
}
}
for (var x = 0; x < newArray.length; x++){
newArray.sort();
if (newArray[x] === newArray[x -1]){
newArray.splice(newArray[x-1]);
}
}
}
primeChecker(numberArray);
console.log(newArray);
The returned array is [ 1, 4, 4, 9 ]. The function successfully gets rid of the repeating 9s but I am still left with two 4s. Any thoughts as to why this might be? I am a JavaScript beginner and not totally familiar with the language.
Loop backwards. When you remove the item from the array the array gets shorter.
https://jsfiddle.net/2w0k5tz8/
function remove_duplicates(array_){
var ret_array = new Array();
for (var a = array_.length - 1; a >= 0; a--) {
for (var b = array_.length - 1; b >= 0; b--) {
if(array_[a] == array_[b] && a != b){
delete array_[b];
}
};
if(array_[a] != undefined)
ret_array.push(array_[a]);
};
return ret_array;
}
console.log(remove_duplicates(Array(1,1,1,2,2,2,3,3,3)));
Loop through, remove duplicates, and create a clone array place holder because the array index will not be updated.
Loop backward for better performance ( your loop wont need to keep checking the length of your array)
You do not need insert the number that already is in newArray, you can know what element is in the array with the method indexOf.
Try it in the if, and you can delete the second cicle for.
Something like this:
if (Math.sqrt(arrayCheck[i]) % 1 === 0 && newArray.indexOf(arrayCheck[i])==-1)

Categories

Resources