php calculation solution for pagination - php

I have a variable $total which is the total number of results and $page which is the page number. The result is limited to 12 per page.
Suppose if $total is 24, the script may return 1 and 2 for $page=1 and $page=2 respectively. It should also return 1 if the input number is less than 1 (negative or zero) or if the number is greater than 2
Again, suppose if $total is 25, the script may return 1, 2 and 3 for $page=1, $page=2 and $page=3 respectively. It should also return 1 if the input number is less than 1 (negative or zero) or if the number is greater than 1

Here's one way to calculate it:
// Assuming you have the $total variable which contains the total
// number of records
$recordsPerPage = 12;
// Declare a variable which will hold the number of pages required to
// display all the records, when displaying #recordsPerPage records on each page
$maxPages = 1;
if($total > 0)
$maxPages = (($total - 1) / $recordsPerPage) + 1;
// $maxPages now contains the number of pages required. you can do whatever
// it is you need to do with it. It wasn't clear from the question..
return $maxPages;
Further, if you wanted to generate an array containing the indexes of each available page you could just do this:
$pages = array();
for($i = 1; $i <= $maxPages; i++)
{
array_push($pages, $i);
}
print_r($pages);

Related

PHP: How to check if a number is between collection of two numbers

i have a code like this
$count=15; // i manually initialising a value that not satisfying by folling condition
$low_limit=0;
$up_limit=10;
$num_pages=0;
(some loop) {
if (($count >= $low_limit) && ($count <= $up_limit))
{
$num_pages=$numpages+1;
echo $num_pages;
}
$low_limit=$up_limit+1;
$up_limit=$up_limit+10;
} // loop ends
my logic was
$count is a variable // this value can be frequently changed
$low_limit and $up_limit are value ranges // 0-10 , 10-20 , 20-30 ,etc
$num_pages is a variable that return
1 if $low_limit= 0 and $up_limit= 10
2 if $low_limit= 11 and $up_limit= 20
3 if $low_limit= 21 and $up_limit= 30 and so on
here the $low_limit and $up_limit can be any number (but multiple of 10). it may be upto 50,000.
what will be in some loop .?
How i construct this program, i searched a lot, but i only find programs which checks a number between a range.
Any help would be greately appreciated.
Due to comments above, it should works as expected:
$count = 34; // any number
$per_page = 10; // it's fixed number, but...
$num_page = ceil($count / $per_page); // returns 4
$low_limit = ($num_page - 1) * $per_page; // returns 30
$up_limit = $num_page * $per_page; // returns 40
Between record number 30 and record number 40 are 11 records, not 10.
There are more ways how to fix that:
1. compare < ... <=: $low_limit < $count <= $up_limit
2. compare <= ... <: $low_limit <= $count < $up_limit
3. set limits 1-10, 11-20, 21-30, etc. (simply +1 to $low_limit on 4th line above)
4. set limits 0-9, 10-19, 20-29, etc. (simply -1 to $up_limit on 5th line above)

How can I add a random number to each item in foreach loop but to stay the same for 1 day

I'm trying to assign a different random number on each item in a foreach loop but I'd like the number to stay the same for one day.
I've tried simply adding <?php echo rand(0,20); ?> but this obviously just creates a random number per each refresh.
Is there anyway I could keep the same random number per each item for one day without adding it to the database.
for example:
item 1 = 2
item 2 = 18
item 3 = 13
item 4 = 6
Stays the same for 1 day then changes
You can do this by programming your own random number generator. This guide shows you how to do it.
Note: Code below from sitepoint
class Random {
// random seed
private static $RSeed = 0;
// set seed
public static function seed($s = 0) {
self::$RSeed = abs(intval($s)) % 9999999 + 1;
self::num();
}
// generate random number
public static function num($min = 0, $max = 9999999) {
if (self::$RSeed == 0) self::seed(mt_rand());
self::$RSeed = (self::$RSeed * 125) % 2796203;
return self::$RSeed % ($max - $min + 1) + $min;
}
}
To call it
// set seed
Random::seed(42);
// echo 10 numbers between 1 and 100
for ($i = 0; $i < 10; $i++) {
echo Random::num(1, 100) . '<br />';
}
Now set your seed based on the current date with the php date function
// set seed based on date with
Random::seed(date("z") + 1);
This will give you the same numbers every year. If you don't want this, use the seed variable of rubo77. With this version you can ensure to get the same number on different machines (can't guarantee that with srand).
Maybe you could try something like:
$not_random_at_all = base_convert(md5($item . date('l jS \of F Y')), 16, 10);
Where $item is the number of your item (or anything that identifies the item).
It just converts the MD5-Hash of the current date concatenated with your item number to integer.
That means a different random number for every item daily.
Remember that MD5 is not a random number generator and your results might bot be as random as they can be.
$seed = floor(time()/86400);
srand($seed);
foreach($list as $item){
echo $item.rand(0,20);
}
or to obtain the same value of rand in a determined time interval.
Another Example: you have an array of 20 elements and you need to obtain a random item every day but not to change in the 24h period (just imagine "Today's Photo" or similar).
$seed = floor(time()/86400);
srand($seed);
$item = $examplearray[rand(0,19)];
You obtain the same value every time you load the page all the 24h period.

