I have some code from someone but wondering why they might have used a function like this.
this.viewable= 45;
getGroups: function() {
return Math.ceil( this.getList().length / this.viewable );
}
Why would they divide the list length by a number viewable.
The result is the amount of items that should be rendered on the screen.
Why not just say 45 be the number. Is it meant to be a percentage of the list. Usually I will divide a large value by a smaller value to get the percentage.
Sorry if this seems like a stupid math question but my Math skills are crap :) And just trying to understand and learn some simple Math skills.
It's returning the number of groups (pages) that are required to display the list. The reason it's declared as a variable (vs. using the constant in the formula) is so that it can be modified easily in one place. And likely this is part of a plugin for which the view length can be modified from outside, so this declaration provides a handle to it, with 45 being the default.
That will give the number of pages required to view them all.
I would guess you can fit 45 items on a page and this is calculating the number of pages.
Or something similar to that?
This would return the total number of pages.
Total items = 100 (for example)
Viewable = 45
100 / 45 = 2.22222....
Math.ceil(2.2222) = 3
Therefore 3 pages
judging by the function name "getGroups", viewable is the capacity to show items (probably some interface list size).
By doing that division we know how many pages the data is to be divided (grouped) in order to be viewed on the interface. The ceil functions guarantees that we don't left out partial pages, if we had come records left that don't fill a complete page, we still want to show them and therefor make them count for a page.
Related
I am trying to understand how to approach math problems such as the following excerpt, which was demonstrated in a pagination section of a tutorial I was following.
const renderResults = (arrayOfItems, pageNum = 1, resultsPerPage = 10) => {
const start = (pageNum - 1) * resultsPerPage;
const end = pageNum * resultsPerPage;
arrayOfItems.splice(start, end).forEach(renderToScreenFunction);
};
In the tutorial this solution was just typed out and not explained, which got me thinking, had I not seen the solution, I would not have been able to think of it in such a way.
I understood the goal of the problem, and how splice works to break the array into parts. But it was not obvious to me how to obtain the start and end values for using the splice method on an array of of indefinite length. How should have I gone about thinking to solve this problem?
Please understand, I am learning programming in my spare time and what might seem simple to most, I have always been afraid and struggle with math and I am posting this question in hopes to get better.
I would really appreciate if anyone could explain how does one go about solving such problems in theory. And what area of mathematics/programming should I study to get better at such problems. Any pointers would be a huge help. Many thanks.
OK, so what you're starting with is
a list of things to display that's, well, it's as long as it is.
a page number, such that the first page is page 1
a page size (number of items per page)
So to know which elements in the list to show, you need to think about what the page number and page size say about how many elements you have to skip. If you're on page 1, you don't need to skip any elements. What if you're on page 5?
Well, the first page skips nothing. The second page will have to skip the number of elements per page. The third page will have to skip twice the number of elements per page, and so on. We can generalize that and see that for page p, you need to skip p - 1 times the number of elements per page. Thus for page 5 you need to skip 4 times the number of elements per page.
To show that page after skipping over the previous pages is easy: just show the next elements-per-page elements.
Note that there are two details that the code you posted does not appear to address. These details are:
What if the actual length of the list is not evenly divisible by the page size?
What if a page far beyond the actual length of the list is requested?
For the first detail, you just need to test for that situation after you've figured out how far to skip forward.
Your function has an error, in the Splice method
arrayOfItems.splice(start, end).forEach(renderToScreenFunction);
The second argument must be the length to extract, not the final
index. You don't need to calculate the end index, but use the
resultsPerPage instead.
I've rewrite the code without errors, removing the function wrapper for better understanding, and adding some comments...
// set the initial variables
const arrayOfItems =['a','b','c','d','e','f','g','h','i','j','k','l','m'];
const pageNum = 2;
const resultsPerPage = 5;
// calculate start index
const start = (pageNum - 1) * resultsPerPage; // (2-1)*5=5
// generate a new array with elements from arrayOfItems from index 5 to 10
const itemsToShow = arrayOfItems.splice(start, resultsPerPage) ;
// done! output the results iterating the resulting array
itemsToShow.forEach( x=> console.log(x) )
Code explanation :
Sets the initial parameters
Calculate the start index of the array, corresponding to the page you try to get. ( (pageNum - 1) * resultsPerPage )
Generates a new array, extracting resultsPerPage items from arrayOfItems , starting in the start index (empty array is returned if the page does not exist)
Iterates the generated array (itemsToShow) to output the results.
The best way to understand code, is sometimes try to run it and observe the behavior and results.
I'm trying to add a clearance calculation on a pathfinding script (javascript).
I really don't know how to achieve this programmatically...
I'm using an AStar script, so I have a double-dimensionnal array with tiles like this :
[
[0,0,0,0,0,1],
[0,1,0,1,1,1],
[0,1,1,1,0,1],
[1,1,1,0,0,1],
[1,1,0,1,0,1],
[1,0,0,0,0,1]
]
Here, 0 means "wall", and 1 means "path".
1 is the default clearance.
How to loop over each tile (calculation from top-left to bottom-right) to have the max clearance of it, like in this scheme :
https://aigamedev.com/open/tutorials/clearance-based-pathfinding/#TheTrueClearanceMetric
The only problem is the "loop-format", where I need to test if the current tile is 0 or 1, to store the max clearance
Many thanks !
EDIT
For those who can't see the website, some schemes of what I mean :
Steps to calcul clearance
Example of a full result
You will still need the outer set of nested for loops to go through each square as in your jsfiddle.net/uctsf755 code but within each square you want to do Breadth First Search to locate the closest wall. once you find one you can actually update all the squares you have looked at along the way, since the closest wall to those square will be the same wall. Remember which ones you have visited so you don't have to do bfs on them again.
Total complexity will be around O(n^2) since you should only visit each square once.
Good Luck!
I need to calculate the percentile rank of a particular value against a large number of values filtered in various different ways. The data is all stored on Parse.com, which has a limitation of returning a maximum of 1000 rows per query. The number of values stored is likely to exceed well over 100,000.
By 'percentile rank', I mean I need to calculate the percentage of values that the provided value is greater than. I am not trying to calculate the value of a provided percentile. For example, given a list of values {20, 23, 24, 29, 30, 31, 35, 40, 40, 43} the percentile rank of the provided value 35 is 70%. The algorithm for this is simply the rank of the value / count of values * 100. Not sure if 'percentile rank' is the correct terminology for this.
I have considered a couple of different approaches to this. The first is to pull down the full list of values (into Parse Cloud) and then calculate the percentile rank from there, then filter the list and calculate again, repeating the last two steps as many times as required. The problem with this approach is it will not work once we reach 1000 values, which we can expect pretty quickly.
Another option, which is the best I can come up with so far, is to query the count of items, and the rank of the provided value. For example:
var rank_world_alltime = new Parse.Query("Values")
.lessThan("value", request.params.value) // Filters query to values less than the provided value, so counting this query will return the rank
.count();
var count_world_alltime = new Parse.Query("Values")
.count();
Parse.Promise.when(rank_world_alltime, count_world_alltime).then(function(rank, count) {
percentile = rank / count * 100;
console.log("world_alltime_percentile = " + percentile);
});
This works well for a single calculation, but I need to perform multiple calculations, and this approach very quickly becomes a lot of queries. I expect to need to run about 15 calculations per call, which is 30 queries. All calculations need to complete in under 3 seconds before Parse terminates the job, and I am limited to 30 reqs/second, so this is very quickly going to become a problem.
Does anyone have any suggestions on how else I could approach this? I've thought about somehow pre-processing some of this but can't quite work out how to do so, as the filters will be based on time and location (city and country), so there are potentially a LOT of pre-calculations that will need to be run at regular intervals. The results do not need to be 100% accurate but something close.
I don't know much about parse, but as far as I understand what you say, it is some kind of cloud database thingy that holds your hiscores, and limits you 1000 rows per query, 3 seconds per job, and 30 queries per second.
In order to have approximate calculations and divide by 2 the number of queries, I would first of all cache the total (count_world_alltime, count_region,week, whatever). If you can save them somewhere locally. For numbers of 100K just getting the order of magnitude (thus not the latest updated number) should be good enough to get a percentile.
Maybe you can get several counts per query. However my lack of expertise in parse/nosql kind of stops me from being sure of this, you'll have to check their documentation. If it is possible however, for the case where you need percentiles for a serie of values all in the same category, I would
Order the values, let's call them a,b,c,d,e (once ordered)
Get the number of values between the intervals [0,a] [a,b] [b,c] [c,d] [d,e]
Use the cached total to get the percentiles (where Nxy is the number of values in [x,y]) :
Pa = 100 * N0a / total
Pb = 100 * ( N0a + Nab ) / total
Pc = 100 * ( N0a + Nab + Nbc ) / total
and so on...
If you need a value ranked worldwide, the other per region, some per week others over all times, etc, this doesn't apply. In that case I don't think you can get below 1 query/number, with caching the totals.
I'm tried to make some world generation mechanism using Math.random() whenever I needed something random, but then decided that I wanted it seed-based, so, given a seed, I changed all of the Math.random() to Math.sin(seed++)/2+0.5, hoping it would do the same thing, but would be the same if the seed was the same seed.
Then someone made me notice that the sin wave hasn't got even distribution, and finally I saw why some of my code was working strangely.
I was wondering if there was a simple fix, or if there isn't, another very simple seed based randomizer like this
So, I looked at your method, t1wc, and I found that it isn't actually evenly distributed. It is significantly more likely to spit out numbers near 0 or near 1 than it is to spit out numbers near 0.5, for example. This is just a consequence of the way that the sine function works.
Instead, you might try using a method called Blum Blum Shub (named after the authors of the original paper, wonderfully). It is evenly distributed and quite fast. Given a seed, it works as follows:
Square the seed and put the result in a temporary variable (x).
Take the mod of x base M.
M is a product of two large primes.
The value of x is a new seed to be used for future calculations.
Return x/M as your pseudo-random number. It will be evenly distributed between 0 and 1.
Below is a simple implementation of a Blum Blum Shub:
var SeededRand = function(seed, mod1, mod2)
{
return function()
{
seed = (seed*seed) % (mod1*mod2);
return seed/(mod1*mod2);
};
};
If you want to make a new random number generator, you just call:
var rand = SeededRand(seed, mod1, mod2);
Where seed is some initial seed (1234567890 works well), and mod1 and mod2 are some large primes (7247 and 7823 work well). rand is just a variable that I've defined to hold the output.
Now, to start getting random values, you just call:
rand();
Which will spit out a different value each time you run it.
If you have any questions, please ask!
There is a very nice seed-based randomizing script already made. It can be found here.
ok guys, found out this is what I'm really looking for:
(((Math.sin(seed.value++)/2+0.5)*10000)%100)/100
It sends out even spreaded numbers, and I guess it's a lot simpler than any other number generator I've seen
Is this correct? using - http://en.wikipedia.org/wiki/Binomial_probability
Looks like values are from .0000000000000000 to .9999999999999999
Probability of happening twice = p^2 = (1/9999999999999999)^2 = 1.0 e-32
I think I am missing something here?
Also, how does being a pseudo random number generator change this calculation?
Thank You.
In an ideal world Math.random() would be absolutely random, with one output being completely independent from another, which (assuming p=the probability of any given number being produced) results in a probably of p^2 for any value being repeated immediately after another (as others have already said).
In practice people want Math.random to be fast which means pseudo-random number generators are used by the engines. There are many different kinds of PRNG but the most basic is a linear congruential generator, which is basically a function along the lines of:
s(n + 1) = some_prime * s(n) + some_value mod some_other_prime
If such a generator is used then you won't see a value repeated until you've called random() some_other_prime times. You're guaranteed of that.
Relatively recently however it's become apparent that this kind of behaviour (coupled with seeding the PRNGs with the current time) could be used for some forms tracking have led to browsers doing a number of things that mean you can't assume anything about subsequent random() calls.
I think the probability of getting two numbers in a row is 1 divided by the range of the generator, assuming that it has a good distribution.
The reason for this is that the first number can be anything, and the second number needs to just be that number again, which means we don't care about the first number at all. The probability of getting the same number twice in a row is the same as the probability of getting any particular number once.
Getting some particular number twice in a row, e.g. two 0.5s in a row, would be p^2; however, if you just care about any number twice in a row, it's just p.
If the numbers were truly random, you'd expect them, indeed, to appear with probability 1/p, so twice that would be 1/p^2.
The value for p is not exactly the one you have though, because the numbers are being represented internally as binary. Figure out how many bits of mantissa the numbers have in javascript and use that for your combinatoric count.
The "pseudorandom" part is more interesting, because the properties of pseudorandom number generators vary. Knuth does some lovely work with that in Seminumerical Algorithms, but basically most usual PN generators have at least some spectral distributiuon. Cryptograp0hic PN generators are generally stronger.
Update: The amount of time shouldn't be significant. Whether it's a millisecond or a year, as long as you don't update the state The probabilities will stay the same.
The probability that you would get 2 given numbers is (1/p)^2, but the probability that you get 2 of same numbers (any) is 1/p. That is because the first number can be anything, and the second just needs to match that.
You can kind of find out, just let it run a few days :)
var last = 0.1;
var count = 0 | 0;
function rand(){
++count;
var num = Math.random();
if(num === last){
console.log('count: '+count+' num: '+num);
}
last = num;
}
while(true) rand();