distribute a number without remainder - php

I want to distribute an item to specific pieces without cutting the excess piece,
example:
$persons = 7;
$rooms = 2;
for($i = 0; $i < $rooms; $i++)
{
//distribute the persons per room
}
//the endpoint should be
$the_room[0] = 4 //instead of 3.5
$the_room[1] = 3 //instead of 3.5

How about an approach that first equally distributes pieces, then randomises the remainder?
$persons = 7;
$rooms = 2;
$the_room = array();
for($i = 0; $i < $rooms; $i++)
{
$the_room[$i] = floor($persons / $rooms);
}
// Random Distribution
while( $persons - array_sum($the_room) > 0)
{
$the_room[array_rand($the_room)]++;
}
// Sequential Distribution
// $index = 0;
// while( $persons - array_sum($the_room) > 0)
// {
// $the_room[$index++]++;
// }
print_r($the_room);

Related

PHP - get random integer using random_int() without repeating and looping

I need to get 50 random numbers out of range 1-100 without repeating. The current way i do is :
$array = array();
while (count($array) <= 50) {
$temp = random_int(1,100);
if (!in_array($temp, $array))
$array[] = $temp;
}
However, the looping is too many because I need to generate for more than 100,000 times.
Is there other ways that I can get a 50 random non-repeating numbers without looping ?
For example:
$number= range(1,100);
$array = array_slice(shuffle($number),0,50);
I can't use shuffle because it uses pseudo random number.
Is there other ways to achieve what I need, or ways that could shorten time.
pre fill a array of numbers and pick from them, and then remove it.
it prevents the unnecessary random generations you have
$numbers = [];
for ($i = 1; $i <= 100; $i++) {
$numbers[] = $i;
}
$randomNumbers = [];
for ($i = 1; $i <= 50; $i++) {
$r = rand(0, count($numbers) - 1);
$randomNumbers[] = $numbers[$r];
array_splice($numbers, $r, 1);
}
This would be my approach:
This gives you 50 numbers in any case, and they are defenitely different from each other. PLUS: you dont have to prefill some other array:
$start = microtime(true);
for($i = 0; $i <= 100000; $i++){
$arr = [];
while(sizeof($arr) < 50){
$num = rand(1, 100);
$arr[$num] = $num;
}
if(array_unique($arr) !== $arr || sizeof($arr) !== 50 ){
print("FAIL");
}
//print(array_unique($arr) == $arr ? "true" : "false");print("<br>");
//print(sizeof($arr));print("<br>");
//print_r(array_count_values ($arr));print("<br>");
//print_r($arr);print("<br>");
}
$time_elapsed_secs = microtime(true) - $start;
print($time_elapsed_secs);print("<br>");
Running this 100000 times takes about 0.4sec for me.
The actual generation is done in this part:
$arr = [];
while(sizeof($arr) < 50){
$num = rand(1, 100);
$arr[$num] = $num;
}
We can do in 2 steps:
$x = 0;
$arr = [];
while($x < 50){
$tmp = rand(1, 100);
if(!in_array($tmp, $arr)){
$arr[] = $tmp;
$x++;
}
}

Switch elements of 2d array