Smaller number generation from a large number and total of smaller number must be a large number

How can I generate fix smaller random numbers from a large number. Addition of these smaller numbers must be equal to large number. Suppose I want to generate 400 random number and addition of these smaller number = e.g. 1,000,000. every number should be unique and have any value assign to it. Like Number 1=1000 and number 2 may contain only 5. But total of all the number must be a large number. Is there any algorithm to do this kind of operation in php?
function array_generate_sum($n, $total)
{
$sum = 0;
$arr = array();
for( ; $n >= 0; $n--)
{
$current = $n == 0 ? $total - $sum : mt_rand(1, $total - $sum - $n);
$sum += $current;
$arr[] = $current;
}
return $arr;
}
// Generate an array of 5 values whose sum is 30
array_generate_sum(5, 30);

Calculating number of results in a specific page using pagination

I have a search result from MySQL query or Array or something else. The result gave a variable $totalfiles say for example 25. The number of results is limited to $limit, here 12. The maximum number of pages calculated, $maxpages, will be 3.
As we consider the case, we will get 12 results for pages 1 and 2, and 1 for page 3.
What is the easiest way to predict (or calculate) the number of results in a specific page using variables $totalfiles, $limit, $maxpages and $pagenumber using PHP? I don't think all these 4 variables are necessary for doing this.
The only page that is allowed to have a number that is different from $limit is the last one. Don't forget that. And the last page will always have the remainder of the integer division
$last_page_items = $totafiles % $limit;
If $last_page_items is 0, means that you have all pages with $limit items
also,
$pages = ceil($totalfiles / $limit);
R = Number of rows on a given page, P, where P starts at 1.
T = Total rows
L = Rows per page
R = T - ((P-1) * L)
Then just add a check afterwards to set R to 0 if R < 0.
Code:
function get_num_rows_on_page($page, $total_rows, $per_page) {
$on_page = $total_rows - ( ($page-1) * $per_page );
return $on_page < 0 ? 0 : $on_page;
}
Max pages: Total files, divided by the limit. If the remainder is greater than 0, add one.
$maxpages = $totalfiles/$limit;
if ($totalfiles % $limit > 0) $maxpages++;
Number on current page: if Page number less than Max page, there are limit results. If Page number is the Max page, there are (Remainder of Total Files divided by limit) results if that remainder is greater than 0, otherwise limit.
$results = $limit;
$rem = $totalfiles % limit;
if ($pagenumber == $maxpages && $rem > 0) $results = $rem;
If you want to distribute the results evenly in the maximum number of pages, which is 3 as you have suggested, you can use:
$results_per_page = ($totalfiles/$maxpages);
Otherwise, you already have the number of results per page calculated on your $limit variable.
Try this:
function getPageSize($total, $maxpages, $pagenumber){
$itemsperpage=intval($total/$maxpages);
if($pagenumber == $maxpages){
$itemslastpage=abs($total-($itemsperpage*$maxpages));
return $itemslastpage;
}else{
return $itemsperpage;
}
}
// should print '5'
echo getPageSize(29,6,6) . "\n";
// should print '7'
echo getPageSize(14,2,1) . "\n";
Note that $limit is not needed as it is only used to control results from database.

Replace duplicate values in array with new randomly generated values

