Divide integer number into dynamic number of parts using php - 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;
}

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++;
}
}

PHP letter looping number to chr

I am trying to turn numbers into letters to create references for rows.
I have:
public static function references($idx) {
$str = '';
$i = ceil($idx/25);
if(65+$idx > 90) {
} else {
$str = chr(65+$idx);
}
return $chr;
}
But I don't know where to go from here.
Valid outputs would be:
first item: A
28th item: AB
...
Input is an index that comes in from a loop, i.e. 0, 1, 2, 3 etc
I figured it out:
public static function references($n)
{
$r = '';
for ($i = 1; $n >= 0 && $i < 10; $i++) {
$r = chr(0x41 + ($n % pow(26, $i) / pow(26, $i - 1))) . $r;
$n -= pow(26, $i);
}
return $r;
}

I need to find all amicable numbers up to a certain number

Here is my code:
$n = 300;
$set = 0;
$set2 = 0;
for($i = 1; $i<$n; $i++)
{
for($j = 1; $j <$i; $j++)
{
$qol = $i % $j;
if($qol == 0)
{
$set += $j;
}
}
for($s=1; $s<$set; $s++)
{
$qol2 = $set % $s;
if($s == 0)
{
$set2 += $s;
}
}
if($set2 == $i)
{
echo "$set and $i are amicable numbers</br>";
}
}
I do not know what the heck the problem is!
FYI: 220 and 284 are an example of amicable numbers. The sum of the proper divisors of one number are equal to other number and vice versa (wiki).
I am having troubles following your logic. In your code how would $set2 == $i ever be true? Seems to me that $i would always be greater.
I would do it the following way:
First make a separate function that finds the sums of the proper divisors:
// Function to output sum of proper divisors of $num
function sumDiv($num) {
// Return 0 if $num is 1 or less
if ($num <= 1) {
return 0;
}
$result = 1; // All nums divide by 1
$sqrt = sqrt($num);
// Add divisors to result
for ($i = 2; $i < $sqrt; $i++) {
if ($num % $i == 0) {
$result += $i + $num / $i;
}
}
// If perfect square add squareroot to result
if (floor($sqrt) == $sqrt) {
$result += $sqrt;
}
return $result;
}
Next check each iteration for a match:
$n = 1500;
for ($i = 1; $i < $n; $i++) {
// Get sum of proper devisors of $i, and sum of div. of result.
$currentDivs = sumDiv($i);
$resultDivs = sumDiv($currentDivs);
// Check for a match with sums not equal to each other.
if ($i == $resultDivs && $currentDivs != $resultDivs) {
echo "$i and $currentDivs are amicable numbers<br>";
}
}
Here a functioning phpfiddle.
Warning: Large numbers will take very long to process!

prevent Random PHP generator from including zeros

I have a php script that creates a random 10 digit order number:
// Assign order number length
$digits = 10;
// Create random order number to be stored with this order
$order_number = rand(pow(10, $digits-1), pow(10, $digits)-1);
How do I prevent this from ever including the digit zero 0 in the random 10 digit number? Thanks in advance!
You can do fancy base conversions, but in the end, the most straightforward way is to just get a string:
function random_string($count, $available) {
$result = '';
$max = strlen($available) - 1;
for($i = 0; $i < $count; $i++) {
$result .= $available[rand(0, $max)];
}
return $result;
}
…
$order_number = random_string($digits, '123456789');
You can treat it as a number of base 9
base_convert(rand(0, pow(9, $digits) - 1), 10, 9)
This will give you numbers with digits from 0 to 8.
Now just add 1 to every digit to make it 1 to 9
(pow(10, $digits) - 1) / 9
will give you a number filled with ones. Now just add it to your previous number and there you go:
$digits = 10;
$order_number = (pow(10, $digits) - 1) / 9 + base_convert(rand(0, pow(9, $digits) - 1), 10, 9);
Try this :D
function getRandom($from, $to){
$num = rand($from, $to);
$have_zero = true;
$strNum = strval($num);
while ($have_zero){
$have_zero = false;
for ($i = 0; $i < sizeof($strNum); $i++){
if ($strNum[$i] == '0'){
$have_zero = true;
$num = rand($from, $to);
$strNum = strval($num);
break;
}
}
}
return $num;
}
getRandom(1111111111, 9999999999);
You could use a simple function like this:
function getRandom($length) {
$numbers = '';
for($i = 0; $i < $length; $i++) {
$numbers .= rand(1, 9);
}
return $numbers;
}
echo getRandom(10);
I would make a function.
<?php
function myRandomNumberWithoutZeros($digits)
{
$result = str_replace("0", "",rand(pow(10,$digits-1), pow(10, $digits)-1)."");
$resultLength = strlen($result);
if($resultLength < $digits)
{
return intval($result.myRandomNumberWithoutZeros($digits-$resultLength));
}
return intval($result);
}
echo myRandomNumberWithoutZeros(10);
?>

