Selecting the digits in a specific section inside a string - php

I want to pick digits between other groups of digits.
I think it is best that I show this pattern in order to explain what I mean:
xxxxx...xxxxyyyyyyy....yyyyzzzzzzz....zzzz
{ 1000 } { 1500 }
So from the above string structure, I want to pick the digits that occur between the first 1000 digits (xx) and the final 1500 digits (zz).
I tried substr but as I have to specify the length it didn't work for me. Because I don't know what the length is between those two indexes.
Here is my code:
$id = base64_encode($core->security(1070).$list["user_id"]);
$core->security creates number as many as what is input.
In this it example it creates a length of 1070 random digits.
$decoded = base64_decode($id);
$homework_id = mysqli_real_escape_string($connection,substr($decoded, 1070));
I can pick numbers after some length of digits. But I want to take them between series of digits.

I tried substr but as I have to specify the length it didnt work for me. Because I don't the length between 1000 number and 1500 number.
There is a feature of substr that you might have missed. From the documentation:
If length is given and is negative, then that many characters will be omitted from the end of string
So this would work:
$left = 1000; // Number of characters to be chopped off from the left side
$right = 1500; // Number of characters to be chopped off from the right side
$id = substr($id, $left, -$right) ?: "";
The ?: "" part is there to convert false to "". substr will return false when there are not enough characters present in the string to chop off that many characters. If in that case you just want to get an empty string, then ?: "" will do just that.

You can do it with regex to capture numbers that is between 1000 and 1500
<?php
$number = '10001212121212121500'; #make it string first
if (preg_match('/1000(.*?)1500/', $number, $match) == 1) {
echo (int)$match[1];
}
?>
DEMO1: https://3v4l.org/pebul
DEMO2: https://3v4l.org/8TiWH

$text = <<<HEREDOC
xxxxx...xxxxyyyyyyy....yyyyzzzzzzz....zzzz
{ 1000 } { 1500 }
HEREDOC;
preg_match_all('/\{\s+(\d+)\s+\}/', $text, $matches);
var_dump($matches);
Result:
array(2) {
[0]=>
array(2) {
[0]=>
string(12) "{ 1000 }"
[1]=>
string(15) "{ 1500 }"
}
[1]=>
array(2) {
[0]=>
string(4) "1000"
[1]=>
string(4) "1500"
}
}

Related

Number format with str_replace

I need to format my currency values to remove dots and comma and increase 00 in non cents values, this is the best way?
str_replace(['.',','],'', number_format('67.50',2)); return 6750
str_replace(['.',','],'', number_format('112.35',2)); return 11235
str_replace(['.',','],'', number_format('1001',2)); return 100100
Using BCMath extension of PHP directly.
Source code:
<?php
$num = bcmul('123.45', 100);
var_dump($num);
$num = bcmul('123.456', 100);
var_dump($num);
// The thrid parameter is used to set the number of digits after the decimal place in the result.
$num = bcmul('123.456', 100, 1);
var_dump($num);
$num = bcmul('123456.78', 100);
var_dump($num);
Output:
string(5) "12345"
string(5) "12345"
string(7) "12345.6"
string(8) "12345678"
For more information, see https://www.php.net/manual/en/function.bcmul.php

Adding year and leading zeroes in id

