Trying to plan out a function and I wanted to get some input. I am trying to find an efficient way to:
Double the frequency of numbers in an array
Randomize the location of the values in the array.
For example: Lets say I have an array. [0,1,2,3]
first I want to duplicate each number once in a new array. So now we would have something like this.
[0,0,1,1,2,2,3,3].
Lastly, I want to randomize these values so: [0,4,2,3,0,2,3,4]
Eventually, the algorithm I write will need to handle an initial array of 18 digits (so the final, randomized array will be of size 36)
My initial thoughts are to just have a simple while loop that:
Randomly selects a spot in the new array
Checks to see if it is full
-If it is full, then it will select a new spot and check again.
If it is not full, then it will place the value in the new array, and go to the next value.
I am leaving out some details, etc. but I want this algorithm to be fairly quick so that the user doesn't notice anything.
My concern is that when there is only one digit left to be placed, the algorithm will take forever to place it because there will be a 1/36 chance that it will select the empty space.
In general terms, how can I make a smarter and faster algorithm to accomplish what I want to do?
Many thanks!
first I want to duplicate each number once in a new array. So now we would have something like this. [0,0,1,1,2,2,3,3].
That would be rather complicated to accomplish. Since the positions are not relevant anyway, just build [0,1,2,3,0,1,2,3] by
var newArray = arr.concat(arr);
Lastly, I want to randomize these values so: [0,4,2,3,0,2,3,4]
Just use one of the recognized shuffle algorithms - see How to randomize (shuffle) a JavaScript array?. There are rather simple ones that run in linear time and do not suffer from the problem you described, because they don't need to randomly try.
Here is an alternative to the known methods with two arrays, I came up with. It gives relatively good randomization.
var array1=[]
var array=[0,1,2,3,0,1,2,3]
a=array.length;
b=a;
c=b;
function rand(){for (i=0;i<c;i++){
n=Math.floor(Math.random()*b);
array1[i]=array[n]; array.splice(n,1);b--;}
for (i1=0;i1<c;i1++){array[i1]=array1[i1]}
Related
Let's say you want to search for a match between two arrays.
You could loop through both array and find a match. This is O(N*M) though.
I've found another option is to create a lookuplist.
How is it that using a lookuplist (simple Object mapping dictionary) is much faster to search for an element than using a search algorithm?
i.e.
const map {
hundreds of keys to hundreds of values
}
One can simply find the value of a foo key by doing the below
map['foo'] = bar.
As opposed to multiple loops or using something like _.filter or _.find
I understand that the map method would introduce more memory into the equation. But processing-wise it seems to scale nicely. What is it with hashes that make searching so fast? Isn't a full-scan of all keys still needed at the end of the day?
I have a website that will give you a random fact from Wikipedia when you click a big red button. I have heard from a few people that they are getting certain facts repeatedly, even though there are over 200.
The big red button has onclick="giveafact()" which triggers this function:
function giveafact(){ //instead of relisting all array items here, add all the other arrays to this one
var factsList= foodFactsList.concat(musicFactsList,historyFactsList,popFactsList,sportsFactsList,technologyFactsList,televisionFactsList,miscFactsList);
randomFact = Math.floor(Math.random()*factsList.length);
document.getElementById("total").innerHTML=factsList.length;
document.getElementById("fact").innerHTML=factsList[randomFact];
updateShareLinks();
return false;
}
Basically, I have 8 different arrays of facts as you can see in var factsList above. This is so the user can filter by fact. By default, there is no filter so all lists are concatenated.
If it helps, the full .js file is here: http://thewikifix.com/scripts/script.js. These random "give a fact" functions start at about line 442, with the arrays above them. (Pardon the messy code, I know I mix jQuery and Javascript a lot.)
The site is http://thewikifix.com, if it helps anyone to look at all the code.
I'm just trying to see if there's a way to better randomize the facts than I currently have, maybe by adding a function that won't allow a fact to show up twice in a row, or something similar.
Any suggestions would be great!
Edit - Additional thoughts: Thanks for the answers so far. Is there a way to remove an item from an array once it has been picked via the Math.random function so it just wouldn't show up again at all (unless the page was refreshed)? If so, once all items were removed from the array is there a way to reset the array to its original state without the user having to refresh? Thanks.
"Random" and "varied" are, to some extent, conflicting. With 200 facts, and one selected randomly each time, it becomes more likely than not that you'll see a repeat after getting only a couple dozen or so (this is known as the "Birthday Problem").
A simple approach is to store a seed and an index on the client. The seed is set once, and the index is incremented after each fact access. To get a "random" fact, seed a PRNG with the seed, use the PRNG to shuffle the list of facts, then get the fact at the given index in the shuffled list. When you run out, pick a new seed and reset the index.
Here's what I would do:
n = 0 - Find a random fact
add that fact to a new array (arr)
display fact
n + 1 - Find a random fact
check arr using lodash for that facts existence
display or find a new fact, based on result of above
--OR--
you could take the arr and use lodash's _.shuffle() to mix them up and display them in order.
https://lodash.com/docs
I love using lodash for collection and array operations.
I would like min() to choose the two smallest numbers in a list, is this possible and how should I do it?
actually, Math.min only gives you the single smallest of a list, so you need to simply sort them all and grab the quantity you need:
list = [7,4,5,4,2,23,4,6,4,6];
smalls = list.sort(function(a,b){return a-b}).slice(0,2);
alert(smalls); // shows "2, 4"
Sorting is a little inefficient as it takes up O(n log n) time. You could do the same thing with a single pass. Just keep to variables that are initialized to empty (or negative inifinity) or something.
For every element encountered, check against the two variables and update accordingly.
It is pretty simple but it takes up only linear time O(n).
Search for a documentation on "Math" (it is a javascript object with many useful math related functions and variables).
Hint.
So I have a Person object here with the following two attributes: firstname and mood. Assume the firstname attribute is unique.
If I have an array () of 3 Person objects (assume each line is a single person object):
Alison, Happy
Bob, Sad
Charles, Happy
If a have a second array for example of 3 people (from JSON array):
Alison, Sad
Bob, Happy
Jordan, Sad
I want the most efficient way to be able to iterate through the second array to update items in the first array. The way I think of it is with 2 for loops. So for example:
1st iteration, sees Alison, searches through first array for Alison, updates Alison to Sad. 2nd iteration, sees Bob, searches through...etc
3rd iteration, sees Jordan, searches through 1st array for Jordon, does not find... pushes new object onto array with Jordan, Sad.
Now I know that the array may not be the best way to do this, if there is a better way to accomplish this without the 1st array being an array.. could be a map, etc. What I care about is performance as the method i described is incredibly inefficient for many people for example if the arrays were of size 100.
Please help, would appreciate greatly.
This depends somewhat on your browser and library environment. There is Array.indexOf('value'), but that won't work in IE, and it's probably just doing a (optimized) loop behind the scenes anyway.
If you have a lot of data, and it's likely to be sorted, which doesn't seem to be the case for you, it's better to do a binary search. In other words, take the value from the middle of the data set and compare it to your query. If it's greater, your next query is the middle value of the first half of the set of values, and so on, until you get it.
Not necessarily a solution to the performance problem (though better than some) but a good alternative for this kind of work in terms of reduction of coding overhead is the underscore.js library. With underscore you could use _detect to fetch your value and then just use Array.push if not found.
If each person has a unique id or reference, you can put them in an object and use the id as a key, then do:
if (sadBob.id in personCollection) {
// sadBob is already there
personCollection.update(sadBob);
} else {
// add sadBob
personCollection.addPerson(sadBob);
}
Alternatively, you might add a property to the person objects in array2 that is their index in array1 when you create them. So if they don't have an index, they aren't in array1. If they have an index, you can go straight there (which is essentially the same as the above with an object and using the array index as the reference or id).
The following program (taken from a tutorial) prints the numbers in an array in order from lowest to highest. In this case, the result will be 2,4,5,13,31
My question relates to the paramaters "a" and "b" for the function compareNumbers. When the function is called in numArray.sort(compareNumbers) what numbers will be the parameters a and b for the function. Does it just move along the array. For example, start with a=13 and b=2? After that, does the function run again comparing a=2 and b=31? or would it next compare a=31 and b=4?
Can someone please explain how that part works and also how it manages to sort them from lowest to highest? I don`t see how the function manages to do the necessary calculations on the numbers in the array.
function compareNumbers(a,b) {
return a - b;
}
var numArray = [13,2,31,4,5];
alert(numArray.sort(compareNumbers));
The particular pairs that get passed in depend on the sorting algorithm being used. As the algorithm tries to go about sorting the range, it needs to be able to compare pairs of values to determine their ordering. Whenever this happens, it will call your function to get that comparison.
Because of this, without inside knowledge about how the sorting algorithm works, you cannot predict what pairs will get compared. The choice of algorithm will directly determine what elements get compared and in what order.
Interestingly, though, you can actually use the comparison function to visualize how the sort works or to reverse-engineer the sorting algorithm! The website sortviz.org has many visualizations of sorting algorithms generated by passing custom comparators into sorting functions that track the positions of each element. If you take a look, you can see how differently each algorithm moves its elements around.
Even more interestingly, you can use comparison functions as offensive weapons! Some sorting algorithms, namely quicksort, have particular inputs that can cause them to run much more slowly than usual. In "A Killer Adversary for Quicksort," the author details how to use a custom comparator to deliberate construct a bad input for a sorting algorithm.
Hope this helps!
The two parameters will be elements of your array. The system will compare enough pairs to be able to sort them correctly. Nothing else is guaranteed.
There are lots of things the sort method could be doing under the hood; see, e.g., http://en.wikipedia.org/wiki/Sorting_algorithm for some of them. Most Javascript implementations probably use some variant of either quicksort or mergesort.
(Here are super-brief descriptions of those. Quicksort is: pick an element in the array, rearrange the array to put everything smaller than that in front of everything larger, then sort the "smaller" and "larger" bits. Mergesort is: sort the first half of the array, sort the second half of the array, and then merge the two sorted halves. In both cases you need to sort smaller arrays, which you do with the same algorithm until you get to arrays so small that sorting them is trivial. In both cases, good practical implementations do all sorts of clever things I haven't mentioned.)
It will be called for all pairs of a,b that sorting algorithm need to get all array sorted. Check out http://en.wikipedia.org/wiki/Sorting_algorithm for brief list of sorting algorithms.
When you pass a function to Array.sort(), it expects two parameters and returns a numerical value.
If you return a negative value, the first parameter will be placed before the second parameter in the array.
If you return a positive value, the first parameter will be placed after the second parameter in the array.
If you return 0, they will stay in their current position.
By doing return a - b;, you are returning a negative number if a is less than b (2 - 13 = -11), a positive number if b is less than a (13 - 2 = 11), and zero if they are even (13 - 13 = 0).
As far as which numbers are compared in what order, I believe that is up to the javascript engine to determine.
Check out the documentation on javascript array sorting at the MDC Doc Center for more detailed information.
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/sort
(BTW, I always check the MDC Doc Center for any questions about how javascript works, they have the best information on the language AFAIK.)