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);
}
Related
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);
}
I am attempting to determine all possible sums from rolling n dice, where n is not known at compile time.
For two dice, the solution is straightforward, just iterate through both dice and add each possible side to each other. If passing in 2 6-sided dice, the sorted results would be: [2,3,3,4,4,4,5,5,5,5,6,6,6,6,6,7,7,7,7,7,7,8,8,8,8,8,9,9,9,9,10,10,10,11,11,12]
I tried to expand this solution to any n dice, but I realized that I need n for loops.
for(let i = 0; i < numDice; i++)
{
dice.push(sides);
}
for(let i = 0; i < numSides; i++)
{
for(let j = 1; j < dice.length; j++)
{
for(let k = 0; k < numSides; k++)
{
results.add(dice[0][i] + dice[j][k]);
}
}
}
I also attempted a recursion-based approach as the first question below suggested. I believe it will loop the correct number of times, but I couldn't figure out how to define my summing function without introducing yet more loops.
function doCallMany(numDice, numSides, sumFunc)
{
if(numDice == 0)
{
sumfunc(numDice, numSides) //?
}
else
{
for(let i = 0; i < numSides; i++)
{
doCallMany(numDice--, numSides, sumFunc)
}
}
}
I looked at similar questions here and here but they do not answer my question. The first doesn't because the action I need to perform in the loops is not independent. The second is close, but the answers rely on Python-specific answers.
The comment about the complexity of the solutions is correct. It gets big quickly. Having said that, to address your original question, you can do this with a fairly simple recursive function for small input. Basically you start with an array of dice, pop one off add it to a sum and recurse with that sum and the rest of the array.
For example:
function sums(dice, sum = 0, ans = []) {
if (dice.length === 0) ans.push(sum) // edge case, no more dice
else {
let d = dice[0]
for (let i = 1; i <= d; i++) {
sums(dice.slice(1), sum + i, ans) // recurse with remaining dice
}
return ans
}
}
// two six-sided dice
let ans = sums([6, 6])
console.log(JSON.stringify(ans.sort((a, b) => a - b)))
// three three-sided dice
ans = sums([3, 3, 3])
console.log(JSON.stringify(ans.sort((a, b) => a - b)))
I suggest you use the backtracking method.
It lets you vary the number of loops you want to execute. You can even execute a random number of loops, as the number of loops can be held in a variable.
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;
}
}
}
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));
I am new to Javascript, I am doing a coding challenge to learn more about the language. This is not school related or anything like that, totally for my own personal growth. Here is the challenge:
Return the sum of all odd Fibonacci numbers up to and including the
passed number if it is a Fibonacci number.
I have spent the past 2 evenings working on solving this challenge. When I run my code using underscore.js it works. When I use Ramda.js it says NaN. I would think both would return NaN. I'm very surprised that I can get the correct answer from one and not the other. Any insights would be greatly appreciated!
var R = require('ramda');
function sumFibs(num) {
var fib_Arr = [];
var new_Arr = [];
var total = 0;
// I use this to tell if the fib num is greater than 2
var the_Bit = "false";
// This is used to keep track of when to stop the loop
var fib_Num = 0;
// THIS WORKS FROM HERE
// This loop generates a list of fibonacci numbers then pushes them to the fib_Arr
for(var i = 0; total < num; i++){
if (i < 1){
fib_Arr.push(0);
}
else if (i === 1){
fib_Arr.push(i);
fib_Arr.push(1);
}
else if (i === 2){
fib_Arr.push(2);
the_Bit = "true";
}
else if (the_Bit === "true"){
temp_Arr = R.last(fib_Arr,2);
temp_Arr = temp_Arr[0] + temp_Arr[1];
fib_Arr.push(temp_Arr);
total = R.last(fib_Arr);
}
// Generating the fib Array works TO HERE!!!!
}
// console.log(fib_Arr); // Print out the generated fibonacci array
// if last Array element is greater than the original in
var last_Element = R.last(fib_Arr);
if (last_Element > num){
console.log("The last element of the array is bigger!");
fib_Arr.splice(-1,1); // This removes the last item from the array if it is larger than the original num input
}
// This loop removes all of the EVEN fibonacci numbers and leaves all of the ODD numbers
for (var j = 0; j < fib_Arr.length; j++){
if (fib_Arr[j] % 2 !== 0){
new_Arr.push((fib_Arr[j]));
}
}
// This checks if the original input num was a
if (num % 2 !== 0){
new_Arr.push(num);
}
else{
console.log("The original num was not a Fibonacci number!");
}
// if last Array element is the same as the original input num
var last = R.last(fib_Arr);
if (last === num){
console.log("Removing the last element of the array!");
new_Arr.splice(-1,1); // This removes the last item from the array if it is the same as the original num input
}
// Now to add all of the numbers up :-)
for (var k = 0; k < new_Arr.length; k++){
console.log("This is fib_Num: " + fib_Num);
// console.log(fib_N`);
fib_Num = fib_Num += new_Arr[k];
}
return fib_Num;
}
// TEST CASES:
// console.log(sumFibs(75025)); //.to.equal(135721);
console.log(sumFibs(75024)); //.to.equal(60696);
You have a problem on these lines :
temp_Arr = R.last(fib_Arr,2);
temp_Arr = temp_Arr[0] + temp_Arr[1];
Besides the fact that R.last does not take a second argument (that will not fail though), you are using temp_arr as an array, when it is a number. Therefore, temp_arr gets a NaN value.
You are probably looking for R.take (combined with R.reverse) or R.slice.
By changing :
temp_Arr = R.last(fib_Arr,2);
with :
temp_Arr = R.take(2, R.reverse(fib_Arr));
or with :
temp_Arr = R.slice(fib_Arr.length - 2, fib_Arr.length)(fib_Arr);
or with (bonus play with a reduce from the right) :
temp_Arr = R.reduceRight(function(arr, elem) {
return arr.length < 2 ? [elem].concat(arr) : arr;
}, [])(fib_Arr);
We get :
sumFibs(75024) === 60696
For the record, here's how you do this problem:
function fibSumTo(n) {
var f1 = 1, f2 = 1, sum = 1, t;
while (f2 <= n) {
if (f2 & 1) sum += f2;
t = f1 + f2;
f1 = f2;
f2 = t;
}
return sum;
}
There's really no need for any sort of library because there's really no need for any sort of data structure.
var _ = require('underscore');function sumUpFibs (number){
arr_of_fibs = [1,1];
current = 1; //cursor for previous location
while (true){
var num = arr_of_fibs[current] + arr_of_fibs[current - 1];
if (num <= number) {
arr_of_fibs.push(num);
current++;
} else {
break;
}
}
console.log(arr_of_fibs);
var total = 0;
_.each(arr_of_fibs, function(fib){
total += fib;
})
return total;}console.log(sumUpFibs(75025));
This may be a better implementation... Though I know you're just starting so I don't want to come off as mean : D.... Also, maybe check your test cases too.