I have column named ID and I want it to indicate year that record when it was created with format.
Scenario
I created new data on this day( 1-11-2019) and with the format.
2019-01-110000-1
And when it is reached to 9 it will become 0000-00010
Example:
20190101-0000-0001
...
20190101-0000-0010
View
<?= $purchase_order->date . sprintf("%06s",-$counter) ?>
Question: How can I add leading zeroes in 0000-1(it should be like this 0000-0001 and when it reached 9 it will become 0000-0010
Math.
function weirdNumberFormatter(int $input) {
$high = intdiv($input, 10000);
$low = $input % 10000;
return sprintf('%04d-%04d', $high, $low);
}
var_dump(
weirdNumberFormatter(1),
weirdNumberFormatter(1234),
weirdNumberFormatter(12345),
weirdNumberFormatter(1234567),
weirdNumberFormatter(12345678)
);
Output:
string(9) "0000-0001"
string(9) "0000-1234"
string(9) "0001-2345"
string(9) "0123-4567"
string(9) "1234-5678"

Getting files from webpage and save with file_put_contents

I tried making a script that could save all files from a webpage with a pattern in name to a server.
<?php
$base_url = "http://www.someurl.com/";
$sufix = ".jpg";
$id_start= "Name Numberstart"; //Picture 1
$id_end = "Name Numberend"; // Picture 235
$path_to_save = "filer/";
foreach(range($id_start, $id_end) as $id) {
file_put_contents($path_to_save.$id.$sufix, file_get_contents($base_url.$id.$sufix));
}
?>
If I only use id with numbers etc. 1-20 or 50 - 60 and so on, the script works perfectly. But when I have a name in front and white space, it doesn't seem to work. It just saves 1 file and stops.
According to php.net's description of range:
Character sequence values are limited to a length of one. If a length greater than one is entered, only the first character is used.
I take that to mean that
range("Name Numberstart", "Name Numbersend") == array("N");
And if we run php interactively, this is confirmed:
php > $var = range("Name Numberstart", "Name Numbersend");
php > var_dump($var);
array(1) {
[0]=>
string(1) "N"
}
So basically, you're actually getting the range of the first character of the first word to the first character of the second word. If we change the second word to "Pretty", we get:
php > var_dump(range("Name Numberstart", "Pretty Numbersend"));
array(3) {
[0]=>
string(1) "N"
[1]=>
string(1) "O"
[2]=>
string(1) "P"
}

rounding a number, NOT necessarily decimel PHP

I have a question.
I am using php to generate a number based on operations that a user has specified
This variable is called
$new
$new is an integer, I want to be able to round $new to a 12 digit number, regardless of the answer
I was thinking I could use
round() or ceil()
but I believe these are used for rounding decimel places
So, I have an integer stored in $new, when $new is echoed out I want for it to print 12 digits. Whether the number is 60 billion or 0.00000000006
If i understand correctly
function showNumber($input) {
$show = 12;
$input = number_format(min($input,str_repeat('9', $show)), ($show-1) - strlen(number_format($input,0,'.','')),'.','');
return $input;
}
var_dump(showNumber(1));
var_dump(showNumber(0.00000000006));
var_dump(showNumber(100000000000000000000000));
gives
string(12) "1.0000000000"
string(12) "0.0000000001"
string(12) "999999999999"

How to make 5 random numbers with sum of 100 [duplicate]

This question already has answers here:
Getting N random numbers whose sum is M
(9 answers)
Closed 1 year ago.
do you know a way to split an integer into say... 5 groups.
Each group total must be at random but the total of them must equal a fixed number.
for example I have "100" I wanna split this number into
1- 20
2- 3
3- 34
4- 15
5- 18
EDIT: i forgot to say that yes a balance would be a good thing.I suppose this could be done by making a if statement blocking any number above 30 instance.
I have a slightly different approach to some of the answers here. I create a loose percentage based on the number of items you want to sum, and then plus or minus 10% on a random basis.
I then do this n-1 times (n is total of iterations), so you have a remainder. The remainder is then the last number, which isn't itself truley random, but it's based off other random numbers.
Works pretty well.
/**
* Calculate n random numbers that sum y.
* Function calculates a percentage based on the number
* required, gives a random number around that number, then
* deducts the rest from the total for the final number.
* Final number cannot be truely random, as it's a fixed total,
* but it will appear random, as it's based on other random
* values.
*
* #author Mike Griffiths
* #return Array
*/
private function _random_numbers_sum($num_numbers=3, $total=500)
{
$numbers = [];
$loose_pcc = $total / $num_numbers;
for($i = 1; $i < $num_numbers; $i++) {
// Random number +/- 10%
$ten_pcc = $loose_pcc * 0.1;
$rand_num = mt_rand( ($loose_pcc - $ten_pcc), ($loose_pcc + $ten_pcc) );
$numbers[] = $rand_num;
}
// $numbers now contains 1 less number than it should do, sum
// all the numbers and use the difference as final number.
$numbers_total = array_sum($numbers);
$numbers[] = $total - $numbers_total;
return $numbers;
}
This:
$random = $this->_random_numbers_sum();
echo 'Total: '. array_sum($random) ."\n";
print_r($random);
Outputs:
Total: 500
Array
(
[0] => 167
[1] => 164
[2] => 169
)
Pick 4 random numbers, each around an average of 20 (with distribution of e.g. around 40% of 20, i.e. 8). Add a fifth number such that the total is 100.
In response to several other answers here, in fact the last number cannot be random, because the sum is fixed. As an explanation, in below image, there are only 4 points (smaller ticks) that can be randomly choosen, represented accumulatively with each adding a random number around the mean of all (total/n, 20) to have a sum of 100. The result is 5 spacings, representing the 5 random numbers you are looking for.
Depending on how random you need it to be and how resource rich is the environment you plan to run the script, you might try the following approach.
<?php
set_time_limit(10);
$number_of_groups = 5;
$sum_to = 100;
$groups = array();
$group = 0;
while(array_sum($groups) != $sum_to)
{
$groups[$group] = mt_rand(0, $sum_to/mt_rand(1,5));
if(++$group == $number_of_groups)
{
$group = 0;
}
}
The example of generated result, will look something like this. Pretty random.
[root#server ~]# php /var/www/dev/test.php
array(5) {
[0]=>
int(11)
[1]=>
int(2)
[2]=>
int(13)
[3]=>
int(9)
[4]=>
int(65)
}
[root#server ~]# php /var/www/dev/test.php
array(5) {
[0]=>
int(9)
[1]=>
int(29)
[2]=>
int(21)
[3]=>
int(27)
[4]=>
int(14)
}
[root#server ~]# php /var/www/dev/test.php
array(5) {
[0]=>
int(18)
[1]=>
int(26)
[2]=>
int(2)
[3]=>
int(5)
[4]=>
int(49)
}
[root#server ~]# php /var/www/dev/test.php
array(5) {
[0]=>
int(20)
[1]=>
int(25)
[2]=>
int(27)
[3]=>
int(26)
[4]=>
int(2)
}
[root#server ~]# php /var/www/dev/test.php
array(5) {
[0]=>
int(9)
[1]=>
int(18)
[2]=>
int(56)
[3]=>
int(12)
[4]=>
int(5)
}
[root#server ~]# php /var/www/dev/test.php
array(5) {
[0]=>
int(0)
[1]=>
int(50)
[2]=>
int(25)
[3]=>
int(17)
[4]=>
int(8)
}
[root#server ~]# php /var/www/dev/test.php
array(5) {
[0]=>
int(17)
[1]=>
int(43)
[2]=>
int(20)
[3]=>
int(3)
[4]=>
int(17)
}
$number = 100;
$numbers = array();
$iteration = 0;
while($number > 0 && $iteration < 5) {
$sub_number = rand(1,$number);
if (in_array($sub_number, $numbers)) {
continue;
}
$iteration++;
$number -= $sub_number;
$numbers[] = $sub_number;
}
if ($number != 0) {
$numbers[] = $number;
}
print_r($numbers);
This should do what you need:
<?php
$tot = 100;
$groups = 5;
$numbers = array();
for($i = 1; $i < $groups; $i++) {
$num = rand(1, $tot-($groups-$i));
$tot -= $num;
$numbers[] = $num;
}
$numbers[] = $tot;
It won't give you a truly balanced distribution, though, since the first numbers will on average be larger.
I think the trick to this is to keep setting the ceiling for your random # generator to 100 - currentTotal
The solution depends on how random you want your values to be, in other words, what random situation you're going to simulate.
To get totally random distribution, you'll have to do 100 polls in which each element will be binded to a group, in symbolic language
foreach i from 1 to n
group[ random(1,n) ] ++;
For bigger numbers, you could increase the selected group by random(1, n/100) or something like that until the total sum would match the n.
However, you want to get the balance, so I think the best for you would be the normal distribution. Draw 5 gaussian values, which will divide the number (their sum) into 5 parts. Now you need to scale this parts so that their sum would be n and round them, so you got your 5 groups.
The solution I found to this problem is a little different but makes makes more sense to me, so in this example I generate an array of numbers that add up to 960. Hope this is helpful.
// the range of the array
$arry = range(1, 999, 1);
// howmany numbers do you want
$nrresult = 3;
do {
//select three numbers from the array
$arry_rand = array_rand ( $arry, $nrresult );
$arry_fin = array_sum($arry_rand);
// dont stop till they sum 960
} while ( $arry_fin != 960 );
//to see the results
foreach ($arry_rand as $aryid) {
echo $arryid . '+ ';
}

Categories