Inefiecient code on loops. 10000000 loop challenge. - javascript

I don't know how to make my code more efficient. It completes the examples, but it will time out when it tackles the big array.
I ask you for some advice for performance on loops, or if you can tell me where my error is. If my approach is completely wrong don't give me the answer please.
What i have to do:
Given a list of integers and a single sum value, return the first two values (parse from the left please) in order of appearance that add up to form the sum.
Examples:
sum_pairs([11, 3, 7, 5], 10) => [3, 7]
sum_pairs([4, 3, 2, 3, 4], 6)=>[2, 4],[3, 3],[2, 4]
(indices:0,2|1,3|2,4)=>
entire pair is earlier, and therefore is the correct answer===[2, 4]
sum_pairs([0, 0, -2, 3], 2)
there are no pairs of values that can be added to produce 2.
== None/nil/undefined (Based on the language)
sum_pairs([10, 5, 2, 3, 7, 5],10)=>[5, 5][3, 7]
--------------------1------------5
--------------------------3--4
indicies:(1,5|3,4)
entire pair is earlier, and therefore is the correct answer
== [3, 7]
My attemt:
var sum_pairs=function(ints, s){
for(t=1; t <=ints.length-1;t++){
for(i=0; i <=ints.length-t-1;i++){
if(ints[i]+ints[i+t]===s){
return [ints[i],ints[i+t]];
}
}
}
}

Related

what to do? javascript array exercise

Find the correct passcode in the array and we'll do the rest. We can't disclose more information on this one, sorry.
Each entry in the first array represents a passcode
- Find the passcode that has no odd digits.
- For each passcode, show us the amount of even digits.
- If it has no odd digits, show us that you've found it and increase the number of terminals by one.
var passcodes = [
[1, 4, 4, 1],
[1, 2, 3, 1],
[2, 6, 0, 8],
[5, 5, 5, 5],
[4, 3, 4, 3],
];
so, i've tried almost everything i could think of. modulo, function, for loop and i can't seem to get it. i'm a beginner and this is an important exercise i have to do. but what do i do? it asks for the amount of even digits in each passcode, so i have to get the array within the array and then code something that i don't know to find even values. i'm stuck
Your question is not really suitable for StackOverflow, you should at least try to write something and see how far you get.
Anyhow, you seem to want to iterate over the elements in passcodes to find the array with no odd numbers.
The first task is to how to determine if a number is even. That is as simple as looking for the remainder from modulus 2. If the remainder is zero, then the number is even, otherwise it's odd.
So a simple test is:
var isEven;
if (x % 2 == 0) {
isEven = true;
} else {
isEven = false;
}
Since 0 type converts to false, and the not (!) operator reverses the truthiness of values and converts the result to boolean, the above can be written:
var isEven = !(x % 2);
There are many ways to iterate over an array, if your task was just to find the element with no odd numbers, I'd use Array.prototype.every, which returns as soon as the test returns false, or Array.prototype.some, which returns as soon as the test returns true.
However, in this case you want to count the number of even numbers in each element and find the first with all even numbers. One way is to iterate over the array and write out the number of even numbers in the element, and also note if its all even numbers. You haven't said what the output is expected to be, so I've just made a guess.
var passcodes = [
[1, 4, 4, 1],
[1, 2, 3, 1],
[2, 6, 0, 8],
[5, 5, 5, 5],
[4, 3, 4, 3], // this last comma affects the array length in some browsers, remove it
];
// Set flag for first element with all even numbers
var foundFirst = false;
// Iterate over each element in passcodes
passcodes.forEach(function(code) {
// Count of even numbers in current array
var evenCount = 0;
// Test each element of code array and increment count if even
code.forEach(function(num) {
if (!(num % 2)) ++evenCount;
});
// If all elements are even and haven't found first yet, write out elements
if (code.length == evenCount && !foundFirst) {
console.log('Passcode (first all even): ' + code.join());
// Set flag to remember have found first all even array
foundFirst = true;
}
// Write count of even numbers in this array
console.log('Even number count: ' + evenCount + ' of ' + code.length + ' numbers.');
});
I have no idea what you meant ...but it does all what i could understand from your question. Hope it will help :)
var passcodes = [
[1, 4, 4, 1],
[1, 2, 3, 1],
[2, 6, 0, 8],
[5, 5, 5, 5],
[4, 3, 4, 3],
];
var aPassCode;
while(aPassCode = passcodes.shift()){
for(var i=0,evenCount=0,totalCount=aPassCode.length;i<totalCount;i++){
if(aPassCode[i] % 2 == 0)evenCount++;
}
if(evenCount == totalCount){
console.log('all digits even here: ' + aPassCode.join(','));
}else{
console.log(aPassCode.join(',') + ' contains ' + evenCount + ' even digits.');
}
}

