subtracting two integers which have different indexes but the same value - javascript

The given function should accept any array with any number of integers.
After it should subtract each two integers from each other beside integers which the same index.
var ArrayFirst = [4, 34, 6, 1,5];
var ArraySecond = [4,34,6,1,4];
function Find(Arg) {
var ResultArray;
var SecondArray = [];
for (var i = 0; i < Arg.length; i++) {
var FirsArray;
for (var j = 0; j < Arg.length; j++) {
if (Arg.indexOf(Arg[i]) != Arg.indexOf(Arg[j])) {
console.log(Arg.indexOf(Arg[i]) + 'AND' + Arg.indexOf(Arg[j]));
FirstArray = Arg[i] - Arg[j];
console.log(FirstArray);
if (FirstArray >= 0) {
SecondArray.push(FirstArray);
}
}
}
//console.log(SecondArray);
}
ResultArray = Math.min.apply(this, SecondArray);
console.log(ResultArray);
return ResultArray;
}
So After debuging I found that function Find works with ArrayFirst but not with ArraySecond
Question : Why function is not working when Array has two integers with the same value ?
UPDATED
Sorry guys that I haven't putted more details
Task: Create a function which as result will give the sum of subtracting two integers from an array, the sum cannot be subtraction of two integers which have the same index, the sum cannot be bellow 0, the sum closest to the 0 will be the proper result.
Example: [4,6,3,56,4]
4-6,4-3...4-4, then 6-4,6-3...6-4 then etc
So result will be 0 because 4-4 sum is 0
Some Hints
Firstly i thought maybe it is something to do with operation on array but then i used apply and call on arguments
if (Array.prototype.indexOf.apply(arguments[0],[arguments[0][i]]) !== Array.prototype.indexOf.apply(arguments[0],[arguments[0][j]])) {
FirstArray = arguments[0][i] - arguments[0][j];
if (FirstArray >= 0) {
SecondArray.push(FirstArray);
}
}
}
But is still not working, I tried the solution with to arguments, doesn't work either.

First and foremost avoid using Array as a variable name because for the most browser it will lead to unexpected behavior.
I think also you need to pass the two arrays in your function as parameters in order compare them.
And you don't need to find the index of element with index i, the i itself is an index.
Array.indexOf(Array[i]) === i
Here is an example of what you might need:
// it is important for the "array" value to start with lower case symbow, because JavaScript is case sensitive language and it already has object called "Array"
var array = [4, 6, 3, 56, 4];
function find(array)
{
// because we are surching for the minimum, the variable that will hold it needs to have the largest possible variable at the begining
var min = Number.MAX_VALUE;
for (var i = 0 ; i < array.length; i++)
{
for (var j=0 ; j < array.length; j++)
{
if (i != j)
{
var sum = array[i] - array[j];
// if it sum is greater than zero and it is the smallest sum so far we will save it in "min"
if (sum >= 0 && min > sum)
{
min = sum;
}
}
}
}
// retun the smallest sum we've encountered
return min;
}
console.log(find(array));

Related

How to stop random letter picking from doing duplicate letters [duplicate]

