How to calculate how many pair of numbers in array - javascript

i'm currently in this assignment that bother me how to calculate how many pairs of number within an array
this is what i've been tried before
function pairNumber (n,ar)
let numberOfPairs=0
for(let i =0;i<ar.length;i++){
for(let j =1;j<ar.length;j++){
if (ar[i] == ar[j]){
console.log([ar[i], ar[j]], '<< ini isinya')
console.log(ar[i+1], ar[j+1])
numberOfPairs++
ar.splice(i,1)
ar.splice(j,1)
}
}
}
if(n%3 == 0){
numberOfPairs -= 1
return numberOfPairs
} else {
return numberOfPairs
}
}
console.log(sockMerchant(9,[10,20,20,10,10,30,50,10,20]))
console.log(sockMerchant(10,[1,1,3,1,2,1,3,3,3,3]))
but unfortunately, the return will always be
4
4
the correct answer should be
3
4
for both cases can someone please do help me what I've been missing? thanks you!

I just do the sort for array first then you just need loop the array 1 time. It's better to control your code
function pairNumber (n,ar){
let numberOfPairs=0
let i = 0
let j = 1
ar.sort()
for(let i = 0; i < ar.length; i++){
if(ar[i] == ar[i++]){
numberOfPairs++
i+=1
}
}
return numberOfPairs
}

As this is a simple assignment, I am not going to explain in detail. The issue seems to be in the loop variable initialization.
Hint: j=i+1

To overcome the quadratic approach with O(n2), you could take an object and count the occurences.
At the end return the sum by counting only the floored half values.
function pairNumber(n, array) {
var numberOfPairs = 0,
counts = {};
for (let v of array) {
if (!counts[v]) counts[v] = 0;
++counts[v];
}
for (let count of Object.values(counts)) numberOfPairs += count >> 1;
return numberOfPairs;
}
console.log(pairNumber(9, [10, 20, 20, 10, 10, 30, 50, 10, 20]))
console.log(pairNumber(10, [1, 1, 3, 1, 2, 1, 3, 3, 3, 3]))

Related

can anyone tell me what is this code for?

can anyone tell me what is this code for?
especially this line of code, I can't understand this line
ctr[arr[i] - 1]++;
function array_element_mode(arr) {
var ctr = [],
ans = 0;
for (var i = 0; i < 10; i++) {
ctr.push(0);
}
for (var i = 0; i < arr.length; i++) {
// what is this code for??
ctr[arr[i] - 1]++;
if (ctr[arr[i] - 1] > ctr[ans]) {
ans = arr[i] - 1;
}
}
return ans + 1;
}
console.log(array_element_mode([1, 2, 3, 2, 2, 8, 1, 9]))
I believe that this function is supposed to return the mathematical mode of an array.
I just added/fixed some variable names to your function. This is still a terrible implementation but I'm hoping that the edits will make what it does more clear to you.
function array_element_mode2(arr) {
var center = [],
mode = 0;
for (let i = 0; i < 10; i++) {
center.push(0);
}
for (let i = 0; i < arr.length; i++) {
const priorElementOfArr = arr[i] - 1;
center[priorElementOfArr]++;
if (center[priorElementOfArr] > center[mode]) {
mode = priorElementOfArr;
}
}
return mode + 1;
}
I renamed the varibles and splitted ctr[arr[i] - 1]++; into two lines. This functions is supposed to find the number which appears most in a given array of integers.
But it wont work if two or more integers appear the same number of times and if the array contains 0.
/*
* Goal: Find the number which appears most in a given array of integers
* Solution: In the ctr array store the number apperences in the following way
* ctr[0] appearances of "1" in the array
* ctr[1] appearances of "2" in the array
* ctr[2] appearances of "3" in the array
* ...
*/
function array_element_mode(arr) {
var ctr = [],
ans = 0;
// fill the ctr array with nulls
for (var i = 0; i < 10; i++) {
ctr.push(0);
}
for (var i = 0; i < arr.length; i++) {
//////////// here the ctr[arr[i] - 1]++; is splitted into 2 lines
// for each array member "find" the correct index to increase
const convertArrayMemberToIndexForCtr = arr[i] - 1;
// increase the correct index by one
ctr[convertArrayMemberToIndexForCtr]++;
///////////
// check if the increased index if larger then current answer and if so
// store it as the new result
if (ctr[convertArrayMemberToIndexForCtr] > ctr[ans]) {
ans = convertArrayMemberToIndexForCtr;
}
}
// return the result, but not the index we created before (on line 25), but the real number that is in the array (add the +1 we subtracted before)
return ans + 1;
}
console.log('working example');
console.log(array_element_mode([1, 2, 3, 2, 2, 8, 1, 9]));
console.log('this wont work, it shows that "3" is the result, ignoring the "2"');
console.log(array_element_mode([3, 3, 3, 2, 2, 2, 5, 9]));
console.log('this wont work as index arr[i] - 1 would then be 0-1=-1');
console.log(array_element_mode([0, 1, 1, 0, 0, 4, 5, 9]));
console.log('this wont work, all integers are only once in the array');
console.log(array_element_mode([1, 2, 3, 4, 5, 6, 7, 8]));
I think this function is to find out which element has the most number in the array
ctr[arr[i] - 1]++:In order to count

