I'm trying to implement a function which takes three arguments(min, max, step)and generates a range of integers from min to max, with the step. The first integer is the minimum value, the second is the maximum of the range and the third is the step.
Here is an example of what it should look like:
generateRange(2, 10, 2) should return array of [2,4,6,8,10].
I'm using the splice method to remove any existing elements in the array that are greater than the max argument.
function generateRange(min, max, step) {
var arr = [];
var count = min;
for (var i = 0; i < max / step; i++) {
arr[i] = count;
count = count + step;
arr[i] > max ? arr.splice(i, 1) : arr[i];
}
return arr;
}
console.log(generateRange(2, 10, 2));
Whenever I console.log my result I get a bunch of commas after the last item...so it looks like this: [2,4,6,8,10, , , , ]
It doesn't appear to be deleting the items. What am I missing? Thanks!
The ternary operator is a bit strange, as the expression is not stored. It fixes the array by removing too large values. That works once, but if there is a second time, i will have increased, and by the assignment to arr[i], the array's length is again as if there had been no splice performed before (except for the undefined value at that i-1 index).
It would be better to exit the loop before assigning a value that is outside of the range. There is no sense in continuing the loop in such a case.
So make the count variable your loop variable and condition:
function generateRange(min, max, step){
var arr = [];
for(var count = min; count <= max; count+=step){
arr.push(count);
}
return arr;
}
var res = generateRange(2, 10, 2);
console.log(res);
A less readable, but shorter ES6 version would be:
function generateRange(min, max, step){
return Array.from(Array(Math.floor((max-min)/step)+1), (x,i) => min+i*step);
}
let res = generateRange(2, 10, 2);
console.log(res);
Related
I think that my error is in the return section
I've tried many things but I can't find the solution
the question is : "Write a function called countNums that gets two arguments - an array of numbers and some member
And prints to the screen some organs in an array that are smaller than the given organ.
For the screen, countNums([7,3,9,1,20], 10) will be printed to read: for example
"4 elements are less than 10."
function countNums(arr, element) {
for (var i = 0; i < arr.length; i++) {
if (arr[i] < element) {
return " " + arr[i] + "elements are less than" + element + " ";
}
}
}
arr = [14, 25, 36, 50]
document.write(countNums(arr, 20));
Javascript has functions that can help you do this easily, such as array.filter which will return a subset of an array depending upon the condition.
However, I've presented an answer that uses the logic you outlined in your own attempt but modified in order to return the correct result.
The primary problem with your code was that you were not actually counting the number of elements below the target number - instead you returned when the first array element was below the target number.
I've fixed that by adding a count variable to keep a running count.
In the if statement, if the array element is lower than the number then count is incremented by one. At the end of the function, the total running count is returned.
Here's a working snippet showing this:
function countNums(arr, element)
{
let count = 0;
for (var i = 0; i < arr.length; i++) {
if (arr[i] < element)
count++;
}
return count;
}
let arr = [14,25,36,50]
let num = 20;
let result = countNums(arr, num);
document.write(result + " element(s) are less than " + num);
In the snippet above, you can modify num to specify the target number that the array elements must be lower than. The output statement will be modified automatically to show the correct wording.
It's a typical situation to use Array built-in method "reduce":
const array = [12, 6, 11, 4]
const count = (arr, num) => {
return `${arr.reduce(
(acc, val) => val < num
? acc + 1
: acc, 0
)} number(s) are less than ${num}`
}
console.log(count(array, 10))
I need to do something like this: Let's say I have an array:
[3, 4, 1, 2]
I need to swap 3 and 4, and 1 and 2, so my array looks like [4, 3, 2, 1]. Now, I can just do the sort(). Here I need to count how many iterations I need, to change the initial array to the final output. Example:
// I can sort one pair per iteration
let array = [3, 4, 1, 2, 5]
let counter = 0;
//swap 3 and 4
counter++;
// swap 1 and 2
counter++;
// 5 goes to first place
counter++
// now counter = 3 <-- what I need
EDIT: Here is what I tried. doesn't work always tho... it is from this question: Bubble sort algorithm JavaScript
let counter = 0;
let swapped;
do {
swapped = false;
for (var i = 0; i < array.length - 1; i++) {
if (array[i] < array[i + 1]) {
const temp = array[i];
array[i] = array[i + 1];
array[i + 1] = temp;
swapped = true;
counter++;
}
}
} while (swapped);
EDIT: It is not correct all the time because I can swap places from last to first, for example. Look at the example code above, it is edited now.
This is most optimal code I have tried so far, also the code is accepted as optimal
answer by hackerrank :
function minimumSwaps(arr) {
var arrLength = arr.length;
// create two new Arrays
// one record value and key separately
// second to keep visited node count (default set false to all)
var newArr = [];
var newArrVisited = [];
for (let i = 0; i < arrLength; i++) {
newArr[i]= [];
newArr[i].value = arr[i];
newArr[i].key = i;
newArrVisited[i] = false;
}
// sort new array by value
newArr.sort(function (a, b) {
return a.value - b.value;
})
var swp = 0;
for (let i = 0; i < arrLength; i++) {
// check if already visited or swapped
if (newArr[i].key == i || newArrVisited[i]) {
continue;
}
var cycle = 0;
var j = i;
while (!newArrVisited[j]) {
// mark as visited
newArrVisited[j] = true;
j = newArr[j].key; //assign next key
cycle++;
}
if (cycle > 0) {
swp += (cycle > 1) ? cycle - 1 : cycle;
}
}
return swp;
}
reference
//You are given an unordered array consisting of consecutive integers [1, 2, 3, ..., n] without any duplicates.
//still not the best
function minimumSwaps(arr) {
let count = 0;
for(let i =0; i< arr.length; i++){
if(arr[i]!=i+1){
let temp = arr[i];
arr[arr.indexOf(i+1)] =temp;
arr[i] = i+1;
count =count+1;
}
}
return count;
}
I assume there are two reasons you're wanting to measure how many iterations a sort takes. So I will supply you with some theory (if the mathematics is too dense, don't worry about it), then some practical application.
There are many sort algorithms, some of them have a predicable number of iterations based on the number of items you are sorting, some of them are luck of the draw simply based on the order of the items to be sorted and which item how you select what is called a pivot. So if optimisation is very important to you, then you'll want to select the right algorithm for the purpose of the sort algorithm. Otherwise go for a general purpose algorithm.
Here are most popular sorting algorithms for the purpose of learning, and each of them have least, worst and average running-cases. Heapsort, Radix and binary-sort are worth looking at if this is more than just an theoretical/learning exercise.
Quicksort
Worst Case: Θ(n 2)
Best case: Θ(n lg n)
Average case: Θ(n lg n)
Here is a Quicksort implementation by Charles Stover
Merge sort
Worst case: Θ(n lg n)
Best case: Θ(n lg n)
Average Case: Θ(n lg n)
(note they're all the same)
Here is a merge sort implementation by Alex Kondov
Insertion sort
Worst case: Θ(n2)
Best case: Θ(n)
Average case:Θ(n2)
(Note that its worst and average case are the same, but its best case is the best of any algorithm)
Here is an insertion sort implementation by Kyle Jensen
Selection sort
Worst case: Θ(n2)
Best case: Θ(n2)
Average case: Θ(n2)
(note they're all the same, like a merge sort).
Here is a selection sort algorithm written by #dbdavid updated by myself for ES6
You can quite easily add an iterator variable to any of these examples to count the number of swaps they make, and play around with them to see which algorithms work best in which circumstance.
If there's a very good chance the items will already be well sorted, insertion sort is your best choice. If you have absolutely no idea, of the four basic sorting algorithms quicksort is your best choice.
function minimumSwaps(arr) {
var counter = 0;
for (var i = arr.length; i > 0; i--) {
var minval = Math.min(...arr); console.log("before", arr);
var minIndex = arr.indexOf(minval);
if (minval != = arr[0]) {
var temp = arr[0];
arr[0] = arr[minIndex];
arr[minIndex] = temp; console.log("after", arr);
arr.splice(0, 1);
counter++;
}
else {
arr.splice(0, 1); console.log("in else case")
}
} return counter;
}
This is how I call my swap function:
minimumSwaps([3, 7, 6, 9, 1, 8, 4, 10, 2, 5]);
It works with Selection Sort. Logic is as follows:
Loop through the array length
Find the minimum element in the array and then swap with the First element in the array, if the 0th Index doesn't have the minimum value founded out.
Now remove the first element.
If step 2 is not present, remove the first element(which is the minimum value present already)
increase counter when we swap the values.
Return the counter value after the for Loop.
It works for all values.
However, it fails due to a timeout for values around 50,000.
The solution to this problem is not very intuitive unless you are already somewhat familiar with computer science or real math wiz, but it all comes down to the number of inversions and the resulting cycles
If you are new to computer science I recommend the following resources to supplement this solution:
GeeksforGeeks Article
Informal Proof Explanation
Graph Theory Explanation
If we define an inversion as:
arr[i]>arr[j]
where "i" is the current index and "j" is the following index --
if there are no inversions the array is already in order and requires no sorting.
For Example:
[1,2,3,4,5]
So the number of swaps is related to the number of inversions, but not directly because each inversion can lead to a series of swaps (as opposed to a singular swap EX: [3,1,2]).
So if one consider's the following array:
[4,5,2,1,3,6,10,9,7,8]
This array is composed of three cycles.
Cycle One- 4,1,3 (Two Swaps)
Cycle Two- 5,2 (One Swap)
Cycle Three- 6 (0 Swaps)
Cycle Four- 10,9,7,8 (3 Swaps)
Now here's where the CS and Math magic really kicks in: each cycle will only require one pass through to properly sort it, and this is always going to be true.
So another way to say this would be-- the minimum number of swaps to sort any cycle is the number of element in that cycle minus one, or more explicitly:
minimum swaps = (cycle length - 1)
So if we sum the minimum swaps from each cycle, that sum will equal the minimum number of swaps for the original array.
Here is my attempt to explain WHY this algorithm works:
If we consider that any sequential set of numbers is just a section of a number line, then any set starting at zero should be equal to its own index should the set be expressed as a Javascript array. This idea becomes the criteria to programmatically determined if in element is already in the correct position based on its own value.
If the current value is not equal to its own index then the program should detect a cycle start and recording its length. Once the while loop reaches the the original value in the cycle it will add the minimum number of swaps in the cycle to a counter variable.
Anyway here is my code-- it is very verbose but should work:
export const minimumSwaps = (arr) => {
//This function returns the lowest value
//from the provided array.
//If one subtracts this value the from
//any value in the array it should equal
//that value's index.
const shift = (function findLowest(arr){
let lowest=arr[0];
arr.forEach((val,i)=>{
if(val<lowest){
lowest=val;
}
})
return lowest;
})(arr);
//Declare a counter variable
//to keep track of the swaps.
let swaps = 0;
//This function returns an array equal
//in size to the original array provided.
//However, this array is composed of
//boolean values with a value of false.
const visited = (function boolArray(n){
const arr=[];
for(let i = 0; i<n;i++){
arr.push(false);
}
return arr;
})(arr.length);
//Iterate through each element of the
//of the provided array.
arr.forEach((val, i) => {
//If the current value being assessed minus
//the lowest value in the original array
//is not equal to the current loop index,
//or, if the corresponding index in
//the visited array is equal to true,
//then the value is already sorted
if (val - shift === i || visited[i]) return;
//Declare a counter variable to record
//cycle length.
let cycleLength = 0;
//Declare a variable for to use for the
//while loop below, one should start with
//the current loop index
let x = i;
//While the corresponding value in the
//corresponding index in the visited array
//is equal to false, then we
while (!visited[x]) {
//Set the value of the current
//corresponding index to true
visited[x] = true;
//Reset the x iteration variable to
//the next potential value in the cycle
x = arr[x] - shift;
//Add one to the cycle length variable
cycleLength++;
};
//Add the minimum number of swaps to
//the swaps counter variable, which
//is equal to the cycle length minus one
swaps += cycleLength - 1;
});
return swaps
}
This solution is simple and fast.
function minimumSwaps(arr) {
let minSwaps = 0;
for (let i = 0; i < arr.length; i++) {
// at this position what is the right number to be here
// for example at position 0 should be 1
// add 1 to i if array starts with 1 (1->n)
const right = i+1;
// is current position does not have the right number
if (arr[i] !== right) {
// find the index of the right number in the array
// only look from the current position up passing i to indexOf
const rightIdx = arr.indexOf(right, i);
// replace the other position with this position value
arr[rightIdx] = arr[i];
// replace this position with the right number
arr[i] = right;
// increment the swap count since a swap was done
++minSwaps;
}
}
return minSwaps;
}
Here is my solution, but it timeouts 3 test cases with very large inputs. With smaller inputs, it works and does not terminate due to timeout.
function minimumSwaps(arr) {
let swaps = 0;
for (let i = 0; i < arr.length; i++) {
if (arr[i] === i + 1) continue;
arr.splice(i, 1, arr.splice(arr.indexOf(i + 1), 1, arr[i])[0]); //swap
swaps++;
}
return swaps;
}
I'm learning how to make it more performant, any help is welcome.
This is my solution to the Main Swaps 2 problem in JavaScript. It passed all the test cases. I hope someone finds it useful.
//this function calls the mainSwaps function..
function minimumSwaps(arr){
let swaps = 0;
for (var i = 0; i < arr.length; i++){
var current = arr[i];
var targetIndex = i + 1;
if (current != targetIndex){
swaps += mainSwaps(arr, i);
}
}
return swaps;
}
//this function is called by the minimumSwaps function
function mainSwaps(arr, index){
let swapCount = 0;
let currentElement = arr[index];
let targetIndex = currentElement - 1;
let targetElement = arr[currentElement - 1];
while (currentElement != targetElement){
//swap the elements
arr[index] = targetElement;
arr[currentElement - 1] = currentElement;
//increase the swapcount
swapCount++;
//store the currentElement, targetElement with their new values..
currentElement = arr[index];
targetElement = arr[currentElement - 1];
}
return swapCount;
}
var myarray = [2,3,4,1,5];
var result = console.log(minimumSwaps(myarray));
you can also do it with a map. But its O(nlogn)
const minSwaps = (arr) =>{
let arrSorted = [...arr].sort((a,b)=>a-b);
let indexMap = new Map();
// fill the indexes
for(let i=0; i<arr.length; i++){
indexMap.set(arr[i],i);
}
let count = 0;
for(let i=0; i<arrSorted.length;i++){
if(arr[i] != arrSorted[i]){
count++;
// swap the index
let newIdx = indexMap.get(arrSorted[i]);
indexMap.set(arr[i],newIdx);
indexMap.set(arrSorted[i],i);
// sawp the values
[arr[i],arr[newIdx]] =[arr[newIdx],arr[i]];
}
}
return count;
}
What is wrong with this code?
function range(start, end){
var arrayRange = [];
for(i= start; i<=end; i++){
arrayRange.push(i)
}
return(arrayRange);
}
var r = range(1,10);
console.log(r);
function sumRange(sumArray){
var total = 0;
for(var i=0; i <= sumArray.length; i++){
total = total + sumArray[i];
}
return total;
}
var s=sumRange(r);
console.log(s);
This is what gets displayed in console.
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
NaN
I'm trying an exercise from Eloquent Javascript to understand callback function. My aim is to produce this
console.log(sum(range(1,10)));
// 55
The problem is i <= sumArray.length, the array indexes are from 0 to length -1 so the loop condition should be i < sumArray.length
In your case the last iteration of the loop will be total + undefined which will return NaN
function sumRange(sumArray) {
var total = 0;
for (var i = 0; i < sumArray.length; i++) {
total = total + sumArray[i];
}
return total;
}
You can use Array.reduce() like
function sumRange(sumArray) {
return sumArray.reduce(function (sum, val) {
return sum + val;
}, 0);
}
In this part of the sum function:
for(var i=0; i <= sumArray.length; i++){
total = total + sumArray[i];
}
Because your condition is i <= sumArray.length instead of i < sumArray.length, you try to access an array index that has not been set. When you do this, JavaScript will yield undefined as the value, and undefined when added to any number, will produce NaN.
The NaN value is basically JavaScript's way of letting you know that something went wrong in the calculations, without actually being helpful enough to tell you where it went wrong. Even strict mode will not modify this behavior, so you just have to be careful when you work with arrays to avoid accessing undefined keys. By the way, the same behavior exists when you try to access undefined object keys (In JavaScript, arrays are just special cases of objects).
Recall that JavaScript's arrays are zero-indexed, i.e. an array with n elements will have index keys 0..n-1, so you want to iterate up to the array's length non-inclusively using the condition
i < sumArray.length. As soon as this condition is false, you want to stop the iteration because you're in undefined territory.
I have javascript function that add numbers to array start form min to max and increase by step but when I use getNumbers(2, 20, 2); it print 2,22,222,2222,.... It doesn't increase can anyone help me please.
function getNumbers(min, max, step) {
var i;
for(i=min ; i<max ; i+=step){
array.push(i);
alert(array);
}
Nothing wrong with your function, you must pass numbers, if the passing parameters are string, change them to numbers as i did below:
var array = new Array();
function getNumbers (min, max, step) {
var i;
for(i=min ; i<max ; i+=step){
array.push(i);
alert(array);
}
}
//passing numbers:
getNumbers(1, 10, 2);
//output is 1,3,5,7,9
//if your numbers are strings, use:
var min = '1';
var max = '10';
var step = '2';
getNumbers(parseInt(min), parseInt(max), parseInt(step));
//this will work correctly
DEMO
Use parseInt to cast to integers
I see no problem with the function. Other than the array is not defined.
You're probably sending the variables in as a string, which causes concatenation instead of addition.
function getNumbers(min, max, step) {
var array = [];
for(var i = min ; i <= max ; i += step){
array.push(i);
}
return array;
}
You might also need to make sure that you use i <= max in your loop, if you want to include the max.
I have:
function getRandomInt(min, max){
return Math.floor(Math.random() * (max - min + 1)) + min;
}
But the problem is I want randomise the population of something with elements in an array (so they do not appear in the same order every time in the thing I am populating) so I need to ensure the number returned is unique compared to the other numbers so far.
So instead of:
for(var i = 0; i < myArray.length; i++) {
}
I have:
var i;
var count = 0;
while(count < myArray.length){
count++;
i = getRandomInt(0, myArray.length); // TODO ensure value is unique
// do stuff with myArray[i];
}
It looks like rather than independent uniform random numbers you rather want a random permutation of the set {1, 2, 3, ..., N}. I think there's a shuffle method for arrays that will do that for you.
As requested, here's the code example:
function shuffle(array) {
var top = array.length;
while (top--) {
var current = Math.floor(Math.random() * top);
var tmp = array[current];
array[current] = array[top - 1];
array[top - 1] = tmp;
}
return array;
}
Sometimes the best way to randomize something (say a card deck) is to not shuffle it before pulling it out, but to shuffle it as you pull it out.
Say you have:
var i,
endNum = 51,
array = new Array(52);
for(i = 0; i <= endNum; i++) {
array[i] = i;
}
Then you can write a function like this:
function drawNumber() {
// set index to draw from
var swap,
drawIndex = Math.floor(Math.random() * (endNum+ 1));
// swap the values at the drawn index and at the "end" of the deck
swap = array[drawIndex];
array[drawIndex] = array[endNum];
array[endNum] = swap;
endNum--;
}
Since I decrement the end counter the drawn items will be "discarded" at the end of the stack and the randomize function will only treat the items from 0 to end as viable.
This is a common pattern I've used, I may have adopted it into js incorrectly since the last time I used it was for writing a simple card game in c#. In fact I just looked at it and I had int ____ instead of var ____ lol
If i understand well, you want an array of integers but sorted randomly.
A way to do it is described here
First create a rand function :
function randOrd(){
return (Math.round(Math.random())-0.5); }
Then, randomize your array. The following example shows how:
anyArray = new Array('1','2','3','4','5');
anyArray.sort( randOrd );
document.write('Random : ' + anyArray + '<br />';);
Hope that will help,
Regards,
Max
You can pass in a function to the Array.Sort method. If this function returns a value that is randomly above or below zero then your array will be randomly sorted.
myarray.sort(function() {return 0.5 - Math.random()})
should do the trick for you without you having to worry about whether or not every random number is unique.
No loops and very simple.