Populate 4 arrays evenly distributed as much as possible from top to bottom

This question is in relation to this post
How to distribute mysql result set in an multidimensional array of 4 arrays
I got the accepted answer but now i want to make a change to the code and i'm not having a lot of success...
Basically, from a mysql result set, i need to populate 4 arrays evenly distributed as much as possible from top to bottom...
Chris Hayes provided a solutuon that works, but when i tested it today, i realize that it populates the array from left to rigth, and not from top to bottom...
How do i change the code so it populates the 4 arrays as much as possible from top to bottom ?
$i = 0;
$array_r = array( array(), array(), array(), array() );
while ($stmt->fetch()) {
array_push($array_r[$i], array(... values ...));
$i = ($i + 1) % 4;
}
final version without manipulating the input array at all:
for ($num = count($input), $offset = 0; $numBuckets > 0; $numBuckets -= 1, $num -= $bucketSize, $offset += $bucketSize) {
$bucketSize = ceil($num / $numBuckets);
$output[] = array_slice($input, $offset, $bucketSize);
}
pervious answer:
Try the following:
<?php
$input = range('A', 'Z'); // test input data
$output = array(); // the output container
$numBuckets = 4; // number of buckets to fill
for (; $numBuckets > 0; $numBuckets -= 1) {
$output[] = array_splice($input, 0, ceil(count($input) / $numBuckets));
}
print_r($output);
alternative version, without constant rechecking the length of the array
for ($num = count($input); $numBuckets > 0; $numBuckets -= 1, $num -= $bucketSize) {
$bucketSize = ceil($num / $numBuckets);
$output[] = array_splice($input, 0, $bucketSize);
}
This snippet should work for you:
<?php
$array= [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17];
$strays = count($array)%4;
$offset = 0;
$results = array();
for($x = 0; $x < 4; $x++){
if ($x < $strays){
$size = (floor(count($array)/4) + 1);
} else {
$size = (floor(count($array)/4));
}
$results[] = array_slice($array, $offset, $size);
$offset+=$size;
}
print_r($results);
I've tested something and it seems to work... but it looks very spaghetti... please feel free to optimize the code. Thanks.
$num_rows = $stmt->num_rows; //number of records returned by the result set
$min_per_column = (int)($num_rows/4); //minimum records per column
$remainder = $num_rows % 4; //the remainder
$array_r = array(array(), array(), array(), array());
$i = 1;
$col = 0;
//how many records to populate before moving to the next array?
$rows = ($col < $remainder) ? $min_per_column + 1 : $min_per_column;
while ($stmt->fetch()) {
array_push($array_r[$col], array($r_recordingid, $r_title, $r_subtitle, $r_seourl));
$i++;
//initialize values for new array
if ($i > $rows) {
$i = 1;
$col++;
$rows = ($col < $remainder) ? $min_per_column + 1 : $min_per_column;
}
}

Categories