I need help with writing some code that will create a random number from an array of 12 numbers and print it 9 times without dupes. This has been tough for me to accomplish. Any ideas?
var nums = [1,2,3,4,5,6,7,8,9,10,11,12];
var gen_nums = [];
function in_array(array, el) {
for(var i = 0 ; i < array.length; i++)
if(array[i] == el) return true;
return false;
}
function get_rand(array) {
var rand = array[Math.floor(Math.random()*array.length)];
if(!in_array(gen_nums, rand)) {
gen_nums.push(rand);
return rand;
}
return get_rand(array);
}
for(var i = 0; i < 9; i++) {
console.log(get_rand(nums));
}
The most effective and efficient way to do this is to shuffle your numbers then print the first nine of them. Use a good shuffle algorithm.What Thilo suggested will give you poor results. See here.
Edit
Here's a brief Knuth Shuffle algorithm example:
void shuffle(vector<int> nums)
{
for (int i = nums.size()-1; i >= 0; i--)
{
// this line is really shorthand, but gets the point across, I hope.
swap(nums[i],nums[rand()%i]);
}
}
Try this once:
//Here o is the array;
var testArr = [6, 7, 12, 15, 17, 20, 21];
shuffle = function(o){ //v1.0
for(var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
return o;
};
shuffle(testArr);
This is relatively simple to do, the theory behind it is creating another array which keeps track of which elements of the array you have used.
var tempArray = new Array(12),i,r;
for (i=0;i<9;i++)
{
r = Math.floor(Math.random()*12); // Get a random index
if (tempArray[r] === undefined) // If the index hasn't been used yet
{
document.write(numberArray[r]); // Display it
tempArray[r] = true; // Flag it as have been used
}
else // Otherwise
{
i--; // Try again
}
}
Other methods include shuffling the array, removing used elements from the array, or moving used elements to the end of the array.
If I understand you correctly, you want to shuffle your array.
Loop a couple of times (length of array should do), and in every iteration, get two random array indexes and swap the two elements there. (Update: if you are really serious about this, this may not be the best algorithm).
You can then print the first nine array elements, which will be in random order and not repeat.
Here is a generic way of getting random numbers between min and max without duplicates:
function inArray(arr, el) {
for(var i = 0 ; i < arr.length; i++)
if(arr[i] == el) return true;
return false;
}
function getRandomIntNoDuplicates(min, max, DuplicateArr) {
var RandomInt = Math.floor(Math.random() * (max - min + 1)) + min;
if (DuplicateArr.length > (max-min) ) return false; // break endless recursion
if(!inArray(DuplicateArr, RandomInt)) {
DuplicateArr.push(RandomInt);
return RandomInt;
}
return getRandomIntNoDuplicates(min, max, DuplicateArr); //recurse
}
call with:
var duplicates =[];
for (var i = 1; i <= 6 ; i++) {
console.log(getRandomIntNoDuplicates(1,10,duplicates));
}
const nums = [1,2,3,4,5,6,7,8,9,10,11,12];
for(var i = 1 ; i < 10; i++){
result = nums[Math.floor(Math.random()*nums.length)];
const index = nums.indexOf(result);
nums.splice(index, 1);
console.log(i+' - '+result);
}

Find the number with the most digits in an array

Here we are. Stuck.
I've decided to create a function that finds the element with the most digits. If two of them have the same length, return the first one. Common sense tells us that it might be the highest number. Here is the code snippet:
function findLongest(array) {
var biggestNum = 0;
for(var i = 0; i < array.length; i++) {
if(array[i] > biggestNum) {
biggestNum = array[i];
}
}
return biggestNum;
}
findLongest([111,1111,5555,10000,1,90000]); //returns 90000 instead of 10000.
However, I can't meet the second condition (if length of two is the same, return the first one).
Any idea?
If you want digit-length comparing, cast the items into string and use length of them.
function findLongest(array) {
var biggestNum = 0;
for(var i = 0; i < array.length; i++) {
if(array[i].toString().length > biggestNum.toString().length) {
biggestNum = array[i];
}
}
return biggestNum;
}
console.log(findLongest([111, 1111, 5555, 10000, 1, 90000]));
You could take the integer value of the logarithm of 10 of the value for checking, because you get the count of digits (minus 1) for comapiring.
function findLongest(array) {
var biggestNum = array[0];
for (var i = 1; i < array.length; i++) {
if (Math.floor(Math.log10(array[i]) || 0) > Math.floor(Math.log10(biggestNum) || 0)) {
biggestNum = array[i];
}
}
return biggestNum;
}
console.log(findLongest([111, 1111, 5555, 10000, 1, 90000, 0]));
The second condition negates the first every time. The "highest number" right?
If you want the highest number why not sort and pop the last element as the returned value?
array[array.sort(function(a,b){return b - a}).length - 1]
Iteration of array is unnecessary

Getting the prime factors of two arrays

Hello guys I am trying to create an LCM function that takes in two numbers. The findCommonMultiple() function in this piece of code basically returns an array for the prime factors for that number. What I'm trying to do in this function is to check if there are duplicates in both arrays and if there are any that number will be pushed inside a new array. After a number has been pushed the inner loop should break and continue to the next iteration. If both numbers are not equal to each other they both will be pushed. This also goes on even if one of the arrays goes over their index. After all the duplicate factors and unique ones have been pushed I will begin to multiply them and return the LCM of both numbers. I have yet to create a helper function for that but I need to fix this problem first.
function leastCommonMultiple(num1, num2){
var prime1 = findPrimeFactors(num1);
var prime2 = findPrimeFactors(num2);
var primes = [];
var lcm = 1;
for(var i = 0; i < prime1.length; i++){
var factor1 = prime1[i];
for(var j = i; j < prime2.length; j++){
var factor2 = prime2[j];
if(factor1 === factor2){
primes.push(factor1);
break;
} else if(factor1 === undefined && factor2 > 0){
primes.push(factor2);
} else if(factor2 === undefined && factor2 > 0){
primes.push(factor1)
} else {
primes.push(factor1);
primes.push(factor2);
break;
}
}
}
return primes;
}
EDIT:
So I'm adding a test case. So if I have values 26 and 24 passed I would get two arrays. One would be [2, 2, 2, 3] and the other would be [2, 13]. This function will take my duplicates in side the new array and add in all the others that aren't duplicates so: [2] is in first because both arrays have 2 and then [2, 2, 2, 3, 13] the rest of the numbers without duplicates gets added into the array.
If all you need is unique items from both the arrays, I suggest doing it this way,
First concatenate the two arrays and store it in a new array, in this case,
var tempPrimes= prime1.concat(prime2);
Then just write a simple filter to filter out unique values,
var primes = tempPrimes.filter(function(item, pos){
return tempPrimes.indexOf(item)== pos;
});
If you also want to remove 0 values, then just modify it a bit,
var primes = tempPrimes.filter(function(item, pos){
return tempPrimes.indexOf(item)== pos && tempPrimes[pos]!=0;
});
Hope I helped :)
Edit (after further clarification of the question):
var tempPrimes= prime2.filter(function(item) {
return prime1.indexOf(item) < 0;
});
var primes= prime1.concat(tempPrimes);
When your arrays of prime factors are sorted, which I think they are, you can just traverse them simultaneously. If one of the array heads is smaller than the other, advance that head and push it to the result array. If both array heads are equal, push the head value and advance both heads. That way, you don't have nested loops.
The following code does this and creates arrays or the least common multiple and the greatest common divisor at the same time:
var prime1 = findPrimeFactors(num1);
var prime2 = findPrimeFactors(num2);
var lcm = [];
var gcd = [];
let i = 0;
let j = 0;
while (i < prime1.length && j < prime2.length) {
if (prime1[i] < prime2[j]) {
lcm.push(prime1[i++]);
} else if (prime1[i] > prime2[j]) {
lcm.push(prime2[j++]);
} else {
gcd.push(prime1[i]);
lcm.push(prime1[i]);
i++;
j++;
}
}
while (i < prime1.length) lcm.push(prime1[i++]);
while (j < prime2.length) lcm.push(prime2[j++]);
Another way to solve this is to ceate a count dictionary for both numbers. Merge the two dicts by adding the maximum count for each key to the result dict. This method doesn't require sorted prime factor arrays:
var pmax = {}; // result count dict
var pmax2 = {}; // auiliary count dict of primes2
for (let i = 0; i < prime1.length; i++) {
let p = prime1[i];
pmax[p] = (pmax[p] || 0) + 1;
}
for (let i = 0; i < prime2.length; i++) {
let p = prime2[i];
pmax2[p] = (pmax2[p] || 0) + 1;
}
for (let k in pmax2) {
pmax[k] = Math.max((pmax[k] || 0), pmax2[k]);
}
for (let k in pmax) {
let n = pmax[k];
while (n--) lcm.push(k);
}
Finally, the easiest way to calculate the least common multiple might be to calculate the greatest common divisor with Euclid's algorithm and to apply the relation
lcm(a, b) = a * b / gcd(a, b)
(But be careful, because that method might cause overflow for large numbers.)
There was a simpler way to get the lcm of two numbers. My solution was good but it needed more work.
function lcm(num1, num2){
for(var i = 1; i <= num1 * num2; i++){
if(i % num1 === 0 && i % num2 === 0){
return i;
}
}
}

