I'm trying to write a function that will find which collection of numbers in the array adds up to the largest sum, and puts that number into the new array:
var num = ['267453', '345678', '876787'];
var newArray = [];
I'm actually at a loss here and not sure how to get started on this problem. Can someone help get me off on the right foot?
var num = ['267453', '345678', '876787'];
var sums =[];
num.forEach(function (el) {
string = el.split(''); //split into individual characters
var sum = 0; //have a storage ready
for (var i = 0; i < string.length; i++) { //iterate through
sum += parseInt(string[i],10); //convert from string to int
}
sums.push( sum);
}
Array.prototype.max = function() {
return Math.max.apply(null, this);
};
alert("Max value is: "+sums.max());
Iterate over the strings, split the in to digits sum the digits
var arrayLength = num.length;
var sums = []
for (var i = 0; i < arrayLength; i++) {
var digitsAsChar = num[i].split("");
var tmpSum=0;
var digitsLength = digitsAsChar.length;
for(var y=0; y<digitsLength;y++){
tmpSum = tmpSum+parseInt(digitsAsChar[y]);
}
sums.push(tmpSum)
}
finaly sort the array:
sums.sort():
If I understood your question correctly, you can achieve this rather easily.
var num = ['267453', '345678', '876787'];
var max = -Infinity;
var maxi = 0;
num.forEach(function (el, i) {
var n = el.split('').reduce(function (a, b) {
return parseInt(a,10) + parseInt(b,10);
});
if (n > max) {
max = n;
maxi = i;
}
})
console.log(max); //43
console.log(num[maxi]); //"876787"
Regarding performance, this calls parseInt a number of times more than strictly necessary, if speed is a problem you may want to consider parsing first and summing separately.
Here is the fiddle for this :
var num = ['267453', '345678', '876787'];
var newArray = [];
var html = '';
for(var n=0; n<num.length; n++) {
var len = num[n].length;
count = 0;
for(var i=0; i<len; i++) {
count += parseInt(num[n].substring(i,i+1));
//console.log(count);
}
var temp1 = parseInt(num[n]);
newArray.push(count);
}
newArray = newArray.sort();
newArray = newArray.reverse();
var max = newArray[0];
https://jsfiddle.net/o6mryk1q/1/
Related
I am trying to shuffle a deck. I take a number of cards as input. For example, numCards = 5, so the deck (list) becomes [0,1,2,3,4]. The problem is that the while loop in the test_order(i,j,l) function is not shuffling properly. Function console.log(m) should print a new shuffled deck/list using the original list (l) but it keeps printing [0,1,2,3,4] after the first correct shuffle. It should create a newly shuffled deck each time using the original list, instead, it keeps repeating the original list or 1st shuffled list.
The purpose of the program is to find the probability of the number of times a card labeled i is above card labeled j after shuffles.
function list(numCards){
var newList = []
var i = 0;
while (i < numCards){
newList.push(i);
i++;
}
return newList
}
function top_to_random(l){
while(numPerformed != 0){
var x = Math.floor(Math.random() * l.length);
l.splice(x, 0, l.shift())
numPerformed--;
}
return l
}
function test_order(i,j,l){ //PROBLEM IS IN HERE!!!!
var n = 0
var trials = 10
var count = 0
while (count < trials){ // PROBLEM IN WHILE LOOP
let arrayCopy = JSON.parse(JSON.stringify(l));
//console.log(arrayCopy)
var m = top_to_random(arrayCopy)
m.indexOf(i) < m.indexOf(j) ? n++ : n = n + 0
//console.log(arrayCopy)
console.log(m)
count++
}
var prob = n/trials
return prob
}
//Argument Inputs
var numCards = parseInt(prompt("Enter number of cards in deck: "))
var l = list(numCards)
var numPerformed = parseInt(prompt("Enter number of shuffles to perform on deck: "));
var i = parseInt(prompt("i: "))
var j = parseInt(prompt("j: "))
//Execution
console.log(test_order(i,j,l))
Problem is not where you think it is, it's in your top_to_random function. You count the number of mixes done in your shuffle down from numPerformed, but this is a global-scope variable, so its not reset at each call. You should pass the mix count as a parameter like this:
function top_to_random(l, mixNum){
for (;mixNum > 0; mixNum--) {
var x = Math.floor(Math.random() * l.length);
l.splice(x, 0, l.shift());
}
return l;
}
Fixing a number of your syntax miconstructs, I get this code:
function list(numCards){
var newList = [];
var i = 0;
while (i < numCards){
newList.push(i);
i++;
}
return newList;
}
function top_to_random(l, mixNum){
for (;mixNum > 0; mixNum--) {
var x = Math.floor(Math.random() * l.length);
l.splice(x, 0, l.shift());
}
return l;
}
function test_order(i,j,l){ //Problem is NOT in here
let n = 0;
let trials = 10;
for (let count = 0; count < trials; count++) { // No not here
let arrayCopy = [...l];
top_to_random(arrayCopy, numPerformed);
console.log(arrayCopy)
if (arrayCopy.indexOf(i) < arrayCopy.indexOf(j)) n++;
console.log(arrayCopy);
}
var prob = n/trials;
return prob;
}
// Argument Inputs
var numCards = parseInt(prompt("Enter number of cards in deck: "));
var l = list(numCards);
var numPerformed = parseInt(prompt("Enter number of shuffles to perform on deck: "));
var i = parseInt(prompt("i: "));
var j = parseInt(prompt("j: "));
//Execution
console.log(test_order(i,j,l));
Also You should be more careful about details when you code:
You have a lot of missing semicolons
You're mixing function arguments and global variables with no logic to the decision
Don't use while when you should be using for
Ternary operator to perform a simple if ?
You'd better use const and let instead of var. For one thing it would have saved you this error
Better written code:
const SHUFFLE_REPEATS = 10;
function list(numCards) {
const newList = [];
for (let i = 0; i < numCards; i++)
newList.push(i);
return newList;
}
function top_to_random(l, mixNum) {
for (; mixNum > 0; mixNum--) {
const x = Math.floor(Math.random() * l.length);
l.splice(x, 0, l.shift());
}
return l;
}
function test_order(i, j, l) {
let n = 0;
for (let count = 0; count < SHUFFLE_REPEATS; count++) {
const arrayCopy = [...l];
top_to_random(arrayCopy, numPerformed);
console.log(arrayCopy)
if (arrayCopy.indexOf(i) < arrayCopy.indexOf(j)) n++;
}
return n / SHUFFLE_REPEATS;
}
// Argument Inputs
const numCards = parseInt(prompt("Enter number of cards in deck: "));
const l = list(numCards);
const numPerformed = parseInt(prompt("Enter number of shuffles to perform on deck: "));
const i = parseInt(prompt("i: "));
const j = parseInt(prompt("j: "));
//Execution
console.log(test_order(i,j,l));
I am trying to get my array reversed without using the reverse() method. What am I doing wrong here?
This is the code that I have for now. I think I'm close but I'm stuck.
var zin = ["Kan jij achterstevoren praten?"];
var woorden = zin.split(" ");
woordenOmgedraaid = achterstevoren(woorden);
document.write(woordenOmgedraaid);
function achterstevoren(omgedraaid) {
var length = omgedraaid.length;
var woordenOmgedraaid = [];
var counter = 0;
for (var i = omgedraaid.length - 1; i >= 0; i -= 1) {
woordenOmgedraaid[counter] = omgedraaid[i];
counter += 1;
}
return woordenOmgedraaid;
}
Take the brackets off the "zin" variable.
var zin = "Kan jij achterstevoren praten?";
var woorden = zin.split(" ");
woordenOmgedraaid = achterstevoren(woorden);
console.log(woordenOmgedraaid);
function achterstevoren(omgedraaid) {
var length = omgedraaid.length;
var woordenOmgedraaid = [];
var counter = 0;
for (var i = omgedraaid.length - 1; i >= 0; i -= 1) {
woordenOmgedraaid[counter] = omgedraaid[i];
counter += 1;
}
return woordenOmgedraaid;
}
If you're trying to create a for loop that goes backwards through an array, you can simply write it as:
var arr = [1,2,3,4,5]
var reversedArr = []
for (var i = arr.length-1; i >= 0; i--) {
reversedArr.push(arr[i])
}
console.log(reversedArr)
Let's say I have an Array who's item length is too big for some maxLength
var maxLength = 3;
var arr = [1,2,3,4,5];
var tooBig = arr.length > maxLength;
Is there an optimized algorithm for reducing this array in length by combining item values?
if(tooBig){
var newArr = refactor(arr, maxLength);
console.log(newArr); //[5,5,5]
}
Evenly re-distributing as much as possible is important:
//Could be reduced more evenly like above
console.log(newArr); //[1,6,8]
The basic idea is to get the sum of the current array. Extract the reminder, and get an average without the reminder. Then create a new array, and populate it with the average + 1 as long as the reminder is greater than 0.
function refactor(arr, maxLength) {
var sum = arr.reduce(function(s, n) {
return s + n;
});
var remainder = sum % maxLength;
var average = (sum - remainder) / maxLength;
var arr = [];
for(var i = 0; i < maxLength; i++) {
arr.push(average + (i < remainder));
}
return arr;
}
var maxLength = 3;
var arr = [1,2,3,4,6];
var tooBig = arr.length > maxLength;
if(tooBig){
var newArr = refactor(arr, maxLength);
console.log(newArr); //[6,5,5]
}
If you don't need the array items to be integers, you can get the average directly, and set it as the value of each array item:
function refactor(arr, maxLength) {
var average = arr.reduce(function(s, n) {
return s + n;
}) / maxLength;
var arr = [];
for(var i = 0; i < maxLength; i++) {
arr.push(average);
}
return arr;
}
var maxLength = 3;
var arr = [1.7,2.4,3,4,6.934];
var tooBig = arr.length > maxLength;
if(tooBig){
var newArr = refactor(arr, maxLength);
console.log(newArr);
}
I am trying to count the number of permutations that do not contain consecutive letters. My code passes tests like 'aabb' (answer:8) and 'aab' (answer:2), but does not pass cases like 'abcdefa'(my answer: 2520; correct answer: 3600). Here's my code:
function permAlone(str) {
var totalPerm = 1;
var result = [];
//assign the first letter
for (var i = 0; i < str.length; i++) {
var firstNum = str[i];
var perm = firstNum;
//create an array from the remaining letters in the string
for (var k = 0; k < str.length; k++) {
if (k !== i) {
perm += str[k];
}
}
//Permutations: get the last letter and change its position by -1;
//Keep changing that letters's position by -1 until its index is 1;
//Then, take the last letter again and do the same thing;
//Keep doing the same thing until the total num of permutations of the number of items in the string -1 is reached (factorial of the number of items in the string -1 because we already established what the very first letter must be).
var permArr = perm.split("");
var j = permArr.length - 1;
var patternsLeft = totalNumPatterns(perm.length - 1);
while (patternsLeft > 0) {
var to = j - 1;
var subRes = permArr.move(j, to);
console.log(subRes);
if (noDoubleLettersPresent(subRes)) {
result.push([subRes]);
}
j -= 1;
if (j == 1) {
j = perm.length - 1;
}
patternsLeft--;
}
}
return result.length;
}
Array.prototype.move = function(from, to) {
this.splice(to, 0, (this.splice(from, 1))[0]);
return this.join("");
};
function totalNumPatterns(numOfRotatingItems) {
var iter = 1;
for (var q = numOfRotatingItems; q > 1; q--) {
iter *= q;
}
return iter;
}
function noDoubleLettersPresent(str) {
if (str.match(/(.)\1/g)) {
return false;
} else {
return true;
}
}
permAlone('abcdefa');
I think the problem was your permutation algorithm; where did you get that from? I tried it with a different one (after Filip Nguyen, adapted from his answer to this question) and it returns 3600 as expected.
function permAlone(str) {
var result = 0;
var fact = [1];
for (var i = 1; i <= str.length; i++) {
fact[i] = i * fact[i - 1];
}
for (var i = 0; i < fact[str.length]; i++) {
var perm = "";
var temp = str;
var code = i;
for (var pos = str.length; pos > 0; pos--) {
var sel = code / fact[pos - 1];
perm += temp.charAt(sel);
code = code % fact[pos - 1];
temp = temp.substring(0, sel) + temp.substring(sel + 1);
}
console.log(perm);
if (! perm.match(/(.)\1/g)) result++;
}
return result;
}
alert(permAlone('abcdefa'));
UPDATE: In response to a related question, I wrote an algorithm which doesn't just brute force all the permutations and then skips the ones with adjacent doubles, but uses a logical way to only generate the correct permutations. It's explained here: Permutations excluding repeated characters and expanded to include any number of repeats per character here: Generate all permutations of a list without adjacent equal elements
I agree with m69, the bug seems to be in how you are generating permutations. I got 3600 for 'abcdefa' by implementing a different algorithm for generating permutations. My solution is below. Since it uses recursion to generate the permutations the solution is not fast, however you may find the code easier to follow, if speed is not important.
The reason for having a separate function to generate the array index values in the permutations was to verify that the permutation code was working properly. Since there are duplicate values in the input strings it's harder to debug issues in the permutation algorithm.
// Simple helper function to compute all permutations of string indices
function permute_indices_helper(input) {
var result = [];
if (input.length == 0) {
return [[]];
}
for(var i = 0; i < input.length; i++) {
var head = input.splice(i, 1)[0];
var tails = permute_indices_helper(input);
for (var j = 0; j < tails.length; j++) {
tails[j].splice(0, 0, head);
result.push(tails[j]);
}
input.splice(i, 0, head); // check
}
return result;
};
// Given an array length, generate all permutations of possible indices
// for array of that length.
// Example: permute_indices(2) generates:
// [[0,1,2], [0,2,1], [1,0,2], ... , [2, 0, 1]]
function permute_indices(array_length) {
var result = [];
for (var i = 0; i < array_length; i++) {
result.push(i);
}
return permute_indices_helper(result);
}
// Rearrange letters of input string according to indices.
// Example: "car", [2, 1, 0]
// returns: "rac"
function rearrange_string(str, indices) {
var result = "";
for (var i = 0; i < indices.length; i++) {
var string_index = indices[i];
result += str[string_index];
}
return result;
}
function permAlone(str) {
var result = 0;
var permutation_indices = permute_indices(str.length);
for (var i = 0; i < permutation_indices.length; i++) {
var permuted_string = rearrange_string(str, permutation_indices[i]);
if (! permuted_string.match(/(.)\1/g)) result++;
}
return result;
}
You can see a working example on JSFiddle.
I have an array:
var myarray = [1,2,3,4,7,9,12,13,14]
I need to group values like so:
var array_1 = 1,2,3,4
var array_2 = 7
var array_3 = 8
var array_4 = 12,13,14
I need to find a sequences with an arithmetic progression and seperate from other values.
Any ideas?
Check out this solution
function explode(myarray)
{
var multi = [];
var i = j = 0;
for ( key in myarray )
{
if((myarray[key-1]) != (myarray[key]-1))
{
i++;
j=0;
}
if(j==0)
multi[i] = [];
multi[i][j] = myarray[key];
j++;
}
return multi;
}
It returns a multidimentionnal array that you can use in your example like this
var myarray = [1,2,3,4,7,9,12,13,14];
var multi_array = explode(myarray);
var array_1 = multi_array[0];
var array_2 = multi_array[1];
var array_3 = multi_array[2];
var array_4 = multi_array[3];
New update :
You can also remove the j index and use .push to add new elements to your array
function explode(myarray)
{
var multi = [];
var i = 0;
for ( key in myarray )
{
if((myarray[key-1]) != (myarray[key]-1))
i++;
if(!multi[i])
multi[i] = [];
multi[i].push(myarray[key]);
}
return multi;
}
The following seems to work, but displays a slightly different output than the one you expect.
In your example, I think 7 and 9 should be grouped (any sequence of two items is an arithmetic
progression after all). Or if they are not grouped, then 12 should not be grouped with 13 and
14 either, since 12-9 != 13-12
function split(arr) {
if (arr.length < 2) {
return;
}
var delta = undefined;
var start = 0;
for (var idx = 1; idx < arr.length; idx++) {
if (delta === undefined) {
delta = arr[idx] - arr[idx - 1];
}
if (arr[idx] - arr[idx - 1] != delta) {
alert("subarray " + arr.slice(start, idx));
start = idx;
delta = undefined;
}
}
alert("subarray from" + arr.slice(start, arr.length));
}
split([1,2,3,4,7,9,12,13,14]);
arrays = Array();
var c = 0;
array[c][] = myarray[0]);
for (var i = 1; i<myarray.length; i++) {
if (myarray[i-1] +1 != myarray[i])
c++;
array[c][] = push(myarray[i]);
}
not sure the array syntax (might mix up languages here) is correct or whether I understand your problem fully.