I have below a function (from a previous question that went unanswered) that creates an array with n amount of values. The sum of the array is equal to $max.
function randomDistinctPartition($n, $max) {
$partition= array();
for ($i = 1; $i < $n; $i++) {
$maxSingleNumber = $max - $n;
$partition[] = $number = rand(1, $maxSingleNumber);
$max -= $number;
}
$partition[] = $max;
return $partition;
}
For example: If I set $n = 4 and $max = 30. Then I should get the following.
array(5, 7, 10, 8);
However, this function does not take into account duplicates and 0s. What I would like - and have been trying to accomplish - is to generate an array with unique numbers that add up to my predetermined variable $max. No Duplicate numbers and No 0 and/or negative integers.
Ok, this problem actually revolves around linear sequences. With a minimum value of 1 consider the sequence:
f(n) = 1 + 2 + ... + n - 1 + n
The sum of such a sequence is equal to:
f(n) = n * (n + 1) / 2
so for n = 4, as an example, the sum is 10. That means if you're selecting 4 different numbers the minimum total with no zeroes and no negatives is 10. Now go in reverse: if you have a total of 10 and 4 numbers then there is only one combination of (1,2,3,4).
So first you need to check if your total is at least as high as this lower bound. If it is less there is no combination. If it is equal, there is precisely one combination. If it is higher it gets more complicated.
Now imagine your constraints are a total of 12 with 4 numbers. We've established that f(4) = 10. But what if the first (lowest) number is 2?
2 + 3 + 4 + 5 = 14
So the first number can't be higher than 1. You know your first number. Now you generate a sequence of 3 numbers with a total of 11 (being 12 - 1).
1 + 2 + 3 = 6
2 + 3 + 4 = 9
3 + 4 + 5 = 12
The second number has to be 2 because it can't be one. It can't be 3 because the minimum sum of three numbers starting with 3 is 12 and we have to add to 11.
Now we find two numbers that add up to 9 (12 - 1 - 2) with 3 being the lowest possible.
3 + 4 = 7
4 + 5 = 9
The third number can be 3 or 4. With the third number found the last is fixed. The two possible combinations are:
1, 2, 3, 6
1, 2, 4, 5
You can turn this into a general algorithm. Consider this recursive implementation:
$all = all_sequences(14, 4);
echo "\nAll sequences:\n\n";
foreach ($all as $arr) {
echo implode(', ', $arr) . "\n";
}
function all_sequences($total, $num, $start = 1) {
if ($num == 1) {
return array($total);
}
$max = lowest_maximum($start, $num);
$limit = (int)(($total - $max) / $num) + $start;
$ret = array();
if ($num == 2) {
for ($i = $start; $i <= $limit; $i++) {
$ret[] = array($i, $total - $i);
}
} else {
for ($i = $start; $i <= $limit; $i++) {
$sub = all_sequences($total - $i, $num - 1, $i + 1);
foreach ($sub as $arr) {
array_unshift($arr, $i);
$ret[] = $arr;
}
}
}
return $ret;
}
function lowest_maximum($start, $num) {
return sum_linear($num) + ($start - 1) * $num;
}
function sum_linear($num) {
return ($num + 1) * $num / 2;
}
Output:
All sequences:
1, 2, 3, 8
1, 2, 4, 7
1, 2, 5, 6
1, 3, 4, 6
2, 3, 4, 5
One implementation of this would be to get all the sequences and select one at random. This has the advantage of equally weighting all possible combinations, which may or may not be useful or necessary to what you're doing.
That will become unwieldy with large totals or large numbers of elements, in which case the above algorithm can be modified to return a random element in the range from $start to $limit instead of every value.
I would use 'area under triangle' formula... like cletus(!?)
Im really gonna have to start paying more attention to things...
Anyway, i think this solution is pretty elegant now, it applies the desired minimum spacing between all elements, evenly, scales the gaps (distribution) evenly to maintain the original sum and does the job non-recursively (except for the sort):
Given an array a() of random numbers of length n
Generate a sort index s()
and work on the sorted intervals a(s(0))-a(s(1)), a(s(1))-a(s(2)) etc
increase each interval by the
desired minimum separation size eg 1
(this necessarily warps their
'randomness')
decrease each interval by a factor
calculated to restore the series sum
to what it is without the added
spacing.
If we add 1 to each of a series we increase the series sum by 1 * len
1 added to each of series intervals increases sum by:
len*(len+1)/2 //( ?pascal's triangle )
Draft code:
$series($length); //the input sequence
$seriesum=sum($series); //its sum
$minsepa=1; //minimum separation
$sorti=sort_index_of($series) //sorted index - php haz function?
$sepsum=$minsepa*($length*($length+1))/2;
//sum of extra separation
$unsepfactor100=($seriesum*100)/($seriesum+sepsum);
//scale factor for original separation to maintain size
//(*100~ for integer arithmetic)
$px=series($sorti(0)); //for loop needs the value of prev serie
for($x=1 ; $x < length; $x++)
{ $tx=$series($sorti($x)); //val of serie to
$series($sorti($x))= ($minsepa*$x) //adjust relative to prev
+ $px
+ (($tx-$px)*$unsepfactor100)/100;
$px=$tx; //store for next iteration
}
all intervals are reduced by a
constant (non-random-warping-factor)
separation can be set to values other
than one
implementantions need to be carefuly
tweaked (i usualy test&'calibrate')
to accomodate rounding errors.
Probably scale everything up by ~15
then back down after. Intervals should survive if done right.
After sort index is generated, shuffle the order of indexes to duplicate values to avoid runs in the sequence of collided series.
( or just shuffle final output if order never mattered )
Shuffle indexes of dupes:
for($x=1; $x<$len; $x++)
{ if ($series($srt($x))==$series($srt($x-1)))
{ if( random(0,1) )
{ $sw= $srt($x);
$srt($x)= $srt($x-1);
$srt($x-1)= $sw;
} } }
A kind of minimal disturbance can be done to a 'random sequence' by just parting dupes by the minimum required, rather than moving them more than minimum -some 'random' amount that was sought by the question.
The code here separates every element by the min separation, whether duplicate or not, that should be kindof evenhanded, but overdone maybe. The code could be modified to only separate the dupes by looking through the series(sorti(n0:n1..len)) for them and calculating sepsum as +=minsep*(len-n) for each dupe. Then the adjustment loop just has to test again for dupe before applying adjustment.

Categories