JS: restart loop with a updated index number

Is there a possibility to restart this loop with a new index number:
let ar = [1, 1, 2, 1, 2, 1, 3, 2, 3, 1];
let sortedArray = ar.sort();
let sameNumbersArray = [];
let numberOfSameNumbers = 0;
let lastIndexNumber = 0;
for (i = lastIndexNumber; i < sortedArray.length; i++) {
if (sortedArray[i] == sortedArray[i + 1]) {
const sameNumber = sortedArray[i];
sameNumbersArray.push(sameNumber);
} else {
break;
}
let lastIndexFromNumberArray = [];
lastIndexFromNumberArray.push(sameNumbersArray.length);
lastIndexFromNumberArray.push(3);
lastIndexFromNumberArray.push(2);
lastIndexNumber = lastIndexFromNumberArray.reduce(function (a, b) {
return a + b;
}, 0);
So basically that the loop (lastIndexNumber) starts with index[0], but then restarts with index[5] and index[7].
How would one add this extra loop?
I'm not 100% clear on the aim here. Are you able to elaborate on the desired result of the above?
It looks like you want to get an array of the unique numbers and perhaps the number of unique numbers from the source array?
If so, here's another way which might be cleaner:
let ar = [1, 1, 2, 1, 2, 1, 3, 2, 3, 1];
let sortedArray = ar.sort();
let newSameNumbersArray = unique(sortedArray);
//array of unique numbers:
console.log(newSameNumbersArray);
//count of unique numbers:
console.log(newSameNumbersArray.length);
function unique(array) {
return Array.from(new Set(array));
}
This is based on this answer: https://stackoverflow.com/a/44405494/4801692
That said, you can directly set the value of i and use continue to move to the 'next' iteration.
i = 5;
continue;
This is bad though as you are in danger of feeding i a lower number and getting stuck in an infinite loop. If you can explain the requirement a little more I might be able to suggest something better.
you can do such thing to find the pairs
let ar = [10, 10, 10, 20, 20, 10 ,30, 20 ,30]
function findPair(ar) {
let counts = {};
let count = [];
let sum = 0;
for(let i = 0; i < ar.length; i++){
let item = ar[i]
counts[item] = counts[item] >= 1 ? counts[item] + 1 : 1;
}
count = Object.values(counts);
for(let i = 0; i < count.length; i++){
if(count[i] >= 2){
sum += Math.floor(count[i]/2)
}
}
console.log(sum)
}
findPair(ar)

Mini-Max Sum HACKERHANK JS, why isn't working?

I don't know what's wrong, my function miniMaxSum isn't summing 1+3+4+5. At the end, the result array turns into this [ 14, 12, 11, 10 ], when it should looks like this [ 14, 13, 12, 11, 10 ]
function miniMaxSum(arr) {
let results = [];
let actualValue = 0;
let skipIndex = 0;
for (let i = 0; i < arr.length; i++) {
//skip actual index
if (i == skipIndex) continue;
actualValue += arr[i];
//restart the loop
if (i == arr.length - 1) {
skipIndex++;
results.push(actualValue);
actualValue = 0;
i = 0;
}
}
console.log(results);
console.log(Math.min(...results), Math.max(...results));
}
console.log(miniMaxSum([1, 2, 3, 4, 5]));
You're over-complicating your algorithm by trying to check whether you should add the current number to the overall sum or not. Instead, all you need to do is run a loop over your array, to sum up all your elements in your array. This will give you the total sum of all your elements. Then, again, iterate through your array. For each element in your array subtract it from the sum you just calculated and push it into a new array. This will give you the sum if you were to not use the number in the ith position. You can then find the min/max of this using JavaScript's Math.min and Math.max functions.
Here is an example using .reduce() and .map() to calculate the final result:
const miniMaxSum = arr => {
const sum = arr.reduce((s, n) => n+s, 0)
const results = arr.map(n => sum - n);
return [Math.min(...results), Math.max(...results)];
}
const [min, max] = miniMaxSum([1, 2, 3, 4, 5]);
console.log(min, max);
If you prefer standard for loops, here is an implementation of the above in a more imperative style:
const miniMaxSum = arr => {
let sum = 0;
for(let i = 0; i < arr.length; i++) { // sum all elements
sum += arr[i];
}
let results = [];
for(let i = 0; i < arr.length; i++) {
results[i] = sum - arr[i]; // sum minus the current number
}
return [Math.min(...results), Math.max(...results)];
}
const [min, max] = miniMaxSum([1, 2, 3, 4, 5]);
console.log(min, max);
Assuming you're talking about this question.
Whenever you want to restart the loop, you're setting i=0 but observe that you also have increment statement i++ in for loop so, effectively i starts from 1, not 0. You need to set i=-1 so that i=-1+1 = 0 in subsequent iteration. After doing this, you need to handle a corner case. When skipIndex==arr.length-1, check if i == arr.length-1. If yes, do results.push(actualValue); for the last value and then for loop terminates because i < arr.length is false in next iteration.
Code:
function miniMaxSum(arr) {
let results = [];
let actualValue = 0;
let skipIndex = 0;
for (let i = 0; i < arr.length; i++) {
//skip actual index
if (i == skipIndex){
if(i == arr.length - 1)
results.push(actualValue);
continue;
}
actualValue += arr[i];
//restart the loop
if (i == arr.length - 1) {
skipIndex++;
results.push(actualValue);
actualValue = 0;
i = -1;
}
}
console.log(results);
console.log(Math.min(...results), Math.max(...results));
}
miniMaxSum([1, 2, 3, 4, 5]);
Output
[ 14, 13, 12, 11, 10 ]
10 14

Product of all other numbers in array

I have a function which takes an array of numbers as an argument. I want to return a new array with the products of each number except for the number at the current index.
For example, if arr had 5 indexes and we were creating the value for index 1, the numbers at index 0, 2, 3 and 4 would be multiplied.
Here is the code I have written:
function getProducts(arr) {
let products = [];
for(let i = 0; i < arr.length; i++) {
let product = 0;
for(let value in arr.values()) {
if(value != arr[i]) {
product *= value;
}
}
products.push(product);
}
return products;
}
getProducts([1, 7, 3, 4]);
// Output ➞ [0, 0, 0, 0]
// Expected output ➞ [84, 12, 28, 21]
As you can see, the desired output does not actualise. I did some experimenting and it appears that the second for loop is never really initiated, as any code I put inside the block does not execute:
function getProducts(arr) {
let products = [];
for(let i = 0; i < arr.length; i++) {
let product = 0;
for(let value in arr.values()) {
console.log('hello!');
if(value != arr[i]) {
product *= value;
}
}
products.push(product);
}
return products;
}
getProducts([1, 7, 3, 4]);
// Output ➞
// Expected Output ➞ 'hello!'
What is wrong with my code?
You could take the product of all numbers and divide by the number of the index to get a product of all except the actual value.
function getProducts(array) {
var product = array.reduce((a, b) => a * b, 1);
return array.map(p => product / p);
}
console.log(getProducts([1, 7, 3, 4]));
A more reliable approach with an array with one zero. If an array has more than one zero, all products are zero.
The below approach replaces the value at index with one.
function getProducts(array) {
return array.map((_, i, a) => a.reduce((a, b, j) => a * (i === j || b), 1));
}
console.log(getProducts([1, 7, 0, 4]));
console.log(getProducts([1, 7, 3, 4]));
You simply have to change the in keyword to of keyword. Is not the same a for..in than a for..of.
arr.values() returns an iterator, which has to be iterated with the of keyword.
Also, if product = 0, then all your multiplications will return 0.
By the way this code is prone to error, because you don't check the current index, but you check if the value that you are multiplying is different than the current value. This will lead to a problem if the same number is duplicated in the array.
And, now talking about good practices, is a bit weird that first you iterate through the array with a for(var i... loop and the second time you do it with a for...in/of.
I've fixed the code for you:
function getProducts(arr) {
let products = [];
for(let i = 0; i < arr.length; i++) {
let product = 1;
for(let ii = 0; ii < arr.length; ii++) {
if(i != ii) {
product *= arr[ii];
}
}
products.push(product);
}
return products;
}
A better way to do that is get the total product and use map() to divide total with each value
function getProducts(arr){
let total = arr.reduce((ac,a) => ac * a,1);
return arr.map(x => x === 0 ? total : total/x);
}
console.log(getProducts([1, 7, 3, 4]))
Explanation: replace the number at i with 1 so it doesn't interfere with the multiplication. Also, apply the fill on a copy of a hence the [...a]
console.log( [2,3,4,5].map( (n,i,a) => [...a].fill(1,i,i+1).reduce( (a,b) => a*b ) ) )

Can this function be changed to be more efficient? memory and time

I had a job interview in which I had a couple code exercises. One of which was write a function that can take a numerical array and return either the first duplicated number or -1 in the case of no duplication. I wrote the following function that answers the exercise but failed on efficiency. The problem was, I was not given a sufficient answer, so for a learning point, can someone help me write this function more efficient.
function myFunc(arr) {
for (var i = 0; i < arr.length; i++) {
for (var x = 0; x < arr.length; x++) {
if ((arr[i]==arr[x]) && ( i > x)) {
return arr[i];
}
}
}
return -1;
}
examples of returns:
arr = {8, 4, 6, 2, 6, 4, 7, 9, 5, 8} returns 6
arr = {2, 3, 3, 1, 5, 2} returns 3
In terms of time, you can do it in O(n). Loop through the array, and add the values to a table. As soon as you come across one that you've already added to the table, you've found your duplicate. Adding to and checking the table is O(1), so the algorithmic complexity is dominated by the loop, which is O(n)
function myFunc(arr) {
const table = {};
for (let i = 0; i < arr.length; i++) {
if (table[arr[i]] === true) {
return arr[i];
} else {
table[arr[i]] = true;
}
}
return -1;
}
console.log(myFunc([1, 2, 1, 3, 2]));
In ES6, you could use a Set instead of an object.
You can make your loop on x start from i+1 as instead of checking if i>x in your code
for ( x = i+1; x < arr.length; x++ )
What about sort the data before search for duplicated values:
function MyFunc(arr)
{
var sorted = arr.slice().sort();
for (var i = 0; i < arr.length - 1; i++)
if( sorted[i+1] == sorted[i] )
return sorted[i];
return -1;
}

Categories