How do I generate a random code/PIN. I read PHP's rand() and mt_rand() functions and it seems to do good but I found there are duplicates.
Can someone suggest or demonstrate a better way of achieving this in PHP?
my code:
$size = 1000; //handcoded pin-size
function generatePIN($size =500){
$pins = array(); $i = 0; //ini counter
//my basic algorithm for generating unique pin codes
while ($i < $size){
$pin = (mt_rand(100000,999999));
$pins[] = $pin;
++$i;
}
sort($pins);//sort in lowest to highest
return array_unique($pins);//remove duplicates
}
//call it and print or store in database
$pins = generatePIN($size);
foreach ($pins as $pin) {
echo $pin.'<br>';
}
Thank you.
A true random always has the chance to create a duplicate, because it is unconditional to the previous given randoms.
To make a duplicate less likely you can increase the random interval with mt_rand(10000000,99999999).
Or you can check if your number was a duplicate:
while ($i < $size){
$pin = (mt_rand(100000,999999));
if (array_search($pin, $pins) === FALSE) {
$pins[] = $pin;
++$i;
}
}
This will perform more poorly the bigger $size is compared to the random interval and create an endless loop if $size is bigger than it.
adding to the generated value in the loop solved the problem is its very efficient calling it each day. No matter how long the size is.
$size = 1000; //handcoded value
function generatePIN($size =500){
$pins = array(); $i = 0;
//my basic algorithm for generating unique pin codes
while ($i < $size){
$pin = (mt_rand(100000,999999)) + (mt_rand(1000,9999)) + strtotime(date('Y-m-d', strtotime('+'.$i.' week')));
$pins[] = $pin;
++$i;
}
sort($pins);//sort in lowest to highest
return array_unique($pins);//remove duplicates
}
//store in database or print it
$pins = generatePIN($size);
foreach ($pins as $pin) {
echo $pin.'<br>';
}
echo "<hr />";
echo count($pins);
Related
This code is working fine when the array length is 8 or 10 only. When we are checking this same code for more than 10 array length.it get loading not showing the results.
How do reduce my code. If you have algorithm please share. Please help me.
This program working flow:
$allowed_per_room_accommodation =[2,3,6,5,3,5,2,5,4];
$allowed_per_room_price =[10,30,60,40,30,50,20,60,80];
$search_accommodation = 10;
i am get subsets = [5,5],[5,3,2],[6,4],[6,2,2],[5,2,3],[3,2,5]
Show lowest price room and then equal of 10 accommodation; output like as [5,3,2];
<?php
$dp=array(array());
$GLOBALS['final']=[];
$GLOBALS['room_key']=[];
function display($v,$room_key)
{
$GLOBALS['final'][] = $v;
$GLOBALS['room_key'][] = $room_key;
}
function printSubsetsRec($arr, $i, $sum, $p,$dp,$room_key='')
{
// If we reached end and sum is non-zero. We print
// p[] only if arr[0] is equal to sun OR dp[0][sum]
// is true.
if ($i == 0 && $sum != 0 && $dp[0][$sum]) {
array_push($p,$arr[$i]);
array_push($room_key,$i);
display($p,$room_key);
return $p;
}
// If $sum becomes 0
if ($i == 0 && $sum == 0) {
display($p,$room_key);
return $p;
}
// If given sum can be achieved after ignoring
// current element.
if (isset($dp[$i-1][$sum])) {
// Create a new vector to store path
// if(!is_array(#$b))
// $b = array();
$b = $p;
printSubsetsRec($arr, $i-1, $sum, $b,$dp,$room_key);
}
// If given $sum can be achieved after considering
// current element.
if ($sum >= $arr[$i] && isset($dp[$i-1][$sum-$arr[$i]]))
{
if(!is_array($p))
$p = array();
if(!is_array($room_key))
$room_key = array();
array_push($p,$arr[$i]);
array_push($room_key,$i);
printSubsetsRec($arr, $i-1, $sum-$arr[$i], $p,$dp,$room_key);
}
}
// Prints all subsets of arr[0..n-1] with sum 0.
function printAllSubsets($arr, $n, $sum,$get=[])
{
if ($n == 0 || $sum < 0)
return;
// Sum 0 can always be achieved with 0 elements
// $dp = new bool*[$n];
$dp = array();
for ($i=0; $i<$n; ++$i)
{
// $dp[$i][$sum + 1]=true;
$dp[$i][0] = true;
}
// Sum arr[0] can be achieved with single element
if ($arr[0] <= $sum)
$dp[0][$arr[0]] = true;
// Fill rest of the entries in dp[][]
for ($i = 1; $i < $n; ++$i) {
for ($j = 0; $j < $sum + 1; ++$j) {
// echo $i.'d'.$j.'.ds';
$dp[$i][$j] = ($arr[$i] <= $j) ? (isset($dp[$i-1][$j])?$dp[$i-1][$j]:false) | (isset($dp[$i-1][$j-$arr[$i]])?($dp[$i-1][$j-$arr[$i]]):false) : (isset($dp[$i - 1][$j])?($dp[$i - 1][$j]):false);
}
}
if (isset($dp[$n-1][$sum]) == false) {
return "There are no subsets with";
}
$p;
printSubsetsRec($arr, $n-1, $sum, $p='',$dp);
}
$blockSize = array('2','3','6','5','3','5','2','5','4');
$blockvalue = array('10','30','60','40','30','50','20','60','80');
$blockname = array("map","compass","water","sandwich","glucose","tin","banana","apple","cheese");
$processSize = 10;
$m = count($blockSize);
$n = count($processSize);
// sum of sets in array
printAllSubsets($blockSize, $m, $processSize);
$final_subset_room = '';
$final_set_room_keys = '';
$final_set_room =[];
if($GLOBALS['room_key']){
foreach ($GLOBALS['room_key'] as $set_rooms_key => $set_rooms) {
$tot = 0;
foreach ($set_rooms as $set_rooms) {
$tot += $blockvalue[$set_rooms];
}
$final_set_room[$set_rooms_key] = $tot;
}
asort($final_set_room);
$final_set_room_first_key = key($final_set_room);
$final_all_room['set_room_keys'] = $GLOBALS['room_key'][$final_set_room_first_key];
$final_all_room_price['set_room_price'] = $final_set_room[$final_set_room_first_key];
}
if(isset($final_all_room_price)){
asort($final_all_room_price);
$final_all_room_first_key = key($final_all_room_price);
foreach ($final_all_room['set_room_keys'] as $key_room) {
echo $blockname[$key_room].'---'. $blockvalue[$key_room];
echo '<br>';
}
}
else
echo 'No Results';
?>
I'm assuming your task is, given a list rooms, each with the amount of people it can accommodate and the price, to accommodate 10 people (or any other quantity).
This problem is similar to 0-1 knapsack problem which is solvable in polynomial time. In knapsack problem one aims to maximize the price, here we aim to minimize it. Another thing that is different from classic knapsack problem is that full room cost is charged even if the room is not completely occupied. It may reduce the effectiveness of the algorithm proposed at Wikipedia. Anyway, the implementation isn't going to be straightforward if you have never worked with dynamic programming before.
If you want to know more, CLRS book on algorithms discusses dynamic programming in Chapter 15, and knapsack problem in Chapter 16. In the latter chapter they also prove that 0-1 knapsack problem doesn't have trivial greedy solution.
My PHP script is running out of memory. I have put memory_get_usage( ) inside the loops and found that it is running out of memory after 6MB.
I would like to clearly explain my script and like to get suggestions from you.
I am not sure, If my script is running out of memory because of problems with code .
So, here is the algorithm for my script:
Read the input json data into an array ( approximatley 200 lines of data)
calculate the sum of the array ($sum)
3 variables $starting, $ending and $compare.( Intialize $compare = $starting)
start with $starting=$vmin , calculate scaling factor, scale the original array and calculate sum of it .That new sum is $ending.
Add 10 to $starting until the diff between $ending and $compare is 50.
repeat all the steps until $vmin reaches $vmax with an increment of $vinc
The above algorithm might look insane, But it finds an optimal solution for supply chain related optimization problem.
I would like you to see if my weak coding capabilities are the reason for the memory outage .If so, Please suggest the changes to my script.
Here is my code
$vmax = 10000;
$vmin = 1000;
$vinc = 2000;
//decode the json data
$fp = fopen("data_save3.json", "r");
$inp=file_get_contents("data_save3.json");
fclose($fp);
$inp=json_decode($inp);
//calculate the array sum
foreach($inp as $i=>$element) {
foreach($element as $j=>$sub_element) {
$sum+= $inp[$i][$j];
}
}
//start at vmin and increment it until vmax
for(;$vmin <=$vmax;) {
$starting=$vmin;
$compare = $starting;
//calculate scaling factor
$scale = $starting/$sum;
//calculate the scaled array
$sum2 = 0;
$inp_info2 = $inp;
$ending = newscale($inp_info2,$scale,$sum2);
$optimal = getClosest($starting,$ending,$compare,$sum);
echo $optimal.PHP_EOL;
$vmin = $vmin+$vinc ;
}
// function to find the closest value
$inp_info1=$inp;
function getClosest($starting,$compare,$ending,$sum,$inp) {
global $sum2;
global $compare;
global $inp_info1;
global $starting , $ending, $scale1, $sum, $inp, $inp_info2, $inp_info3,$rowsum2, $rowsum3, $rowsum4, $rowsum5;
if (abs($ending - $compare) < 50){
return $starting;
} else{
$starting = $starting +10;
$scale1 = $starting/$sum;
$inp_info1 = $inp;
$sum2 = 0;
$ending = newscale($inp_info1,$scale1,$sum2);
return getClosest($starting);
}
}
//array scaling function
function newscale($array,$scale,$sum2){
global $sum2,$scale;
foreach($array as $i=>$element) {
foreach($element as $j=>$sub_element) {
$array[$i][$j]*= $scale;
$array[$i][$j] = truncate($array[$i][$j]);
$sum2+=$array[$i][$j];
}
}
return $sum2;
}
//truncate function
function truncate($num, $digits = 0) {
$shift = pow(10, $digits);
return ((floor($num * $shift)) / $shift);
}
I'm are trying to teach myself to be better at programming. Part of this I have been taking puzzle that I find in newspapers and magazines and trying to find programming solutions
Today I seen a puzzle regarding numbers that are the reversed when multiplied by a number from 2-9. The example given was 1089 * 9 = 9801.
I have started to write a program in php to find the numbers this applies to and adds them to an array.
First I created a loop to cycle through the possible numbers. I then reversed each of the numbers and created a function to compare the numbered and the reversed number. The function then returns numbers that meet the criteria and adds them to an array.
This is what I have so far...
<?php
function mul(){ // multiply number from loop
for($i=2;$i<=9;$i++){
$new = $num * $i;
if($new == $re){
return $new;
}
else{
return;
}
}
}
$arr = array();
for ($num = 1000; $num <10000; $num++) { //loop through possible numbers
$re = strrev($num); // get reverse of number
func($re,$num); //multiply number and return correct numbers
$arr.push($new); //add to array??
}
?>
I'm still very new to php and I find understanding programming, any pointers on a more logical way of doing this puzzle would be greatly appreciated.
Here's my solution with a nested loop. Quick and dirty.
$result = array();
for ($i = 1000; $i < 5000; $i++) {
for ($m = 2; $m < 10; $m++) {
if ($i*$m == (int)strrev($i)) {
$result[] = array($i, $m);
}
}
}
var_dump($result);
I'd like to expand on this line:
if ($i*$m == (int) strrev($i)) {
One side is $i*$m, easy, the multipication.
On the other, we have (int)strrev($i), which means "Take $i, cast it to a string, and reverse that. Then cast it back into an int.
If that evaluates to true, an array containing $i and m is inserted into the $result array.
I was also looking for logical questions to solve to preparing for my interview. Thanks for sharing this question.I have solved this question but using Java.I have used very basic concept.I hope you can understand and convert it to php.
public static boolean processNumber(int number)
{
for(int i=2;i<=9;i++)
{
int reverseNumber=number*i;
boolean status=checkReverse(reverseNumber,number);
if(status)
{
return true;
}
}
return false;
}
public static boolean checkReverse(int reverseNumber,int numberOriginal)
{
int number=reverseNumber;
int reverse=0,digit;
do
{
digit=number%10;
number=number/10;
reverse=reverse*10+digit;
}while(number>0);
if(reverse==numberOriginal)
{
return true;
}
else
{
return false;
}
}
//This is my little effort towards programming check if it satisfy your requirements
$n = 1089;
$temp = $n;
$sum =0;
//reversing given number
while($n>1){
$rem = $n%10;
$sum = $sum*10 + $rem;
$n = $n/10;
}
//checking for digit that satisfy criteria
for($i=0; $i<=9; $i++){
if($i*$temp == $sum){
echo "$temp * $i = $sum";
}
}
I'm trying to program my own Sine function implementation for fun but I keep getting :
Fatal error: Maximum execution time of 30 seconds exceeded
I have a small HTML form where you can enter the "x" value of Sin(x) your looking for and the number of "iterations" you want to calculate (precision of your value), the rest is PhP.
The maths are based of the "Series definition" of Sine on Wikipedia :
--> http://en.wikipedia.org/wiki/Sine#Series_definition
Here's my code :
<?php
function factorial($int) {
if($int<2)return 1;
for($f=2;$int-1>1;$f*=$int--);
return $f;
};
if(isset($_POST["x"]) && isset($_POST["iterations"])) {
$x = $_POST["x"];
$iterations = $_POST["iterations"];
}
else {
$error = "You forgot to enter the 'x' or the number of iterations you want.";
global $error;
}
if(isset($x) && is_numeric($x) && isset($iterations) && is_numeric($iterations)) {
$x = floatval($x);
$iterations = floatval($iterations);
for($i = 0; $i <= ($iterations-1); $i++) {
if($i%2 == 0) {
$operator = 1;
global $operator;
}
else {
$operator = -1;
global $operator;
}
}
for($k = 1; $k <= (($iterations-(1/2))*2); $k+2) {
$k = $k;
global $k;
}
function sinus($x, $iterations) {
if($x == 0 OR ($x%180) == 0) {
return 0;
}
else {
while($iterations != 0) {
$result = $result+(((pow($x, $k))/(factorial($k)))*$operator);
$iterations = $iterations-1;
return $result;
}
}
}
$result = sinus($x, $iterations);
global $result;
}
else if(!isset($x) OR !isset($iterations)) {
$error = "You forgot to enter the 'x' or the number of iterations you want.";
global $error;
}
else if(isset($x) && !is_numeric($x)&& isset($iterations) && is_numeric($iterations)) {
$error = "Not a valid number.";
global $error;
}
?>
My mistake probably comes from an infinite loop at this line :
$result = $result+(((pow($x, $k))/(factorial($k)))*$operator);
but I don't know how to solve the problem.
What I'm tring to do at this line is to calculate :
((pow($x, $k)) / (factorial($k)) + (((pow($x, $k))/(factorial($k)) * ($operator)
iterating :
+ (((pow($x, $k))/(factorial($k)) * $operator)
an "$iterations" amount of times with "$i"'s and "$k"'s values changing accordingly.
I'm really stuck here ! A bit of help would be needed. Thank you in advance !
Btw : The factorial function is not mine. I found it in a PhP.net comment and apparently it's the optimal factorial function.
Why are you computing the 'operator' and power 'k' out side the sinus function.
sin expansion looks like = x - x^2/2! + x^3/3! ....
something like this.
Also remember iteration is integer so apply intval on it and not floatval.
Also study in net how to use global. Anyway you do not need global because your 'operator' and power 'k' computation will be within sinus function.
Best of luck.
That factorial function is hardly optimal—for speed, though it is not bad. At least it does not recurse. It is simple and correct though. The major aspect of the timeout is that you are calling it a lot. One technique for improving its performance is to remember, in a local array, the values for factorial previously computed. Or just compute them all once.
There are many bits of your code which could endure improvement:
This statement:
while($iterations != 0)
What if $iterations is entered as 0.1? Or negative. That would cause an infinite loop. You can make the program more resistant to bad input with
while ($iterations > 0)
The formula for computing a sine uses the odd numbers: 1, 3, 5, 7; not every integer
There are easier ways to compute the alternating sign.
Excess complication of arithmetic expressions.
return $result is within the loop, terminating it early.
Here is a tested, working program which has adjustments for all these issues:
<?php
// precompute the factorial values
global $factorials;
$factorials = array();
foreach (range (0, 170) as $j)
if ($j < 2)
$factorials [$j] = 1;
else $factorials [$j] = $factorials [$j-1] * $j;
function sinus($x, $iterations)
{
global $factorials;
$sign = 1;
for ($j = 1, $result = 0; $j < $iterations * 2; $j += 2)
{
$result += pow($x, $j) / $factorials[$j] * $sign;
$sign = - $sign;
}
return $result;
}
// test program to prove functionality
$pi = 3.14159265358979323846264338327950288419716939937510582097494459230781640628620;
$x_vals = array (0, $pi/4, $pi/2, $pi, $pi * 3/2, 2 * $pi);
foreach ($x_vals as $x)
{
$y = sinus ($x, 20);
echo "sinus($x) = $y\n";
}
?>
Output:
sinus(0) = 0
sinus(0.78539816339745) = 0.70710678118655
sinus(1.5707963267949) = 1
sinus(3.1415926535898) = 3.4586691443274E-16
sinus(4.7123889803847) = -1
sinus(6.2831853071796) = 8.9457384260403E-15
By the way, this executes very quickly: 32 milliseconds for this output.
First: The problem's name in Wikipedia is "ordered partition of a set".
I have an algorithm which counts possible partitions. To speed it up, I use a cache:
function partition($intervalSize, $pieces) {
// special case of integer partitions: ordered integer partitions
// in Wikipedia it is: ordered partition of a set
global $partition_cache;
// CACHE START
$cacheId = $intervalSize.'-'.$pieces;
if (isset($partition_cache[$cacheId])) { return $partition_cache[$cacheId]; }
// CACHE END
if ($pieces == 1) { return 1; }
else {
$sum = 0;
for ($i = 1; $i < $intervalSize; $i++) {
$sum += partition(($intervalSize-$i), ($pieces-1));
}
$partition_cache[$cacheId] = $sum; // insert into cache
return $sum;
}
}
$result = partition(8, 4);
Furthermore, I have another algorithm which shows a list of these possible partitions. But it doesn't use a cache yet and so it's quite slow:
function showPartitions($prefix, $start, $finish, $numLeft) {
global $partitions;
if ($numLeft == 0 && $start == $finish) { // wenn eine Partition fertig ist dann in Array schreiben
$gruppen = split('\|', $prefix);
$partitions[] = $gruppen;
}
else {
if (strlen($prefix) > 0) { // nicht | an Anfang setzen sondern nur zwischen Gruppen
$prefix .= '|';
}
for ($i = $start + 1; $i <= $finish; $i++) {
$prefix .= chr($i+64);
showPartitions($prefix, $i, $finish, $numLeft - 1);
}
}
}
$result = showPartitions('', 0, 8, 4);
So I have two questions:
1) Is it possible to implement a cache in the second algorithm, too? If yes, could you please help me to do this?
2) Is it possible to write the results of the second algorithm into an structured array instead of a string?
I hope you can help me. Thank you very much in advance!
PS: Thanks for the two functions, simonn and Dan Dyer!
No, I don't think a cache will help you here because you're never actually performing the same calculation twice. Each call to showPartitions() has different parameters and generates a different result.
Yes, of course. You're basically using another level of nested arrays pointing to integers to replace a string of characters separated by pipe characters. (Instead of "A|B|C" you'll have array(array(1), array(2), array(3)).)
Try changing showPartitions() as such:
if ($numLeft == 0 && $start == $finish) { // wenn eine Partition fertig ist dann in Array schreiben
$partitions[] = $prefix;
}
else {
$prefix[] = array();
for ($i = $start + 1; $i <= $finish; $i++) {
$prefix[count($prefix) - 1][] = $i;
showPartitions($prefix, $i, $finish, $numLeft - 1);
}
}
and instead of calling it with an empty string for $prefix, call it with an empty array:
showPartitions(array(), 0, 8, 4);
Off topic: I rewrote the first function to be a little bit faster.
function partition($intervalSize, $pieces) {
// special case of integer partitions: ordered integer partitions
// in Wikipedia it is: ordered partition of a set
// CACHE START
static $partition_cache = array();
if (isset($partition_cache[$intervalSize][$pieces])) {
return $partition_cache[$intervalSize][$pieces];
}
// CACHE END
if ($pieces === 1) {
return 1;
}
if ($intervalSize === 1) {
return 0;
}
$sum = 0;
$subPieces = $pieces - 1;
$i = $intervalSize;
while (--$i) {
$sum += partition($i, $subPieces);
}
$partition_cache[$intervalSize][$pieces] = $sum; // insert into cache
return $sum;
}
Although this is a bit old, nevertheless,
a PHP Class which implements various combinatorics/simulation methods including partitions/permutations/combinations etc.. in an efficient way
https://github.com/foo123/Simulacra/blob/master/Simulacra.php
PS: i am the author