Excuse the tardy title.
This question is related to variable by reference.
Lets say we have a little for loop like this:
for($i = 0; $i < 5; $i++) {
$r = 15;
$t = &$i + $r;
array_push($a, $t);
}
Expected output:
Array
(
[0] => 15
[1] => 16
[2] => 17
[3] => 18
[4] => 19
)
Returned output:
Array
(
[0] => 0
[1] => 1
[2] => 2
[3] => 3
[4] => 4
)
Yet if I have something like this:
for($i = 0; $i < 5; $i++) {
$r = 15;
$num = &$i;
$t = $num + $r;
array_push($a, $t);
}
It returns the exact expected result as above.
Could somebody please shed some light on this.
I'll have a go...
In the second example:
for($i = 0; $i < 5; $i++) {
$r = 15;
$num = &$i; // now $num and $i are the same thing - perfectly legitimate
$t = $num + $r; // equivalent to $t = $i + $r
array_push($a, $t);
}
Whereas in the first example:
for($i = 0; $i < 5; $i++) {
$r = 15;
$t = &$i + $r; // $t and $i are the same thing. $r is not involved
$t = &$i * "anything you want"; // this does exactly the same thing
array_push($a, $t);
}
Note that in the documentation, these kinds of assignments are written like $t =& $i, which I think is a useful reminder that you're just creating an alias between two things and anything else in the same statement is irrelevant.
Related
This question already has answers here:
How can I sort arrays and data in PHP?
(14 answers)
Closed 3 years ago.
I am trying to create an algorithm that shows each step of bubble sort, sorting one number at a time. I was was able to sort the number at the first index, but I need to figure out how to sort all the numbers.
$x = array (9,7,5,3,0);
$count = count($x);
for($i = 0; $i < $count-1; $i++ ) {
$temp = $x[$i+1];
$x[$i+1] = $x[$i];
$x[$i] = $temp;
echo '<pre>';
print_r($x);
}
My current output is:
Array
(
[0] => 7
[1] => 9
[2] => 5
[3] => 3
[4] => 0
)
Array
(
[0] => 7
[1] => 5
[2] => 9
[3] => 3
[4] => 0
)
Array
(
[0] => 7
[1] => 5
[2] => 3
[3] => 9
[4] => 0
)
Array
(
[0] => 7
[1] => 5
[2] => 3
[3] => 0
[4] => 9
)
From here I need to continue sorting the remaining numbers. For 7, the output should be
57390
53790
53970
53907
and then for 3
35079
30579
30759
30795
and then for 0, it should be same for all 4 lines like
03570
03579
03579
03579
[The assigned problem.][1]
Two issues:
You should only swap values when they are not in the right order
You need an outer loop to repeat this inner loop, similar to a proper bubble sort algorithm.
Your code can be modified like below so it generates the required output:
$x = array (9,7,5,3,0);
$count = count($x) - 1;
for($times = 0; $times < $count; $times++) {
for($i = 0; $i < $count; $i++ ) {
$temp = $x[$i+1];
if ($temp < $x[$i]) {
$x[$i+1] = $x[$i];
$x[$i] = $temp;
}
echo implode(" ", $x) . "\n";
}
echo "\n";
}
Note that a proper bubble sort algorithm will perform fewer iterations.
Bubble sort is basically simplified into a min() + shift (or sometimes swap) operation that occurs N times. So it's an O(n^2) algorithm.
Since this is for learning purposes I'm going to try to be as verbose as possible.
function getMin(Array &$array): Int {
$min = reset($array);
$minKey = null;
// Find the minimum value
foreach($array as $k => $n) {
if ($n < $min) {
$min = $n;
$minKey = $k;
}
}
// remove the minimum value from the array
$array[$k] = null;
$array = array_filter($array, function ($v) { return $v !== null; });
return $min;
}
$array = [9,7,5,3,0];
foreach ($array as $n => $value) {
// Find the min value in the array from Nth index onward
$min = getMin($array); // get the smallest value in the array and remove it.
$sorted[] = $min; // push it on to the new array
}
var_dump($sorted);
This gives you the expect result:
array(5) {
[0]=>
int(0)
[1]=>
int(3)
[2]=>
int(5)
[3]=>
int(7)
[4]=>
int(9)
}
Of course, this is not the way you would want to implement Bubble Sort, because it's a bit circuitous. Again, it's for educational purposes. You can inspect the $array as it's being modified at each step and the new $sorted as it's being built. Typically you would just swap the min/max values in place and use the same array (keeping track of the keys to rescan the array).
Like this...
// Unsorted $array
$array = [9,7,5,3,0];
// Sort the array
for ($lastKey = $i = 0, $len = count($array); $i < $len; $i++) {
// Scan for minimum value
for ($minKey = $j = $lastKey, $min = $array[$minKey]; $j < $len; $j++) {
if ($array[$j] < $min) {
$minKey = $j;
$min = $array[$j];
}
}
// Swap the values
$swap = $array[$lastKey];
$array[$lastKey] = $min;
$array[$minKey] = $swap;
// Update the scan position
$lastKey++;
}
var_dump($array); // Gives you [0,3,5,7,9]
You are performing unconditional position swapping, but you actually need to check if movement is required.
There is no shortage of tutorials that demonstrate a bubble sort in php. A quick good lead me to this one: https://www.w3resource.com/php-exercises/searching-and-sorting-algorithm/searching-and-sorting-algorithm-exercise-6.php which can be modified for your purposes.
PHP now offers "array destructuring" which means you no longer need to use a temporary holding variable while swapping.
Code: (Demo)
$x = [9,7,5,3,0];
$count = count($x) - 1;
for ($pass = 0; $pass < $count; ++$pass) {
for ($i = 0; $i < $count; ++$i) {
if ($x[$i] > $x[$i + 1]) {
[$x[$i + 1], $x[$i]] = [$x[$i], $x[$i + 1]];
}
$results[] = implode($x);
}
$results[] = "\n";
}
echo implode("\n", $results);
I made a merge sort in python which works fine and I've tried recreating the logic in PHP but it is not working correctly. Here is the python code:
def merge(array):
if len(array) > 1:
arrayL = []
arrayR = []
for i in range(int(len(array)/2)):
arrayL.append(array[i])
for i in range(int(len(array)/2),len(array)):
arrayR.append(array[i])
arrayL = merge(arrayL)
arrayR = merge(arrayR)
left = right = insert = 0
while left < len(arrayL) and right < len(arrayR):
if arrayL[left] < arrayR[right]:
array[insert] = arrayL[left]
left += 1
else:
array[insert] = arrayR[right]
right += 1
insert += 1
while left < len(arrayL):
array[insert] = arrayL[left]
left += 1
insert += 1
while right < len(arrayR):
array[insert] = arrayR[right]
right += 1
insert += 1
return array
And this is from the shell:
>>> merge([23,21,5,111,32,11,7,1,45])
[1, 5, 7, 11, 21, 23, 32, 45, 111]
Here is the PHP code:
function merge($array) {
$arrayLength = count($array);
if ($arrayLength > 1) {
$arrayLeft = array_slice($array, 0, $arrayLength/2);
$arrayRight = array_slice($array, $arrayLength/2);
$arrayLeft = merge($arrayLeft);
$arrayRight = merge($arrayRight);
$left = 0;
$right = 0;
$insert = 0;
while ($left < count($arrayLeft) and $right < count($arrayRight)){
if ($arrayLeft[$left] < $arrayRight[$right]) {
$array[$insert] = $arrayLeft[$left];
$left += 1;
} else {
$array[$insert] = $arrayRight[$right];
$right += 1;
}
$insert += 1;
}
while ($left < count($arrayLeft)) {
$array[$insert] = $arrayLeft[$left];
$left += 1;
$insert += 1;
}
while ($right < count($arrayRight)) {
$array[$insert] = $arrayRight[$right];
$right += 1;
$insert += 1;
}
return $array;
}
}
print_r(merge(array(23,21,5,111,32,11,7,1,45)));
And this is what it outputs:
Array ( [0] => 1 [1] => 5 [2] => 23 [3] => 21 [4] => 32 [5] => 11 [6] => 45 [7] => 45 [8] => 111 )
Any help would be very much appreciated
The return $array; statement should be outside the if scope.
I need a PHP code to find longest contiguous sequence of characters in the string. So if b is coming together for maximum number of times your program should echo b and count
Example string:
aaabababbbbbaaaaabbbbbbbbaa
Output must be:
b 8
Using
- preg_match_all to get sequences of repeating characters,
- array_map along with strlen to get the string length of each sequence
- max to get the biggest value in the array.
Consider the following example:
$string = "aaabababbbbbaaaaabbbbbbbbaa";
preg_match_all('#(\w)\1+#',$string,$matches);
print_r($matches);
Will output
Array
(
[0] => Array
(
[0] => aaa
[1] => bbbbb
[2] => aaaaa
[3] => bbbbbbbb
[4] => aa
)
[1] => Array
(
[0] => a
[1] => b
[2] => a
[3] => b
[4] => a
)
)
Next we get the sizes for each string of repeating characters
$sizes = array_map('strlen', $matches[0]);
print_r($sizes);
Will output
Array
(
[0] => 3
[1] => 5
[2] => 5
[3] => 8
[4] => 2
)
Now let's get the biggest value of the $sizes array
print max($sizes);
Will give us
8
We need the key for the max value to pick up the letter
$maxKey = array_keys($sizes, max($sizes));
print $matches[1][$maxKey[0]];
Will output
b
Since you're looking for continuous sequences:
$string = 'aaabababbbbbaaaaabbbbbbbbaa';
$count = strlen($string);
if ($count > 0)
{
$mostFrequentChar = $curChar = $string[0];
$maxFreq = $curFreq = 1;
for ($i = 1; $i < $count; $i++)
{
if ($string[$i] == $curChar)
{
$curFreq++;
if ($curFreq > $maxFreq)
{
$mostFrequentChar = $curChar;
$maxFreq = $curFreq;
}
}
else
{
$curChar = $string[$i];
$curFreq = 1;
}
}
}
echo $mostFrequentChar . ' ' . $maxFreq;
$string = 'aaabababbbbbaaaaabbbbbbbbaa';
$occurrence = [];
$count = strlen($string);
for ($x = 0; $x < $count; $x++) {
if(isset($ocurrence[$string[$x]])) {
$ocurrence[$string[$x]]++;
} else {
$ocurrence[$string[$x]] = 0;
}
}
var_dump($occurrence);
This should do the trick.
<?php
$x = "aaaaaaabbbbbbbaaaacccccccaaaaaaaaaaaaaaaaabbbbbbaaaaadddddddddddddddddddddddddddddddddd";
$count = strlen($x);
$y =array();
$n =0;
$d =1;
$first = $x{1};
for($j = $d;$j < $count;$j++)
{
if($x{$j} == $first )
{
$y[$j] = $x{$j};
$first = $x{$j};
}
elseif($x{$j} != $first )
{
$y[$j] = ",".$x{$j};
$first = $x{$j};
}
}
$xy = implode("",$y);
$xy1 = explode(",",$xy);
$c_count = count($xy1);
$dg = 1;
for($g = 0;$g < $c_count;$g++)
{
$cnt = strlen($xy1[$g]);
$cntm = $xy1[$g];
$replace = $cntm{1};
if($cnt > $dg)
{
$ab = str_replace($cntm,$replace,$cntm);
$dg = $cnt.".".$ab ;
}
}
echo $dg;
?>
This question already has answers here:
PHP array combinations
(8 answers)
Closed 7 years ago.
Hi Guys i have an array like this
$array1 = array('a','b','c','d)
and i want to combine with output like this
'a,b,c'
'a,b,d'
'a,c,d'
'b,c,d'
The problem is to create a function with a variable number and not multiple variable, can anybody help me?
Make a try
[akshay#localhost tmp]$ cat permutation_comb.php
<?php
function _perm($comb,$arr)
{
$arr_len = count($arr);
$comb = intval($comb);
if ($comb > $arr_len)
{
$p = 0;
}
elseif ($arr_len == $comb)
{
$p = 1;
}
else {
if ($comb >= $arr_len - $comb)
{
$l = $comb+1;
for ($i = $l+1 ; $i <= $arr_len ; $i++)
$l *= $i;
$m = 1;
for ($i = 2 ; $i <= $arr_len-$comb ; $i++)
$m *= $i;
}
else {
$l = ($arr_len-$comb) + 1;
for ($i = $l+1 ; $i <= $arr_len ; $i++)
$l *= $i;
$m = 1;
for ($i = 2 ; $i <= $comb ; $i++)
$m *= $i;
}
}
if(!isset($p)){ $p = $l/$m ; }
$out = array_fill(0, $p, array_fill(0, $comb, '') );
$t = array();
for ($i = 0 ; $i < $comb ; $i++)
$t[$i] = $i;
$out[0] = $t;
for ($i = 1 ; $i < $p ; $i++)
{
if ($t[$comb-1] != count($arr)-1)
{
$t[$comb-1]++;
}
else {
$xx = -1;
for ($j = $comb-2 ; $j >= 0 ; $j--)
if ($t[$j]+1 != $t[$j+1])
{
$xx = $j;
break;
}
if ($xx == -1)
break;
$t[$xx]++;
for ($j = $xx+1 ; $j < $comb ; $j++)
$t[$j] = $t[$xx]+$j-$xx;
}
$out[$i] = $t;
}
for ($i = 0 ; $i < $p ; $i++)
for ($j = 0 ; $j < $comb ; $j++)
$out[$i][$j] = $arr[$out[$i][$j]];
return $out;
}
$Input = array('a','b','c','d');
$output = array_map(function($a){ return implode(",",$a); },_perm(3, $Input));
// Input
print_r($Input);
// Combination output
print_r($output);
?>
Output
[akshay#localhost tmp]$ php permutation_comb.php
Array
(
[0] => a
[1] => b
[2] => c
[3] => d
)
Array
(
[0] => a,b,c
[1] => a,b,d
[2] => a,c,d
[3] => b,c,d
)
To get all possible combination of chars modify calling part of function like below
$output = array();
for($i=1; $i<=count($Input); $i++)
{
$output = array_merge($output, array_map(function($a){ return implode(",",$a); },_perm($i, $Input)) ) ;
}
Which results
[akshay#localhost tmp]$ php permutation_comb.php
Array
(
[0] => a
[1] => b
[2] => c
[3] => d
)
Array
(
[0] => a
[1] => b
[2] => c
[3] => d
[4] => a,b
[5] => a,c
[6] => a,d
[7] => b,c
[8] => b,d
[9] => c,d
[10] => a,b,c
[11] => a,b,d
[12] => a,c,d
[13] => b,c,d
[14] => a,b,c,d
)
At present I have an array of data [0] - [574].
What I would like to do is split this down into a multidimensional array in 25 parts i.e. [0] - [22] as below:
Array
(
[0] =>
[0] => abc
...
[22] => xyz
[1] =>
[0] => abc
...
[22] => xyz
...
}
I assume it can be done using a for loop to split it all up - Ive tried a few methods but havent seemed to quite get there yet!
Thanks
-mango
There is a built-in function for that:
$parts = array_chunk($array, 23);
I've just used dummy data, but you'll get the idea:
// Set up input with dummy data
$input = array();
for ($i = 0; $i < 574; $i++) {
$input[] = $i . 'aaa';
}
$out = array();
for ($i = 0, $j = sizeof($input); $i < $j; $i++) {
$bucket = floor($i / ($j / 25));
if (!isset($out[$bucket])) {
$out[$bucket] = array();
}
$out[$bucket][] = $input[$i];
}
print_r($out);
$array = array();
$chunks = ceil(count($array) / 25);
$new = array_chunk($array, $chunks);