I have a problem: I can't make my script working with penalties, but I made it work with bonuses.
Start: two-dimensional array of users, each has id, name, start position and modificator (if modificator < 0 its bonus; if modificator > 0 its penalty).
How modificators work: for example, I have a queue of users Test1, Test2, Test3. If I give user Test3 bonus 1, he will switch places with user Test 2 and final queue will be Test1, Test3, Test2. If I give him bous 2, than he will be first at queue.
Penalties works the other way around. If I give user Test1 penalty 1, he will be second in a queue. If I give him penalty 3, he will be moved to the end of the queue.
This is my working code for bonuses:
<?
$new = array(); $orders = array();
$new[111]['position'] = 1; $new[111]['user'] = 'Test1'; $orders[1] = 111; $new[111]['shift'] = 0;
$new[222]['position'] = 2; $new[222]['user'] = 'Test2'; $orders[2] = 222; $new[222]['shift'] = 0;
$new[333]['position'] = 3; $new[333]['user'] = 'Test3'; $orders[3] = 333; $new[333]['shift'] = 0;
$new[444]['position'] = 4; $new[444]['user'] = 'Test4'; $orders[4] = 444; $new[444]['shift'] = 0;
$new[555]['position'] = 5; $new[555]['user'] = 'Test5'; $orders[5] = 555; $new[555]['shift'] = 0;
$new[666]['position'] = 6; $new[666]['user'] = 'Test6'; $orders[6] = 666; $new[666]['shift'] = 0;
$new[777]['position'] = 7; $new[777]['user'] = 'Test7'; $orders[7] = 777; $new[777]['shift'] = 0;
$new[888]['position'] = 8; $new[888]['user'] = 'Test8'; $orders[8] = 888; $new[888]['shift'] = 0;
//shift function
function bonus($start, $bonus)
{
global $new, $orders;
//for bonuses, shift to start, $bonus is negative number
if ($bonus < 0)
{
for ($i = $start; $i > ($start - abs($bonus)); $i--)
{
$order_id = intval($orders[$i]);
$prev = intval($orders[$i - 1]);
if ($prev != 0)
{
$temp = $new[$order_id]['position'];
$new[$order_id]['position'] = $new[$prev]['position'];
$new[$prev]['position'] = $temp;
$orders[$i] = $prev;
$orders[$i - 1] = $order_id;
}
}
}
//end for bonuses
}
// Now I set modificator (bonus negative, penalty positive)
$new[555]['shift'] = -2;
// sort by bonuses
$i = 1;
foreach($new as $value)
{
$order_id = $orders[$i];
bonus($new[$order_id]['position'], $new[$order_id]['shift']);
$i++;
}
// sort 2d array with field position
usort($new, function($a, $b){
return $a['position'] <=> $b['position'];
});
//DATA OUTPUT
$i = 1;
foreach($new as $value)
{
echo $i . '. ' . $value['user'] . ' ; shift: ' . $value['shift'];
echo '<br>';
$i++;
}
?>
At this code I set bonus with: $new[555]['shift'] = -2;
So, penalty will be like: $new[444]['shift'] = 3;
Code for penalties I think must be something like this:
//for penalty, shift to the end, $bonus positive number
if ($bonus > 0)
{
$total_new = count($new);
for ($i = $start; $i < ($start + $bonus); $i++)
{
$order_id = intval($orders[$i]);
$next = intval($orders[$i + 1]);
if ($next < $total_new)
{
$temp = $new[$order_id]['position'];
$new[$order_id]['position'] = $new[$next]['position'];
$new[$next]['position'] = $temp;
$orders[$i] = $next;
$orders[$i + 1] = $order_id;
}
}
}
//end code for penalty
Here is something wrong with $orders. I tried many different types of code all day long, including array enumeration in asc/desc order, but it didn't work correcty...
P.S. I know about array_multisort, but I dont need to sort, I need to switch elements with each other.
Again: bonus 2 means that user must switch places with previous number 2 times. Penalty 3 means that user must switch places with next user 3 times.

Divide integer number into dynamic number of parts using php

I want to divide a number into n number of parts like follows
Input : $n = 4;$m =14;
Output should as : array(1=>4,2=>4,3=>3,4=>3);
i.e :
$n $m
1 1+1+1+1
2 1+1+1+1
3 1+1+1
4 1+1+1
Any suggestions or links would help a lot.
Here is one way to do it - this works in phpfiddle:
$n = 4;
$m =14;
$array = distribute($m,$n);
print_r($array);
function distribute($m,$n) {
$div = floor($m / $n);
$mod = fmod($m, $n);
$result = array();
for ($i = 1;$i <= $n;$i++) {
$result[$i] = $div;
}
if ($mod > 0) {
for ($i = 1;$i <= $mod;$i++) {
$result[$i] = $result[$i] + 1;
}
}
return $result;
}

Automate sum in array

I will try to explain the problem that I have with this code.
This script works well to up to three persons ($numRows = 3).
$z=0;
$i=0;
$x=0;
do {
$total[] = (
${'contaH'.$z}[$i+0]*$final[$x+0]+
${'contaH'.$z}[$i+1]*$final[$x+1]+
${'contaH'.$z}[$i+2]*$final[$x+2]
);
$z++;
} while ($z<$numRows); //3
But if I have only four persons ($numRows = 4), I need something like this:
$z=0;
$i=0;
$x=0;
do {
$total[] = (
${'contaH'.$z}[$i+0]*$final[$x+0]+
${'contaH'.$z}[$i+1]*$final[$x+1]+
${'contaH'.$z}[$i+2]*$final[$x+2]+
${'contaH'.$z}[$i+3]*$final[$x+3]
// if they are 5 persons ($numRows=5), here, should exists another row
);
$z++;
} while ($z<$numRows); //4
So the problem is to automate these changes in relation of $numRows.
Here is a demo of matrix algebra:
The only thing that I want is put my code dynamically in a function of number of persons.
A | B | C | D
Person1
Person2
Person3
Person4
...
What can be different in my case is just the number of persons.
More information here.
$z=0;
$i=0;
$x=0;
$numRows = 5;
do{
$currentSum = 0;
for($c = 0; $c < $numRows; $c++){
$currentSum += (${'contaH'.$z}[$i+$c] * $final[$x+$c]);
}
$total[] = $currentSum;
$z++;
}while($z < $numRows);
$subtotal = 0;
for ($i = 0; $i < $numRows; $i++) {
$subtotal += ${'contaH'.$z}[$i] * $final[$i];
}
$total[] = $subtotal;
You might be interested in the Math_Matrix library which will help you do all sorts of matrix arithmetic.
The following code, however, automates your solution:
function mat_mult($matrix, $vector) {
$result = array();
$matrixWidth = count($matrix[0]);
for ($z = 0; $z < $matrixWidth; $z++) {
$value = 0;
for ($y = 0; $y < $matrixWidth; $y++) {
$value += $matrix[$z][$y]*$vector[$y];
}
$result[] = $value;
}
return $result;
}
$matrix = array(
array(1, 1/3.0, 2, 4),
array(3, 1, 5, 3),
array(1/2.0, 1/5.0, 1, 1/3.0),
array(1/4.0, 1/3.0, 3, 1)
);
$vector = array(0.26, 0.50, 0.09, 0.16);
$v2 = mat_mult($matrix, $vector);
print_r($v2);
Also, to tie it more into your existing matrix structure:
$matrix = array();
for ($z = 0; $z < $numRows; $z++) {
$matrix[] = ${'contaH'.$z};
}