What is faster - merge 2 sorted arrays into a sorted array w/o duplicate values

I was trying to figure out which is the fastest way to do the following task:
Write a function that accepts two arrays as arguments - each of which is a sorted, strictly ascending array of integers, and returns a new strictly ascending array of integers which contains all values from both of the input arrays.
Eg. merging [1, 2, 3, 5, 7] and [1, 4, 6, 7, 8] should return [1, 2, 3, 4, 5, 6, 7, 8].
Since I don't have formal programming education, I fint algorithms and complexity a bit alien :) I've came with 2 solutions, but I'm not sure which one is faster.
solution 1 (it actually uses the first array instead of making a new one):
function mergeSortedArrays(a, b) {
for (let i = 0, bLen = b.length; i < bLen; i++) {
if (!a.includes(b[i])) {
a.push(b[i])
}
}
console.log(a.sort());
}
const foo = [1, 2, 3, 5, 7],
bar = [1, 4, 6, 7, 8];
mergeSortedArrays(foo, bar);
and solution 2:
function mergeSortedArrays(a, b) {
let mergedAndSorted = [];
while(a.length || b.length) {
if (typeof a[0] === 'undefined') {
mergedAndSorted.push(b[0]);
b.splice(0,1);
} else if (a[0] > b[0]) {
mergedAndSorted.push(b[0]);
b.splice(0,1);
} else if (a[0] < b[0]) {
mergedAndSorted.push(a[0]);
a.splice(0,1);
} else {
mergedAndSorted.push(a[0]);
a.splice(0,1);
b.splice(0,1);
}
}
console.log(mergedAndSorted);
}
const foo = [1, 2, 3, 5, 7],
bar = [1, 4, 6, 7, 8];
mergeSortedArrays(foo, bar);
Can someone help me with time complexity of both solutions? Also, is there another, faster solution? Should I be using reduce()?
Your first function modifying passed argument and this is bad practice.
You can do it in the following way:
function mergeSortedArrays(a, b) {
return a.concat(b.filter(el => !a.includes(el))).sort();
}
The complexity also depends on the methods that you use in your code.
1) An algorithm commonly used for sorting is Quicksort (introsort as a variation of quicksort).
It has O(n log n) complexity however the worst case may still be O(n^2) in case the input is already sorted. So your solution has O( length(b) + length(a)+length(b) log (length(a)+length(b)) ) runtime complexity.
2) According to this question on the complexity of splice() the javascript function needs O(n) steps at worst (copying all elements to the new array of size n+1). So your second solution takes length of array b multiplied by n steps needed to copy the elements during splice plus the time to push().
For a good solution that works in linear time O(n+m) refer to this Java example and port it (i.e. create an array of size length(a) + length(b) and step via the indeces as shown). Or check out the very tight and even a littler faster implementation below of the answer.

what does max() function do in javascript if array has several equally large numbers

If we get something like
array=[5,5,5,5,3,2];
return Math.max.Apply(Math,array);
How do I get it to return the numbers from first to last if such a case occurs.
To answer the question in the title:
what does max() function do in javascript if array has several equally
large numbers
The answer is, nothing. Math.max() doesn't act on arrays.
You can pass an array by spreading the items as arguments to max():
Math.max(...[1,2,3]) // 3
Or as you've seen, with apply():
Math.max.apply(Math, [1,2,3]) // 3
If the question is more:
What does Math.max() do when more than one of the same maximum number is given?
The answer is, it returns that number:
const a = [5, 5, 5, 5, 3, 2]
const max = Math.max(...a)
console.log(max) // 5
This question is confusing:
How do I get it to return the numbers from first to last if such a case occurs.
You want it to return a sorted array? From [5, 5, 5, 5, 3, 2] to [2, 3, 5, 5, 5, 5]?
a.sort() // [2, 3, 5, 5, 5, 5]
You want dupes removed? From [5, 5, 5, 5, 3, 2] to [2, 3, 5]?
Array.from(new Set(a)) // [2, 3, 5]
Could you clarify your question?
The best way to do this is the following:
var a = [5,5,5,5,3,2];
var largest = Math.max.apply(null,a)
var filtered = a.filter(function(item) {
item === largest
});
Where filtered will have contain all the largest elements.
In #Clarkie's example, he's calling Math.max more frequently than needed.
In both Dan and Clarkie's example they're capitalizing Apply which is incorrect, the correct function to call is Math.max.apply and Math need not be passed in as the first argument.
See the following for a working example:
https://jsfiddle.net/fx5ut2mm/
Modifying #Clarkie's very nice idea. We can boil it down to...
var a = [5,5,5,5,3,2],
m = Math.max(...a),
f = a.filter(e => e == m);
document.write("<pre>" + JSON.stringify(f) + "</pre>");

Javascript Sub-Array

