How to find the lowest and highest value couples in a sequence of number? I want to save the low/high values of a line graph.
Can you help me with a piece of pseudo code so people can implement the answer in their favorite prog language.
I will be using this to generate a line graph with D3.js. If anybody knows how to do this with D3 I would be more than happy to know about it.
Data Sample:
[20, 10, 11, 5, 15, 25, 10, 5, 15, 17, 26, 15, 7]
Desired Result:
array[0][high] = 20
array[0][low] = 5
array[1][high] = 25
array[1][low] = 5
array[2][high] = 26
array[2][low] = 7
This is what I have so far (in Javascript). Do you guys see anyway we can optimize this piece of code?
// data sample
var data_sample = Array(5, 15, 20, 15, 6, 11, 21, 14, 9, 4, 15, 20, 15, 1, 10, 20, 4);
// algo
var low = high = k = 0;
var log = [];
for (var i = 0; i < data_sample.length; i++) {
var current = data_sample[i];
var m = i+1;
var next = data_sample[m];
if (typeof next == 'undefined') {
break;
}
if (current < next) {
if (low === 0) {
low = current;
} else if (current < low) {
low = current;
}
} else if (current > next && low !== 0) {
if (high === 0) {
high = current;
} else if (current > high) {
high = current;
}
}
if (low > 0 && high > 0){
log[k] = [];
log[k]['low'] = low;
log[k]['high'] = high;
k++
low = high = 0;
}
};
Thank you in advance
Try this:
var arr = [20, 10, 11, 5, 15, 25, 10, 6, 15, 17, 26, 15, 7],
sorted = arr.sort(function(a,b){return a-b});
var array = [];
sorted.forEach(function(d,i){
var s = [];
s.push(sorted[i], sorted[(sorted.length-1) - i]);
array.push(s);
});
console.log(array);
Working fiddle here
The missing part of your code is how to store as array or object.
In your last if condition before you end the for loop you need to initialize log[k] as an object then add the property low and high like this
if (low > 0 && high > 0){
log[k] = {};
log[k].low = low;
log[k].high = high;
k++
low = high = 0;
}
Doing so will result is
array[0]{high: 20, low: 5}
array[1]{high: 25,low: 6}
If you want it to be an multidimensional array you do it like this:
Initialize log[k] as ab empty array.
if (low > 0 && high > 0){
log[k] = [];
log[k]['low'] = low;
log[k]['high'] = high;
k++
low = high = 0;
}
And the result
array[0]['high'] = 20
array[0]['low'] = 5
array[1]['high'] = 25
array[1]['low'] = 6
Related
I am trying to find out the minimum elements in array whose sum equals
the given input.I tried for few input sum but was able to find only a
pair in first case while I need to implement for more than just a pair.
var arr = [10, 0, -1, 20, 25, 30];
var sum = 45;
var newArr = [];
console.log('before sorting = ' + arr);
arr.sort(function(a, b) {
return a - b;
});
console.log('after sorting = ' + arr);
var l = 0;
var arrSize = arr.length - 1;
while (l < arrSize) {
if (arr[l] + arr[arrSize] === sum) {
var result = newArr.concat(arr[l], arr[arrSize]);
console.log(result);
break;
} else if (arr[l] + arr[arrSize] > sum) {
arrSize--;
} else {
l++;
}
}
Input Array : [10, 0, -1, 20, 25, 30]
Required Sum: 45
Output: [20, 25]
I am trying for
Required Sum : 59
Output: [10, -1, 20, 30]
This can be viewed as an optimization problem which lends itself well to dynamic programming.
This means you would break it up into a recursion that tries to find the minimum length of increasingly smaller arrays with the sum adjusted for what's been removed. If your array is [10, 0, -1, 20, 25, 30] with a sum of 59 you can think of shortest as the min of:
[10, ... shortest([ 0, -1, 20, 25, 30], 49)
[0, ... shortest([10, 20, 25, 30], 49), 59)
[-1, ... shortest([10, 0, 20, 25, 30], 60)
... continue recursively
with each recursion, the array gets shorter until you are left with one element. Then the question is whether that element equals the number left over after all the subtractions.
It's easier to show in code:
function findMinSum(arr, n){
if(!arr) return
let min
for (let i=0; i<arr.length; i++) {
/* if a number equals the sum, it's obviously
* the shortest set, just return it
*/
if (arr[i] == n) return [arr[i]]
/* recursively call on subset with
* sum adjusted for removed element
*/
let next = findMinSum(arr.slice(i+1), n-arr[i])
/* we only care about next if it's shorter then
* the shortest thing we've seen so far
*/
if (next){
if(min === undefined || next.length < min.length){
min = [arr[i], ...next]
}
}
}
return min && min /* if we found a match return it, otherwise return undefined */
}
console.log(findMinSum([10, 0, -1, 20, 25, 30], 59).join(', '))
console.log(findMinSum([10, 0, -1, 20, 25, 30], 29).join(', '))
console.log(findMinSum([10, 0, -1, 20, 25, 30], -5)) // undefined when no sum
This is still pretty computationally expensive but it should be much faster than finding all the subsets and sums.
One option is to find all possible subsets of the array, and then filter them by those which sum to the required value, and then identify the one(s) with the lowest length:
const getMinElementsWhichSum = (arr, target) => {
const subsets = getAllSubsetsOfArr(arr);
const subsetsWhichSumToTarget = subsets.filter(subset => subset.reduce((a, b) => a + b, 0) === target);
return subsetsWhichSumToTarget.reduce((a, b) => a.length < b.length ? a : b, { length: Infinity });
};
console.log(getMinElementsWhichSum([10, 0, -1, 20, 25, 30], 45));
console.log(getMinElementsWhichSum([10, 0, -1, 20, 25, 30], 59));
// https://stackoverflow.com/questions/5752002/find-all-possible-subset-combos-in-an-array
function getAllSubsetsOfArr(array) {
return new Array(1 << array.length).fill().map(
(e1,i) => array.filter((e2, j) => i & 1 << j));
}
Try this,
var arr = [10, 0, -1, 20, 25, 30];
var sum = 29;
var newArr = [];
var sum_expected = 0;
var y = 0;
while (y < arr.length) {
for (let i = 0; i < arr.length; i++) {
var subArr = [];
sum_expected = arr[i];
if (arr[i] != 0) subArr.push(arr[i]);
for (let j = 0; j < arr.length; j++) {
if (i == j)
continue;
sum_expected += arr[j];
if (arr[j] != 0) subArr.push(arr[j]);
if (sum_expected == sum) {
var result = arr.filter((el)=>(subArr.indexOf(el) > -1));
!newArr.length ? newArr = result : result.length < newArr.length ? newArr = result : 1;
break;
}
}
}
let x = arr.shift();
arr.push(x);
y++;
}
if (newArr.length) {
console.log(newArr);
} else {
console.log('Not found');
}
Complete JS newbie here!
I made an Array with a few numbers in it. I added a function that will show me the lowest number. My question can I show the index of the lowest number?(even If I would change the numbers)
Here is my code in case you need it:
function func()
{
var low= 0;
var numbersArr=[29, 26, 44, 80, 12, 15, 40];
for(var i = 0; i <= numbersArr.length;i++)
{
if(numbersArr[i]< numbersArr[i-1])
{
low = numbersArr[i];
}
}
console.log(low);
}
func();
You can also store value of i in one variable. See below code.
function func()
{
var numbersArr=[29, 26, 11, 44, 80, 12, 15, 40,10];
var low = numbersArr[0];
var indexOfLow;
for(var i = 0; i <= numbersArr.length;i++)
{
if(numbersArr[i]< low)
{
low = numbersArr[i];
indexOfLow = i;
}
}
console.log("Lowest number is : "+low);
console.log("Index of lowest number is : "+indexOfLow);
}
func();
My question can I show the index of the lowest number?
You can do
numbersArr.indexOf(low)
Edit
That said, your logic of finding the lowest number isn't correct as you are only comparing the consecutive values of the array, try the updated logic in demo below.
Demo
function func() {
var numbersArr = [29, 26, 11, 44, 80, 12, 15, 40];
var low = numbersArr[0];
for (var i = 1; i <= numbersArr.length; i++) {
if (numbersArr[i] < low ) {
low = numbersArr[i];
}
}
console.log(low);
console.log(numbersArr.indexOf(low));
}
func();
You function lack the problem of keeping the lowest value, because you compare only the actual element and the element before.
function getLowestValue(array) {
var low = 0,
i;
for (i = 0; i < array.length; i++) { // just loop i < array.length!
if (array[i] < array[i - 1]) {
// ^^^^^^^^^^^^ this is the problem, you need to check against low
low = array[i];
}
}
return low;
}
console.log(getLowestValue([29, 26, 11, 80, 12, 15, 40])); // 12 instead of 11
You could store the value of the lowest element and compare with this value.
function getLowestValue(array) {
var low = array[0], // take the first element at index 0
i;
for (i = 1; i < array.length; i++) { // start with index 1, because you need to
// check against the last known smallest value
if(array[i] < low) {
low = array[i];
}
}
return low;
}
console.log(getLowestValue([29, 26, 11, 80, 12, 15, 40])); // 11 the right value
For getting the lowest index, you could just store the index instead of th value and take it for comparison.
function getLowestIndex(array) {
var lowIndex = 0,
i;
for (i = 1; i < array.length; i++) {
if (array[i] < array[lowIndex]) {
lowIndex = i;
}
}
return lowIndex;
}
console.log(getLowestIndex([29, 26, 11, 80, 12, 15, 40])); // 2
No need to make a function to find minimum value. You can use simply Math.min.apply to find minimum value from array and then indexOf to find index of that value
var numbersArr = [29, 26, 44, 80, 12, 15, 40];
var minValue = Math.min.apply(null, numbersArr);
console.log("Minimum Value:"+ minValue, "Index is:" + numbersArr.indexOf(minValue));
Solution:You will declair a variable which will hold the index of low number and assign it in the if statement as shown below:
if(numbersArr[i]< numbersArr[i-1])
{
low = numbersArr[i];
IndexLow=i;
}
I found a super easy way to do that, in your way. Just little change in your code. Please take a look.
function func()
{
var numbersArr=[29, 31, 26, 44, 80, 123, 151, 40,15];
var low= numbersArr[0];
var index = 0;
for(var i = 1; i < numbersArr.length;i++)
{
if(low >= numbersArr[i])
{
low = numbersArr[i];
index = i;
}
}
console.log(index);
console.log(low);
}
func();
Hope you found your problem. Happy coding :)
I am looking for a better solution for getting minimum distance between 2 elements in an array.
Input: arr[] = {3, 5, 4, 2, 6, 5, 6, 6, 5, 4, 8, 3}, x = 3, y = 6
Output: Minimum distance between 3 and 6 is 4.
I have this Code in JS & it works fine for now.
I am looking for better code for achieving the same.
Thanks!!
<script>
var numbers= ["2", "3", "5","7","1","2","3","4","8"];
var x ="5";
var y ="8";
var firstIndex = numbers.indexOf(x);
var minD = numbers.length;
var x= numbers.forEach(function(item,index){
if((item == x) || (item == y))
{
if((index != firstIndex) && (index-firstIndex < minD))
{
minD = index-firstIndex;
firstIndex = index;
}
else
{
firstIndex = index;
}
}
});
alert(minD);
document.getElementById("demo").innerHTML = minD;
</script>
var xs=array.reduce((arr,el,i)=>(!(el===x)||arr.push(i),arr),[]);
var ys=array.reduce((arr,el,i)=>(!(el===y)||arr.push(i),arr),[]);
var lowest= xs.map(ix=>ys.map(iy=>Math.abs(iy-ix)).sort()[0]).sort()[0];
Im not sure if this is really shorter or better, just another approach...
Ive simply filtered out all x and y positions, then calculated the distance between each of them ( iy-ix) and took the smalles value (.sort()[0])
http://jsbin.com/nolohezape/edit?console
You could keep the indices and optimise the minimum value by testing if the actual difference is smaller.
function getMinDistance(array, left, right) {
var rightIndex, leftIndex, minDistance;
array.forEach(function (a, i) {
if (a === left && (leftIndex === undefined || leftIndex < i)) {
leftIndex = i;
}
if (a === right && leftIndex !== undefined) {
rightIndex = i;
}
if (leftIndex < rightIndex && (minDistance === undefined || minDistance > rightIndex - leftIndex)) {
minDistance = rightIndex - leftIndex;
}
});
return minDistance
}
console.log(getMinDistance(["2", "3", "5", "7", "1", "2", "3", "4", "8"], "5", "8"));
console.log(getMinDistance([3, 5, 4, 2, 6, 5, 6, 6, 5, 4, 8, 3], 3, 6));
function findMin(arr,a,b){
var firstIndex = arr.indexOf(a);
console.log(firstIndex);
var lastIndex = arr.indexOf(b);
console.log(lastIndex);
var minDistance;
if(firstIndex===lastIndex){
minDistance = 1;
}
if(firstIndex<lastIndex){
minDistance = lastIndex-firstIndex;
}
return minDistance;
}
console.log(findMin([1,2,3,4,5,6],1,5));
Assuming the array can be extremely large, I would rather not sort it before iterating, as it is not an efficient strategy.
The below logic scans the array from left-to-right, so in each iteration, the number marked with ๐ is checked against all proceeding numbers, until the best match is found, and then the same happens width the next number, until all possibilities have been calculated and the best (lowest) outcome is saved (minDis).
๐ - - - - - ๐ฅ
[50, 5, 75, 66, 32, 4, 58] // diff between 50 and each number past it (min is 8)
๐ - - - ๐ฅ -
[50, 5, 75, 66, 32, 4, 58] // diff between 5 and each number past it (min is 1)
๐ ๐ฅ - - -
[50, 5, 75, 66, 32, 4, 58] // diff between 75 and each number past it (min is 9)
...
On each iteration in the recursion the minDis parameter is sent to the deeper level so the local diff of that level (the for loop) is compared against that minDis argument, and if there's a smaller diff, it is then set as the "new" minDis value:
var data = [50, 5, 75, 66, 32, 4, 58]; // assume a very large array
// find the minimum distance between two numbers
function findMinDistance(arr, minDis = Infinity, idx = 0){
for( var numIdx = idx; numIdx < arr.length; numIdx++ ){
var diff = Math.abs(arr[idx] - arr[numIdx+1])
if( diff < minDis ) minDis = diff
// no need to continue scanning, since "0" is the minimum possible
if( minDis === 0 ) return 0
}
// scan from left to right, so each item is compared to the ones past it
return idx < arr.length - 1 && minDis > 0
? findMinDistance(arr, minDis, idx+1)
: minDis
}
console.log(`Min distance is: ${findMinDistance(data)}`)
A non-recursive approach, similar to the above:
var data = [50, 5, 75, 66, 32, 4, 58]; // assume a very large array
// find the minimum distance between two numbers
function findMinDistance(arr){
var minDis = Infinity, idx = 0, numIdx = idx
for( ; numIdx < arr.length; numIdx++ ){
var diff = Math.abs(arr[idx] - arr[numIdx+1])
// if result is lower than minDis, save new minDis
if( diff < minDis )
minDis = diff
// "0" is the minimum so no need to continue
if( minDis === 0 )
return 0
// go to the next number and compare it to all from its right
else if( numIdx == arr.length - 1 )
numIdx = ++idx
}
return minDis
}
console.log(`min distance is: ${findMinDistance(data)}`)
This is probably an odd question since I have a solution (below), but was hoping someone could show me a more succinct or readable way to do this:
I created a loop that outputs the following array:
[0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91]
the gaps between numbers get progressively larger:
1-0 = 1
3-1 = 2
6-3 = 3
10-6 = 4
...
91-78 = 13
etc.
I did it by creating two variables, step keeps track of the gap size and count keeps track of the current 'position' in the gap. count counts down to zero, then increases step by one.
var output = [];
var step = 0;
var count = 0;
for (var i = 0; i < 100; i++) {
if (count == 0){
step += 1;
count = step;
output.push(i);
}
count -= 1;
}
You can try the following:
var output = [];
var total = 0;
for (var i=1; i < 100; i++) {
output.push(total);
total += i;
}
The gaps between numbers simply increase by one for each step, so a for loop should be able to track this change.
You should skip useless iterations. If you want a sequence of 100 numbers, use
var output = [];
var step = 0;
for (var i = 0; i < 100; i++) {
step += i;
output.push(step);
}
If you want the general term,
aโ = โโฟแตขโโ i = n*(n+1)/2
So you can also do
var output = [];
for (var i = 0; i < 100; i++) {
output.push(i * (i+1) / 2);
}
You can save the total helper variable with this solution:
var output = [0]
for (var i = 1; i < 14; i++) {
output.push(output[i - 1] + i)
}
console.log(output) // [ 0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91 ]
This solution takes into account that the value to add the counter value to is already present at the last position in the array.
A recursive version is also possible:
output = (function f(x) {
return x.length == 14 ? x : f(x.concat([x[x.length - 1] + x.length]))
})([0])
console.log(output); // [ 0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91 ]
Here is no additional counter variable is needed. I use concat because it returns an array what I need for the recursive call, where push returns the new array length. The argument for concat is an array with one element with the new value to add.
Try online
my question is actually similar to: Extracting the most duplicate value from an array in JavaScript (with jQuery)
Solution (the one I found as the best, and slightly changed by me):
var arr = [3, 7, 7, 7, 7, 10, 10, 8, 5, 5, 5, 5, 20, 20, 1],
result = {},
max = 0,
res;
for( var i = 0, total = arr.length; i < total; ++i ) {
var val = arr[i],
inc = ( result[val] || 0 ) + 1;
result[val] = inc;
if( inc > max ) {
max = inc;
res = val;
}
}
alert(res);
I would like to add an extra which is : if we have, say two numbers with the same number of occurrences, how could we find the minimum of them (the above should alert 5 and not 7, which is the case)? The current solution works for getting only the first most duplicate found, but it does not deal with repetition.
Thanks!
Sort the array before you count the incidences:
var arr = [3, 7, 7, 7, 7, 10, 10, 8, 5, 5, 5, 5, 20, 20, 1];
function min_most_duplicate (arr) {
var result = {},
max = 0,
res;
arr = arr.slice(0); // make a copy of the array
arr.sort(function(a, b) { return (a - b); }); // sort it numerically
for( var i = 0, total = arr.length; i < total; ++i ) {
var val = arr[i],
inc = ( result[val] || 0 ) + 1;
result[val] = inc;
if( inc > max ) {
max = inc;
res = val;
}
}
return res;
}
min_most_duplicate(arr); // returns 5
This works because the way the for loop is written it's going to return the first one that it finds that has the most duplicates, so if the array is sorted, the smallest number will come first, so it'll be the one that the for loop finds.
This would work, example:
var arr = [3, 7, 7, 7, 7, 10, 10, 8, 5, 5, 5, 5, 20, 20, 1],
result = {},
max = 0,
res, key, min;
for (var i = 0, total = arr.length; i < total; ++i) {
var val = arr[i],
inc = (result[val] || 0) + 1;
result[val] = inc;
if (inc > max) {
max = inc;
res = val;
}
}
for (var i in result) {
if (result[i] === max) {
key = parseInt(i, 10);
min = min || key;
console.log(min)
if (min > key) {
min = key;
}
}
}
res = min;
alert(res);
let getMostDuplicated = array => {
let duplicated = '';
let max = 0;
for (let i = 0; i < array.length; i++) {
let counter = 0;
for (let j = 1; j < array.length - 1; j++) {
if (array[i] === array[j])
counter++;
}
if (counter > max) {
duplicated = array[i];
max = counter;
}
}
return duplicated;
};
let array = [3, 7, 7, 7, 7, 10, 10, 8, 5, 5, 5, 5, 20, 20, 1];
getMostDuplicated(array);