php array output problem

In php is there a function to increment the
values of subsequent values twice(*2) in an array
column based on an initial value?
$beta = array(
array('5', '1''1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1'),
array('5','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2'),
array('5','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2'),
array('5','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2'),
array('5','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2'),
array('5','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2'),
array('5','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2'),
array('5','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2'),
array('5','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2'),
array('5','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2')
);
/*Example: '5' will be '10' (5*2 =10 and output 10 to web)
'2' will be '4' (2*2 = 4 and output 4 to web)
The next '2' will be '16' (4*2 = 8 and output 8 to web)
The next '2' will be '32' (8*2 = 16 and output 16 to web)
And so forth? */
Furthermore is there an easier way to construct this array, cause I firmly believe there is, but not something too complicated in terms of construct such that a noob will not understand it, again thanks.
[Disclaimer: I have spent 3 days trying to understand arrays, I now understand them; however, I am still new and am currently having some issues when trying to manipulate the values in my array and output them to the web.And I am still pretty sure I have a lot to read and learn, so please no flamers, I just need some help, found this problem in this C++ book:
[http://books.google.com/books?id=4Fn_P7tdOZgC&pg=PT424&lpg=PT424&dq=subsequent+++column+is+twice+the+value&source=bl&ots=gSvQ_LhxoI&sig=dG_Ilf1iLO86lqX936cT1PpkPc8&hl=en&ei=OEEBS_eODYyotgOFtJD3CQ&sa=X&oi=book_result&ct=result&resnum=1&ved=0CAgQ6AEwAA#v=onepage&q=subsequent%20%20%20column%20is%20twice%20the%20value&f=false][1]
You can try array_map:
<?php
function increase($n) {
return is_array($n) ? array_map('increase', $n) : $n * 2;
}
$new_beta = array_map("increase", $beta);
As for constructing the array, there are other methods to do so but I believe this is the most performent and clean.
Here is an answer for each question in that section of the book, enjoy!
<?php
// Declare an array alpha of 10 rows and 20 columns of type int
// Initialise the array alpha to 0
$alpha = array(array());
for($i = 0; $i < 10; $i++)
{
for($j = 0; $j < 20; $j++)
{
$alpha[$i][$j] = 0;
}
}
// Store 1 in the first row and 2 in the remaining rows
for($i = 0; $i < 10; $i++)
{
for($j = 0; $j < 20; $j++)
{
if($i == 0)
{
$alpha[$i][$j] = 1;
}
else
{
$alpha[$i][$j] = 2;
}
}
}
// Store 5 in the first column, and make sure that the value in
// each subsequent column is twice the value in the previous column
// (Beware this doesn't build off the initial value of 5 in the first
// column but the previously set values above)
for($i = 0; $i < 10; $i++)
{
for($j = 0; $j < 20; $j++)
{
if($j == 0)
{
$alpha[$i][$j] = 5;
}
else
{
if($j - 1 >= 1)
{
$alpha[$i][$j] = $alpha[$i][$j-1] * 2;
}
}
}
}
// Print the array alpha one row per line
print "Printing the array alpha one row per line:<br/>";
for($i = 0; $i < 10; $i++)
{
for($j = 0; $j < 20; $j++)
{
print "[". $alpha[$i][$j] ."] ";
}
print "<br/>";
}
print "<br/>";
// Print the array alpha one column per line
print "Printing the array alpha one column per line:<br/>";
for($j = 0; $j < 20; $j++)
{
for($i = 0; $i < 10; $i++)
{
print "[". $alpha[$i][$j] ."] ";
}
print "<br/>";
}
?>

Categories