Comparing sums of elements within an array to determine which is the highest

I am trying to create a single function in Javascript that will take each element of an array of numbers (specifically phone numbers in this case) and determine which element has the highest sum. I have reached a point where I am feeling pretty defeated, yet I think I am very close. Can anyone give some guidance? This is what I have so far:
function highest(inputArray) {
var sum = 0;
var currentHighest = 0;
var largest = 0;
I set the variables I am going to use, then created a for loop to iterate over each element in the array.
for (a = 0; a < inputArray.length; a++)
var tempArray = inputArray[a].replace(/\D/g,'');
I create a place holder string to remove any non integers in the element, then create a function that will sum all the digits of the element.
function sumDigits(str) {
for (i = 0; i < str.length; i++) {
sum += parseInt(str.charAt(i));
return sum;
}
}
Then create an if statement that tests if the sum of the current element is higher or equal to the highest sum element.
if (sumDigits(tempArray) >= currentHighest) {
currentHighest = sum;
largest = inputArray[a];
return largest;
}
else {
return largest;
}
}
var newArray = ['123-456-7777', '963-481-7945', '111-222-3333'];
console.log(highest(newArray));
Here is the entire code block as a whole:
function highest(inputArray) {
var sum = 0;
var currentHighest = 0;
var largest = 0;
for (a = 0; a < inputArray.length; a++)
var tempArray = inputArray[a].replace(/\D/g,'');
function sumDigits(str) {
for (i = 0; i < str.length; i++) {
sum += parseInt(str.charAt(i));
return sum;
}
}
if (sumDigits(tempArray) >= currentHighest) {
currentHighest = sum;
largest = inputArray[a];
return largest;
}
else {
return largest;
}
}
}
var newArray = ['123-456-7777', '963-481-7945', '111-222-3333'];
console.log(highest(newArray));
I get "undefined" as the result when I run the code if that helps. Thank you in advance for your assistance.
If I'm interpreting this question correctly (add each number of a phone number, then print the largest result), you can accomplish it like this:
//Define an array of phone numbers
var numbers = ['123-456-7777', '111-222-3333', '963-481-7945'];
//Map takes an array, does something with each element, then returns that result
var sums = numbers.map(function (m) {
//In this case, we return an object containing the original number, and a score
return {
number: m,
//The score is calculated by adding up each number. The match expression creates an array of all terms (g modifier) matching the expression. \d matches a single digit, so we end up with an array of each digit in the number.
//Reduce applies a function to each item in an array, and adds them up
score: m.match(/\d/g).reduce(function (p, c) {
//This looks like magic, but the + before p and c coerces them to numbers (they're strings right now, since match returns an array of strings)
//Both numbers are then added
return +p + +c;
})
}
}).sort(function (a, b) {
//Now that we have the scores of all numbers, we can sort the array to find the highest score
//To be honest, sort() is mostly trial and error for me to find which values to return 1 and -1 for
if (a.score < b.score) return 1;
if (a.score > b.score) return -1;
return 0;
});
//All together, without comments:
sums = numbers.map(function (m) {
return {
number: m,
score: m.match(/\d/g).reduce(function (p, c) {
return +p + +c;
})
}
}).sort(function (a, b) {
if (a.score < b.score) return 1;
if (a.score > b.score) return -1;
return 0;
});
console.log(sums);
document.write("Number with the highest score: " + sums[0].number);
document.write("<br>");
document.write("It's score is " + sums[0].score);
Which prints the number with the largest sum to the console. The sum of the numbers is also available in the object that is returned in the score property.
In your code, you are not initializing the sum variable here and you are prematurely returning the sum value in this function:
function sumDigits(str) {
for (i = 0; i < str.length; i++) {
sum += parseInt(str.charAt(i));
return sum;
}
}
It should be this:
function sumDigits(str) {
var sum = 0;
for (i = 0; i < str.length; i++) {
sum += parseInt(str.charAt(i), 10);
}
return sum;
}
We can't really see what else is wrong without seeing all the code together in one block so we can see how different parts call each other and interact.
Here's a more compact solution (assuming you're trying to sum the digits in each phone number):
var phoneNumbers = ["123-456-7890", "982-111-9999"];
var sums = phoneNumbers.map(function(p) {
return p.match(/\d/g).reduce(function(sum, num) {
return sum + parseInt(num, 10);
}, 0);
});
var maxSum = Math.max.apply(Math, sums);
// output results in the snippet window
document.write("sums = " + JSON.stringify(sums) + "<br>");
document.write("maxSum = " + maxSum + "<br>");
Here's how it works:
Run .map() on the phone numbers array with the goal of returning an array of sums.
Within the .map() search for all digits, then run .reduce() on that resulting array to accumulate the sum.
Then, to get the max value in the sums array, use Math.max() which can accept the entire array and do the max work for you.

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