I have a question about feasibility of my code. I'm sure there is a better and more efficient way to write the function I wrote.
This is the function:
let i;
for (i = 0; i < ns.length; i++) {
if (ns[i] > 1) {
ns[i] = 3;
const place = ns[i];
ns.splice(place + 2, 1, 4);
ns.splice(place, 1, 2);
ns.splice(place - 1, 1, 1);
}
}
Initial Array (this array have a length of upto 20 items):
ns = [1 , 1 , 1 , 1 , 2 , 0]
Result Array:
ns = [1 , 1 , 1 , 2 , 3 , 4]
Believe it or not but this will suit my needs. But is there a better way than to just add up three times splice? It also extends my array if the number two of the initial array is at the end or beginning. I know I could just wrap it in another conditional but this seems so clumsy to me.
Thanks in Advance!
Regards
You could replace splicing with deleting a single value and adding a single value with a simple assingment at the index.
For preventing updating values at not given indices, you could take a function which checks the wanted index and updates only given indices.
function update(array, index, value) {
if (index >= 0 && index < array.length) {
array[index] = value;
}
}
var ns = [1, 1, 1, 1, 2, 0],
length = ns.length,
i,
place = 3;
for (i = 0; i < length; i++) {
if (ns[i] > 1) {
ns[i] = place;
update(ns, place - 1, 1);
update(ns, place, 2);
update(ns, place + 2, 4);
}
}
console.log(ns);
So with help from Nina Scholz and a Friend i got to the right answer:
Initial Array:
["1", "1", "1", "1", "1", "2", "0", "0"]
Desired Array:
["1", "1", "1", "1", "2", "3", "4", "0"]
The Function:
isSibling() {
const siblings = this.props.data.map(item => (
item.progress
));
let i;
const place = '3';
for (i = 0; i < siblings.length; i++) {
if (siblings[i] === '2') {
const num = i;
siblings[i] = place;
this.update(siblings, i - 1, '2');
this.update(siblings, i + 1, '4');
return siblings;
}
}
return siblings;
}
Update Function:
to ensure the array is not enlongated or shortened:
update(array, index, value) {
if (index >= 0 && index < array.length) {
array[index] = value;
}
}
Thank you for your help! :D
Related
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
How do i multiply every number in the array from position tabProsent[I] to the left? It is not working for me to write tabProsent[i].reduceRight(getSum).
function getSum(total, num) {
return total * num;
}
// Update the current slider year (each time you drag the slider handle)
slider.oninput = function() {
output.innerHTML = this.value;
var i;
for (i = 0; i < tabAar.length; i++) {
if (slider.value == tabAar[i]) {
output2.innerHTML=Math.round(startVerdi * tabProsent[i].reduceRight(getSum));
}
}
}
This is a possible solution.
Note: I don't know what the result should be if the index is negative, actually then you get an result of 1. If index is greater then array-length the I reduce pos to the array-length.
function getMult(arr, pos) {
if (pos>=arr.length)
pos = arr.length-1;
let res =1;
for (let i=0; i<= pos; i++) {
res *= arr[i];
}
return res;
}
console.log(getMult([1,2,3,4,5], 3));
A functional approach could look like this:
let multToLeft = (arr, num, m) => {
if (num < 0 || num > arr.length) throw new Error(`Invalid num ${num}`);
return [ ...arr.slice(0, num).map(v => v * m), ...arr.slice(num) ];
};
let examples = [
[ [ 1, 2, 3, 4, 5 ], 2, 10 ],
[ [ 1, 2, 3, 4, 5 ], 3, 20 ],
[ [ 1, 2, 3, 4, 5 ], 5, 11 ]
];
for (let [ arr, num, m ] of examples) {
console.log(`multToLeft(${JSON.stringify(arr)}, ${num}, ${m}) -> ${JSON.stringify(multToLeft(arr, num, m))}`);
}
Note that I am working with num instead of index. I've chosen num to indicate the actual number of elements to the left of the array that get multiplied. This makes more sense than working with index, as it becomes messy to apply the multiplication to zero elements in the array (since supplying 0 would still mean to apply the multiplication to the first array item).
I have an array which values are like this :
1,2,3,4,5,6,7,8,9 (based on row of the table)
In my case if i select as "istirahat" at 2nd row, I want the column called jam ke become like this :
1
-
2
3
4
5
6
7
8
My idea is I collect them to array :
[1,2,3,4,5,6,7,8,9]
if i selected index 1, then i'll replace 2 to "" so the values become :
[1,"",2,3,4,5,6,7,8] but I confused to replace and make it to sequence after "" << empty string
$(document).on('change','.jenis_mapel', function(event) {
event.preventDefault();
/* Act on the event */
var index = $(this).data('jam');//value of index row
var expect = 0;
for (var i = 0; i < arr.length; i++){
if (arr[i] == index)
{
expect = arr[i];
arr[i] = "";
}
else
{
var curr = arr[i];
arr[i] = expect;
}
}
console.log(arr);
});
Anyone can help me out ?
You could splice the array (Array#splice) and insert a value at a certain position.
This mutates the original array.
function add(array, index, value) {
array.splice(index, 0, value);
}
function remove(array, index) {
array.splice(index, 1);
}
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9];
add(array, 1, '-');
console.log(...array);
remove(array, 1);
console.log(...array);
Without using .indexOf, I'm trying to loop through an array from the end to find the last occurrence of a specific value. This is what I have so far but it keeps returning undefined.
var lastIndexOf = function (array, index) {
for (i=array.length-1; i < 0; i--) {
if (array[i] === index) {
return i;
}
}
}
console.log(lastIndexOf([ 0, 1, 4, 1, 2 ], 1); //should return 3
console.log(lastIndexOf([ 0, 1, 4, 1, 2 ], 2); //should return 4
Yor check is wrong, i is never smaller than zero for an index.
By the way, if you check against a value, you could use the name value instead of index, which leads to wrong assumptions and declare all variables in advance.
var lastIndexOf = function(array, value) {
var i;
for (i = array.length - 1; i >= 0; i--) {
if (array[i] === value) {
return i;
}
}
return -1; // standard default value for not found indices
};
console.log(lastIndexOf([0, 1, 4, 1, 2], 1)); // 3
console.log(lastIndexOf([0, 1, 4, 1, 2], 2)); // 4
console.log(lastIndexOf([0, 1, 4, 1, 2], 42)); // -1
A shorter approach with a while loop.
var lastIndexOf = function(array, value) {
var i = array.length
while (i--) {
if (array[i] === value) {
return i;
}
}
return -1;
};
console.log(lastIndexOf([0, 1, 4, 1, 2], 1)); // 3
console.log(lastIndexOf([0, 1, 4, 1, 2], 2)); // 4
console.log(lastIndexOf([0, 1, 4, 1, 2], 42)); // -1
Your loop condition is wrong. i will never be less than 0 unless the array is empty.
Use this instead:
(i=array.length-1; i >= 0; i--) {
You should change the check you make in the for statement. We start from the last index and we go down to the 0 index. So you loop while index >=0 and not when index<0.
I used different names for some parameters and arguments, in order to make the code more readable.
var lastIndexOf = function (array, number) {
for (var index = array.length-1; index>=0; index--) {
if (array[index] === number) {
return index;
}
}
};
console.log(lastIndexOf([ 0, 1, 4, 1, 2 ], 1)); //should return 3
I want to loop through an array and then add each value to each other (except itself + itself) and if the sum of the two values that were looped through equals the second argument in my function, and the pair of values hasn't been encountered before, then remember their indices and, at the end, return the full sum of all remembered indices.
In other words, the problem statement is: given an array A of integers and a second value s that is a desired sum, find all pairs of values from array A at indexes i, j such that i < j and A[i] + A[j] = s, and return the sum of all indexes of these pairs, with the following restriction:
don't reuse value pairs, i.e. if two index pairs i, j and k, l satisfying the above conditions are found and if A[i] == A[k] and A[j] == A[l] or A[i] == A[l] and A[j] == A[k], then ignore the pair with the higher index sum.
Example
For example, functionName([1, 4, 2, 3, 0, 5], 7) should return 11 because values 4, 2, 3 and 5 can be paired with each other to equal 7 and the 11 comes from adding the indices of them to get to 11 where:
4 + 3 = 7
5 + 2 = 7
4 [index: 1]
2 [index: 2]
3 [index: 3]
5 [index: 5]
1 + 2 + 3 + 5 = 11
Example #2
functionName([1, 3, 2, 4], 4) would only equal 1, because only the first two elements can be paired to equal 4, and the first element has an index of 0 and the second 1
1 + 3 = 4
1 [index: 0]
3 [index: 1]
0 + 1 = 1
This is what I have so far:
function functionName(arr, arg) {
var newArr = [];
for(var i = 0; i < arr.length; i++){
for(var j = i + 1; j < arr.length; j++) {
if((arr[i] + arr[j]) === arg ) {
newArr.push(i , j);
}
}
}
if(newArr.length === 0) {
return console.log(0);
}
return console.log(newArr.reduce(function(a,b){return a + b}));
}
functionName([1, 4, 2, 3, 0, 5], 7);
The problem I have is that it all works but I have the issue that once it finds a pair that equals the second argument, then it's not supposed to use the same value pairs again but mine does, e.g.:
if the array is [1,1,1] and the second argument is 2, the loop will go through and find the answer but it continues to search after it finds the sum and I only want it to use the pair [1, 1] once, so if it finds a pair like this at indexes [0, 1] then it should not include any other pair that contains the value 1.
I was thinking that i could remove the rest of the values that are the same if more than 2 are found using filter leaving me with only 2 of the same value if there is in an array thus not having to worry about the loop finding a 1 + 1 twice but is this the best way to go about doing it?
I'm still new to this but looking forward to your comments
PS I'm planning on doing this using pure JavaScript and no libraries
Link to a JS fiddle that might make things easier to see what I have.
https://jsfiddle.net/ToreanJoel/xmumv3qt/
This is more complicated than it initially looks. In fact, making a loop inside a loop causes the algorithm to have quadratic time complexity with regard to the size of the array. In other words, for large arrays of numbers, it will take a very long time to complete.
Another way to handle this problem is to notice that you actually have to use each unique value in the array only once (or twice, if s is even and you have two s/2 values somewhere in the array). Otherwise, you would have non-unique pairs. This works because if you need pairs of numbers x and y such that x + y = s, if you know x, then y is determined -- it must be equal s - x.
So you can actually solve the problem in linear time complexity (to be fair, it's sometimes n*log(n) if all values in A are unique, because we have to sort them once).
The steps of the algorithm are as follows:
Make a map whose keys are values in array A, and values are sorted lists of indexes these values appear at in A.
Move through all unique values in A (you collected them when you solved step 1) in ascending order. For each such value:
Assume it's the lower value of the searched pair of values.
Calculate the higher value (it's equal to s - lower)
Check if the higher value also existed in A (you're doing it in constant time thanks to the map created in step 1).
If it does, add the lowest indexes of both the lower and the higher value to the result.
Return the result.
Here's the full code:
function findSumOfUniquePairs(numbers, sum) {
// First, make a map from values to lists of indexes with this value:
var indexesByValue = {},
values = [];
numbers.forEach(function (value, index) {
var indexes = indexesByValue[value];
if (!indexes) {
indexes = indexesByValue[value] = [];
values.push(value);
}
indexes.push(index);
});
values.sort();
var result = 0;
for (var i = 0, maxI = values.length; i < maxI; ++i) {
var lowerValue = values[i],
higherValue = sum - lowerValue;
if (lowerValue > higherValue) {
// We don't have to check symmetrical situations, so let's quit early:
break;
}
var lowerValueIndexes = indexesByValue[lowerValue];
if (lowerValue === higherValue) {
if (lowerValueIndexes.length >= 2) {
result += lowerValueIndexes[0] + lowerValueIndexes[1];
}
} else {
var higherValueIndexes = indexesByValue[higherValue];
if (higherValueIndexes) {
result += lowerValueIndexes[0] + higherValueIndexes[0];
}
}
}
return result;
}
document.write(findSumOfUniquePairs([1, 4, 2, 3, 0, 5], 7) + '<br>'); // 11;
document.write(findSumOfUniquePairs([1, 3, 2, 4], 4) + '<br>'); // 1
document.write(findSumOfUniquePairs([1, 1, 1], 2) + '<br>'); // 1
document.write(findSumOfUniquePairs([1, 1, 1, 1], 2) + '<br>'); // 1
document.write(findSumOfUniquePairs([1, 2, 3, 1, 2, 3, 1], 4) + '<br>'); // 7
document.write(findSumOfUniquePairs([5, 5, 1, 1, 1], 6) + '<br>'); // 2
document.write(findSumOfUniquePairs([0, 5, 0, 5, 1, 1, 1], 6) + '<br>'); // 5
This works, but it mucks up the initial array.
function functionName(arr, arg) {
var newArr = [];
for(var i = 0; i < arr.length; i++){
for(var j = i + 1; j < arr.length; j++) {
if((arr[i] + arr[j]) === arg ) {
newArr.push(i , j);
arr[i] = null;
arr[j] = null;
}
}
}
if(newArr.length === 0) {
return console.log(0);
}
return console.log(newArr.reduce(function(a,b){return a + b}));
}
Solution with loops with restart, if a sum is found. the found summands are stored in usedNumbers and later sorted and used to get the index for summing the index.
The sorting and the last index provides the correct start position for the Array.prototype.indexOf.
Edit:
what about [1,1,1,1], 2 ... should that be 6 or 1? – Jaromanda X 21
#JaromandaX that should be 1, after the pair is found with the values then it shouldn't look for a pair with the same values again – Torean
This version takes care of the requirement.
function f(array, sum) {
var arrayCopy = array.slice(0),
usedNumbers = [],
index = 0,
indexA = 0,
indexB,
a, b;
while (indexA < arrayCopy.length) {
indexB = indexA + 1;
while (indexB < arrayCopy.length) {
a = arrayCopy[indexA];
b = arrayCopy[indexB];
if (a + b === sum) {
usedNumbers.push(a, b);
arrayCopy = arrayCopy.filter(function (i) { return a !== i && b !== i; });
indexA--; // correction to keep the index
break;
}
indexB++;
}
indexA++;
}
return usedNumbers.sort().reduce(function (r, a, i) {
index = array.indexOf(a, i === 0 || a !== usedNumbers[i - 1] ? 0 : index + 1);
return r + index;
}, 0);
}
document.write(f([1, 4, 2, 3, 0, 5], 7) + '<br>'); // 11
document.write(f([1, 1, 1], 2) + '<br>'); // 1
document.write(f([5, 5, 1, 1, 1], 6) + '<br>'); // 2
document.write(f([0, 5, 0, 5, 1, 1, 1], 6) + '<br>'); // 5
document.write(f([1, 1, 1, 1], 2) + '<br>'); // 1
The solution below is very compact. It avoids unnecessary checks and loops only through the relevant elements. You can check the working codepen here:
http://codepen.io/PiotrBerebecki/pen/RRGaBZ.
function pairwise(arr, arg) {
var sum = 0;
for (var i=0; i<arr.length-1; i++) {
for (var j=i+1; j<arr.length; j++) {
if (arr[i] <= arg && arr[j] <= arg && arr[i] + arr[j] == arg) {
sum += i+j;
arr[i] = arr[j] = NaN;
}
}
}
return sum;
}
console.log( pairwise([1, 1, 0, 2], 2) ) // should return 6
Under the hood:
Start looping from the element with index (i) = 0.
Add a second loop only for the elements which are later in the array. Their index j is always higher than i as we are adding 1 to i.
If both elements (numbers) are less than or equal to to the arg, check if their sum equals to the arg. This avoids checking the sum if either of the numbers are greater than the arg.
If the pair has been found then change their values to NaN to avoid further checks and duplication.
This solution should have a time complexity of 0(n) or linear
Much faster than two nested for-loops. This function will give you the two indices that add up to the target number. It can easily be modified to solve any other configuration of this problem.
var twoSum = function(nums, target) {
const hash = {}
for(let i = 0; i < nums.length; i++) {
hash[nums[i]] = i
}
for(let j = 0; j < nums.length; j++) {
let numToFind = target - nums[j]
if(numToFind in hash && hash[numToFind] !== j) {
return [hash[numToFind], j]
}
}
return false
};
console.log(twoSum([1,2,3,5,7], 5))
In Python:
def twoSum(self, nums: List[int], target: int) -> List[int]:
myMap = {}
for i in range(len(nums)):
myMap[nums[i]] = i
for j in range(len(nums)):
numToFind = target - nums[j]
if numToFind in myMap and myMap[numToFind] != j:
return [myMap[numToFind], j]
print(twoSum([1,2,3,5,7], 5))
In Java:
import java.util.*;
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for(Integer i = 0; i < nums.length; i++) {
map.put(nums[i], i);
}
for(Integer j = 0; j < nums.length; j++) {
Integer numToFind = target - nums[j];
Integer myInt = map.get(numToFind);
if(map.containsKey(numToFind) && myInt != j) {
return new int[] {myInt , j};
}
}
return new int[] {0, 0};
}
}
System.out.println(twoSum([1,2,3,5,7], 5))