Related
So... If I input:
4 1 5 3
INSTEAD OF 1,3,4,5
I GET [ 4, 1, 5, 3 ]
Following is the code for merge sort but for the last comparison the program doesn't fetch updated (1,4) (3,5) value rather (4,1) (5,3) thus giving the wrong result.
var a = [4, 1, 5, 3];
q(a);
function q(a) {
var start = 0;
var n = a.length;
var length = parseInt(n / 2);
if (n < 2) {
return n;
}
var l = [], r = [];
for (i = 0; i < length; i++) {
l[i] = a[i]; //left array
}
for (i = 0, j = length; j < n; i++ , j++) {
r[i] = a[j]; //right array
}
q(l); //merge sort left array
q(r); //merge sort right array
comp(l, r);
}
function comp(l, r) {
var k = [], m = 0, i = 0, j = 0;
while (i < ((l.length)) && j < ((r.length))) {
if (l[i] < r[j]) {
k[m] = l[i];
i++;
m++
}
else {
k[m] = r[j];
j++;
m++
}
}
while (i != (l.length)) {
k[m] = l[i];
m++;
i++;
}
while (j != (r.length)) {
k[m] = r[j];
m++;
j++;
}
console.log(k); //for final output it is [ 4, 1, 5, 3 ] instead of [1,3,4,5]
}
You have a couple small problems. The main one is that you are returning the wrong thing from your edge condition:
if (n < 2) {
return n; // n is just a length; doesn't make sense to return it.
}
n is the length, you really want to return the small array here:
if (n < 2) {
return a; // return the array instead
}
Also, you need to pass the result of the recursive call to your comp function. Right now you're just returning the original lists with:
comp(l, r)
Something like this would work better:
let l_sort = q(l); //merge sort left array
let r_sort = q(r); //merge sort right array
return comp(l_sort, r_sort); // merge the arrays when recursion unwinds.
And you need to return things for recursion to work.
Put all together:
function q(a) {
var start = 0;
var n = a.length;
var length = parseInt(n / 2);
if (n < 2) {
return a;
}
var l = [],
r = [];
for (i = 0; i < length; i++) {
l[i] = a[i]; //left array
}
for (i = 0, j = length; j < n; i++, j++) {
r[i] = a[j]; //right array
}
let l_sort = q(l); //merge sort left array
let r_sort = q(r); //merge sort right array
return comp(l_sort, r_sort);
}
function comp(l, r) {
var k = [],
m = 0,
i = 0,
j = 0;
while (i < ((l.length)) && j < ((r.length))) {
if (l[i] < r[j]) {
k[m] = l[i];
i++;
m++
} else {
k[m] = r[j];
j++;
m++
}
}
while (i != (l.length)) {
k[m] = l[i];
m++;
i++;
}
while (j != (r.length)) {
k[m] = r[j];
m++;
j++;
}
return k
}
console.log(q([4, 1, 5, 3]).join(','));
console.log(q([5, 4, 3, 2, 1]).join(','));
console.log(q([2, 3]).join(','));
console.log(q([3, 2]).join(','));
console.log(q([1]).join(','));
I am writing a function that will return the first n elements of an array and if n is undefined then return the first element.
*Edit: I solved the problem.
_.first = function(array, n) {
var result = [];
if (n == undefined) {
return array[0];
}
var m;
if (array.length < n) {
m = array.length;
} else {
m = n;
}
for (var i = 0; i < m; i++) {
result.push(array[i]);
} return result;
};
This program is basically checking if the n value is bigger than the array's length, if it is, then it exits.
If n is not a number it exits. If it is it executes the program and logs the values of indexes with for loop until i reaches the n value. Also, it pushes the values to the empty array, so you can get the values from the array for later use.
var arr1 = [2, 3, 4, 5, 6, 7, 8];
var arr2 = []; //empty array
function arrNreturn(arr, n){
if(typeof n != 'number'){
console.log('n is not a number');
return false; //exit the program
}
if(n > arr.length){
console.log("the n value is bigger than the length");
}else{
for(var i = 0; i < n; i++){
console.log(arr[n]);
arr2.push(arr[n]);
}
}
}
arrNreturn(arr1, 10);
1_.first = function(array, n) {
2 var result = [];
3 for (var i = 0; i < n; i++) {
4 result.push(array[i]);
5 return result;
6 } return array[0];
7};
the problem is on the 5th line, you seem to be returning the first and not taking into account the n parts
a solution might be
_first = function(array, n){
var result = [];
if(n === undefined) return array[0];
for (var i = 0; i < n; i++) {
result.push(array[i]);
}
return result;
}
Basic is
const newArr = function(arr) {return n }
Shorthand
const newArr = arr => { return n}
var array = [[2,3,4],[4,5,6],[2,3,9],[7,8,1]];
var number = 3;
If I have this nested array and this variable how do I return the index of the sub-arrays where the number is present. So the final result should be 1 and 3.
Try:
array.reduce((acc, subArr, i) => {
if (!subArr.includes(number)) {
acc.push(i);
}
return acc;
}, [])
The solution using Array.prototype.forEach() and Array.prototype.indexOf() functions:
var arr = [[2,3,4],[4,5,6],[2,3,9],[7,8,1]],
number = 3,
result = [];
arr.forEach(function(v,i){
if (v.indexOf(number) === -1) result.push(i);
});
console.log(result);
function X(a){
var r = [];
for(var i = o ; i < a.length; i++)
for(var j = o ; j < a[i].length; i++)
if(a[i][j] === number)
r.push(i);
return r;
}
i think this should do it. i have just written it here so might have some syntax errors
Since the question is super inconsistent, if you want the index of the subarrays that do have the number, do this:
var foundIndices = [];
for(var y = 0;y < array.length; y++) {
for(var x = 0;x < array[y].length; x++) {
if(array[y][x] == number) {
foundIndices[foundIndices.length] = y;
}
}
}
Otherwise, do this:
var foundIndices = [];
var found = false;
for(var y = 0;y < array.length; y++) {
found = false;
for(var x = 0;x < array[y].length; x++) {
if(array[y][x] == number) {
found = true;
}
}
if(found == false) {
foundIndices[foundIndices.length] = y;
}
}
How to write in javascript(w/wth JQuery) to find values that intersect between arrays?
It should be like
var a = [1,2,3]
var b = [2,4,5]
var c = [2,3,6]
and the intersect function should returns array with value {2}. If possible it could applicable for any number of arrays.
Thanks
There are many ways to achieve this.
Since you are using jQuery I will suggest use grep function to filter the value that are present in all three array.
var a = [1, 2, 3]
var b = [2, 4, 5]
var c = [2, 3, 6]
var result = $.grep(a, function(value, index) {
return b.indexOf(value) > -1 && c.indexOf(value) > -1;
})
console.log(result)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Explanation: Loop over any array and filter out the values that are present in other array.
Update (for multimidensional array):
Concept - flatten the multidimensional array that is transform [[1,2],3,4] to [1,2,3,4] and then use the same logic used for single dimensional array.
Example:
var a = [
[1, 4], 2, 3
]
var b = [2, 4, 5]
var c = [2, 3, 6, [4, 7]]
//flatten the array's
//[1,4,2,3]
var aFlattened = $.map(a, function(n) {
return n;
})
//[2,4,5]
var bFlattened = $.map(b, function(n) {
return n;
})
//[2,3,6,4,7]
var cFlattened = $.map(c, function(n) {
return n;
})
var result = $.grep(aFlattened, function(value) {
return (bFlattened.indexOf(value) > -1 && cFlattened.indexOf(value) > -1);
});
console.log(result);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
// First this is how you declare an array
var a = [1,2,3];
var b = [2,4,5];
var c = [2,3,6];
// Second, this function should handle undetermined number of parameters (so arguments should be used)
function intersect(){
var args = arguments;
// if no array is passed then return empty array
if(args.length == 0) return [];
// for optimisation lets find the smallest array
var imin = 0;
for(var i = 1; i < args.length; i++)
if(args[i].length < args[imin].length) imin = i;
var smallest = Array.prototype.splice.call(args, imin, 1)[0];
return smallest.reduce(function(a, e){
for(var i = 0; i < args.length; i++)
if(args[i].indexOf(e) == -1) return a;
a.push(e);
return a;
}, []);
}
console.log(intersect(a, b, c));
First of all '{}' means Object in JavaScript.
Here is my suggestion.(this is another way of doing it)
// declarations
var a = [1,2,3];
var b = [2,4,5];
var c = [2,3,6];
// filter property of array
a.filter(function(val) {
if (b.indexOf(val) > -1 && c.indexOf(val) > -1)
return val;
});
what it does is it checks for each element in array 'a' and checks if that value is present in array 'b' and array 'c'. If it is true it returns the value. Simple!!!. The above code should work for String as well but it wouldn't work for IE < 9, so be careful.
// Intersecting 2 ordered lists of length n and m is O(n+m)
// This can be sped up by skipping elements
// The stepsize is determined by the ratio of lengths of the lists
// The skipped elements need to be checked after skipping some elements:
// In the case of step size 2 : Check the previous element
// In case step size>2 : Binary search the previously skipped range
// This results in the best case complexity of O(n+n), if n<m
// or the more propable complexity of O(n+n+n*log2(m/n)), if n<m
function binarySearch(array, value, start = 0, end = array.length) {
var j = start,
length = end;
while (j < length) {
var i = (length + j - 1) >> 1; // move the pointer to
if (value > array[i])
j = i + 1;
else if (value < array[i])
length = i;
else
return i;
}
return -1;
}
function intersect2OrderedSets(a, b) {
var j = 0;
var k = 0;
var ratio = ~~(b.length / a.length) - 1 || 1;
var result = [];
var index;
switch (ratio) {
case 1:
while (j < a.length) {
if (a[j] === b[k]) {
result.push(a[j]);
j++;
k++;
} else if (a[j] < b[k]) {
while (a[j] < b[k]) j++;
} else {
while (b[k] < a[j]) k++;
if (k >= b.length) break;
}
}
break;
case 2:
while (j < a.length) {
if (a[j] === b[k]) {
result.push(a[j]);
j++;
k++;
} else if (a[j] < b[k]) {
while (a[j] < b[k]) j++;
} else {
while (b[k] < a[j]) k += 2;
if (k - 1 >= b.length) break;
if (a[j] <= b[k - 1]) k--;
}
}
break;
default:
while (j < a.length) {
if (a[j] === b[k]) {
result.push(a[j]);
j++;
k++;
} else if (a[j] < b[k]) {
while (a[j] < b[k]) j++;
} else {
while (b[k] < a[j]) k += ratio;
index = binarySearch(b, a[j], k - ratio + 1, k + 1 < b.length ? k + 1 : b.length - 1);
if (index > -1) {
result.push(a[j]);
j++;
k = index + 1;
} else {
j++;
k = k - ratio + 1;
}
if (k >= b.length) break;
}
}
}
return result;
}
function intersectOrderedSets() {
var shortest = 0;
for (var i = 1; i < arguments.length; i++)
if (arguments[i].length < arguments[shortest].length) shortest = i;
var result = arguments[shortest];
for (var i = 0, a, b, j, k, ratio, index; i < arguments.length; i++) {
if (result.length === 0) return result;
if (i === shortest) continue;
a = result;
b = arguments[i];
result = intersect2OrderedSets(a, b);
}
return result;
}
How to use:
intersectOrderedSets(a,b,c);
What is a fast and simple implementation of interleave:
console.log( interleave([1,2,3,4,5,6] ,2) ); // [1,4,2,5,3,6]
console.log( interleave([1,2,3,4,5,6,7,8] ,2) ); // [1,5,2,6,3,7,4,8]
console.log( interleave([1,2,3,4,5,6] ,3) ); // [1,3,5,2,4,6]
console.log( interleave([1,2,3,4,5,6,7,8,9],3) ); // [1,4,7,2,5,8,3,6,9]
This mimics taking the array and splitting it into n equal parts, and then shifting items off the front of each partial array in sequence. (n=2 simulates a perfect halving and single shuffle of a deck of cards.)
I don't much care exactly what happens when the number of items in the array is not evenly divisible by n. Reasonable answers might either interleave the leftovers, or even "punt" and throw them all onto the end.
function interleave( deck, step ) {
var copyDeck = deck.slice(),
stop = Math.floor(copyDeck.length/step),
newDeck = [];
for (var i=0; i<step; i++) {
for (var j=0; j<stop; j++) {
newDeck[i + (j*step)] = copyDeck.shift();
}
}
if(copyDeck.length>0) {
newDeck = newDeck.concat(copyDeck);
}
return newDeck;
}
It could be done with a counter instead of shift()
function interleave( deck, step ) {
var len = deck.length,
stop = Math.floor(len/step),
newDeck = [],
cnt=0;
for (var i=0; i<step; i++) {
for (var j=0; j<stop; j++) {
newDeck[i + (j*step)] = deck[cnt++];
}
}
if(cnt<len) {
newDeck = newDeck.concat(deck.slice(cnt,len));
}
return newDeck;
}
And instead of appending the extras to the end, we can use ceil and exit when we run out
function interleave( deck, step ) {
var copyDeck = deck.slice(),
stop = Math.ceil(copyDeck.length/step),
newDeck = [];
for (var i=0; i<step; i++) {
for (var j=0; j<stop && copyDeck.length>0; j++) {
newDeck[i + (j*step)] = copyDeck.shift();
}
}
return newDeck;
}
can i has prize? :-D
function interleave(a, n) {
var i, d = a.length + 1, r = [];
for (i = 0; i < a.length; i++) {
r[i] = a[Math.floor(i * d / n % a.length)];
}
return r;
}
according to my tests r.push(... is faster than r[i] = ... so do with that as you like..
note this only works consistently with sets perfectly divisible by n, here is the most optimized version i can come up with:
function interleave(a, n) {
var i, d = (a.length + 1) / n, r = [a[0]];
for (i = 1; i < a.length; i++) {
r.push(a[Math.floor(i * d) % a.length]);
}
return r;
}
O(n-1), can anyone come up with a log version? to the mathmobile! [spinning mathman logo]
Without for loops (I've added some checkup for the equal blocks):
function interleave(arr, blocks)
{
var len = arr.length / blocks, ret = [], i = 0;
if (len % 1 != 0) return false;
while(arr.length>0)
{
ret.push(arr.splice(i, 1)[0]);
i += (len-1);
if (i>arr.length-1) {i = 0; len--;}
}
return ret;
}
alert(interleave([1,2,3,4,5,6,7,8], 2));
And playground :) http://jsfiddle.net/7tC9F/
how about functional with recursion:
function interleave(a, n) {
function f(a1, d) {
var next = a1.length && f(a1.slice(d), d);
a1.length = Math.min(a1.length, d);
return function(a2) {
if (!a1.length) {
return false;
}
a2.push(a1.shift());
if (next) {
next(a2);
}
return true;
};
}
var r = [], x = f(a, Math.ceil(a.length / n));
while (x(r)) {}
return r;
}
Phrogz was pretty close, but it didn't interleave properly. This is based on that effort:
function interleave(items, parts) {
var len = items.length;
var step = len/parts | 0;
var result = [];
for (var i=0, j; i<step; ++i) {
j = i
while (j < len) {
result.push(items[j]);
j += step;
}
}
return result;
}
interleave([0,1,2,3], 2); // 0,2,1,3
interleave([0,1,2,3,4,5,6,7,8,9,10,11], 2) // 0,6,1,7,2,8,3,9,4,10,5,11
interleave([0,1,2,3,4,5,6,7,8,9,10,11], 3) // 0,4,8,1,5,9,2,6,10,3,7,11
interleave([0,1,2,3,4,5,6,7,8,9,10,11], 4) // 0,3,6,9,1,4,7,10,2,5,8,11
interleave([0,1,2,3,4,5,6,7,8,9,10,11], 5) // 0,2,4,6,8,10,1,3,5,7,9,11
Since I've been pushed to add my own answer early (edited to fix bugs noted by RobG):
function interleave(items,parts){
var stride = Math.ceil( items.length / parts ) || 1;
var result = [], len=items.length;
for (var i=0;i<stride;++i){
for (var j=i;j<len;j+=stride){
result.push(items[j]);
}
}
return result;
}
try this one:
function interleave(deck, base){
var subdecks = [];
for(count = 0; count < base; count++){
subdecks[count] = [];
}
for(var count = 0, subdeck = 0; count < deck.length; count++){
subdecks[subdeck].push(deck[count]);
subdeck = subdeck == base - 1? 0 : subdeck + 1;
}
var newDeck = [];
for(count = 0; count < base; count++){
newDeck = newDeck.concat(subdecks[count]);
}
return newDeck;
}