I recently ran into the problem where I would like to select multiple elements from an array, to return a sub-array. For example, given the array:
a = [1, 5, 1, 6, 2, 3, 7, 8, 3]
And the index array of:
i = [3, 5, 6]
I want to select all elements in a, who's index appears in i. So the output in my simple example would be:
[6, 3, 7]
I completely realise I could use a for loop over i and construct a new array then use Array.push(a[index (in i)]) to add in each, but I was wondering if there was a clearer/cleaner way to achieve this (possibly using underscore.js, or something similar).
i.map(function(x) { return a[x]; })
// => [6, 3, 7]
You can try this
a = [1, 5, 1, 6, 2, 3, 7, 8, 3];
i = [3,5,6];
var res= []; //for show result array
for (var n in a){ //loop a[]
for(var index in i){ //loop i[]
if( n == i[index] ) //n is index of a[]
res.push(a[n]); //add array if equal n index and i[] value
}
}
alert(res); // 6,3,7
You could use map function to achieve your desired result.
var a = [1, 5, 1, 6, 2, 3, 7, 8, 3];
var i = [3, 5, 6];
var mapped = i.map(function(index) {
return a[index];
});
console.log(mapped);
Here is the working jsfiddle.
However with above example, map not be available in all browsers yet. Here is the quote from documentation of map.
map was added to the ECMA-262 standard in the 5th edition; as such it
may not be present in all implementations of the standard.
If your code will be running in old browsers then you will need to add a polyfill. However there are libraries that give you similar functionality with polyfills for older browsers. Along with map function, underscodejs has tons of other helpful functions. I higly recommend you to look at what underscorejs has to offer. It provides tons of helper functions and has quite wide range browser support.
You would do following in underscorejs and wont have to worry if your code works in cross browsers.
var a = [1, 5, 1, 6, 2, 3, 7, 8, 3];
var mapped = _.map([3, 5, 6], function(index) {
return a[index];
});
alert(mapped);
Here is jsfiddle for that.

Finding the lowest number in an array using split('') and reverse();

I am trying to find the min value of an array, and am trying to do it by sorting the array, and then reversing the array, and then calling the very first index of the array.
Unfortunately with what I have been trying, I keep getting 9. (don't know why) Can anybody take a quick look at what I have been doing and bail me out here? (i'm using js)
var minny = [4, 3, 5, 2, 6, 3, 4, 5, 2, 3, 4, 6, 7, 8, 9, 9, 1, 11, 25];
var smallest = function (minny){
minny = minny.sort('');
var sorted = minny + " ";
sorted = minny.reverse('').join('');
return sorted[0];
}
console.log(smallest(minny))
By default the sort method sorts elements alphabetically(11 comes before 9) and therefore you need to add a compare function as a param.
var smallest = function (minny) {
minny = minny.sort(function(a, b) { return a - b; });
return minny[0];
}
console.log(smallest(minny))
JSFIDDLE.
Based on your code, you could just do
return minny.sort()[0];
So, your full code example becomes
var minny = [4, 3, 5, 2, 6, 3, 4, 5, 2, 3, 4, 6, 7, 8, 9, 9, 1, 11, 25];
var smallest = function (minny){
return minny.sort()[0];
}
console.log(smallest(minny))
You're calling minny.sort('') which is using the default natural sort, so 11 and 25 end up near the beginning because of the 1 and 2.
What you have to do is call sort with a function that compares numbers, such as:
minny.sort(function(a,b) { return b-a; });
This will sort minny the way you want it.
There is no need to even call reverse and join afterwards, just return the first item. "return sorted[0]" is fine but will fail if there are no items, so you might just want to call "return sorted.shift()" instead. This will return the first item too, but won't fail if the array is empty.
PS. your call to minny.reverse also has an empty string as a parameter. That's not needed, reverse takes no parameters.
sort() sorts alphabetically by string representation, so in your case it would result in 1, 11, 2, 2, 25, .... You have to provide a comparison function for correct integer sorting, although in your specific case it doesn't really make a difference.
var smallest = function (minny){
minny = minny.sort(function(a, b){return a-b});
return minny[0];
}
See jsfiddle
Using sort is fairly short code to write, and it will return the correct number if you use minny.sort(function(a,b){return a-b})[0].
If you have a large unordered array you are running the comparison many times and you are sorting the array, which is not usually what you want to do to an array.
It may be better to just iterate the members and compare each just once to the lowest fond so far.
var minny= [4, 3, 5, 2, 6, 3, 4, 5, 2, 3, 4, 6, 7, 8, 9, 9, 1, 11, 25];
var smallest= function(minny){
var min= Infinity;
minny.forEach(function(next){
if(next<min) min= next;
});
return min;
}
Or use Math.min, if this is code golf:
Math.min.apply(Array,minny);

Categories

Resources