Generate combination array PHP [duplicate] - php

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
)

Related

permutations without repetition in php [duplicate]

I have numbers, from 0 to 8. I would like in result, all possible sets of those numbers, each set should use all numbers, each number can occur only once in a set.
I would like to see solution made in PHP that could print out result. Or, at least, I would like some refreshment in theory of combinatorics, as I have long forgotten it. What is the formula to calculate how many permutations will there be?
Example sets:
0-1-2-3-4-5-6-7-8
0-1-2-3-4-5-6-8-7
0-1-2-3-4-5-8-6-7
0-1-2-3-4-8-5-6-7
0-1-2-3-8-4-5-6-7
0-1-2-8-3-4-5-6-7
and so on...
You're looking for the permutations formula:
nPk = n!/(n-k)!
In your case, you have 9 entries and you want to choose all of them, that's 9P9 = 9! = 362880
You can find a PHP algorithm to permutate in recipe 4.26 of O'Reilly's "PHP Cookbook".
pc_permute(array(0, 1, 2, 3, 4, 5, 7, 8));
Copied in from O'Reilly:
function pc_permute($items, $perms = array( )) {
if (empty($items)) {
print join(' ', $perms) . "\n";
} else {
for ($i = count($items) - 1; $i >= 0; --$i) {
$newitems = $items;
$newperms = $perms;
list($foo) = array_splice($newitems, $i, 1);
array_unshift($newperms, $foo);
pc_permute($newitems, $newperms);
}
}
}
Since PHP 5.5 you can use Generators. Generators save a lot of memory and are way faster (more than half compared to pc_permute()). So if you have any chance of having PHP 5.5 installed, you definitely want Generators.
This snipped is ported from Python: https://stackoverflow.com/a/104436/3745311
function permutations(array $elements)
{
if (count($elements) <= 1) {
yield $elements;
} else {
foreach (permutations(array_slice($elements, 1)) as $permutation) {
foreach (range(0, count($elements) - 1) as $i) {
yield array_merge(
array_slice($permutation, 0, $i),
[$elements[0]],
array_slice($permutation, $i)
);
}
}
}
}
Sample usage:
$list = ['a', 'b', 'c'];
foreach (permutations($list) as $permutation) {
echo implode(',', $permutation) . PHP_EOL;
}
Output:
a,b,c
b,a,c
b,c,a
a,c,b
c,a,b
c,b,a
Since this question often comes up in Google Search results, here's a modified version of the accepted answer that returns all combinations in an array and passes them as a return value of the function.
function pc_permute($items, $perms = array( )) {
if (empty($items)) {
$return = array($perms);
} else {
$return = array();
for ($i = count($items) - 1; $i >= 0; --$i) {
$newitems = $items;
$newperms = $perms;
list($foo) = array_splice($newitems, $i, 1);
array_unshift($newperms, $foo);
$return = array_merge($return, pc_permute($newitems, $newperms));
}
}
return $return;
}
To use:
$value = array('1', '2', '3');
print_r(pc_permute($value));
I've something that You may like
function combination_number($k,$n){
$n = intval($n);
$k = intval($k);
if ($k > $n){
return 0;
} elseif ($n == $k) {
return 1;
} else {
if ($k >= $n - $k){
$l = $k+1;
for ($i = $l+1 ; $i <= $n ; $i++)
$l *= $i;
$m = 1;
for ($i = 2 ; $i <= $n-$k ; $i++)
$m *= $i;
} else {
$l = ($n-$k) + 1;
for ($i = $l+1 ; $i <= $n ; $i++)
$l *= $i;
$m = 1;
for ($i = 2 ; $i <= $k ; $i++)
$m *= $i;
}
}
return $l/$m;
}
function array_combination($le, $set){
$lk = combination_number($le, count($set));
$ret = array_fill(0, $lk, array_fill(0, $le, '') );
$temp = array();
for ($i = 0 ; $i < $le ; $i++)
$temp[$i] = $i;
$ret[0] = $temp;
for ($i = 1 ; $i < $lk ; $i++){
if ($temp[$le-1] != count($set)-1){
$temp[$le-1]++;
} else {
$od = -1;
for ($j = $le-2 ; $j >= 0 ; $j--)
if ($temp[$j]+1 != $temp[$j+1]){
$od = $j;
break;
}
if ($od == -1)
break;
$temp[$od]++;
for ($j = $od+1 ; $j < $le ; $j++)
$temp[$j] = $temp[$od]+$j-$od;
}
$ret[$i] = $temp;
}
for ($i = 0 ; $i < $lk ; $i++)
for ($j = 0 ; $j < $le ; $j++)
$ret[$i][$j] = $set[$ret[$i][$j]];
return $ret;
}
Here is how to use it:
To get the number of combinations:
combination_number(3,10); // returns number of combinations of ten-elements set.
To get all possible combinations:
$mySet = array("A","B","C","D","E","F");
array_combination(3, $mySet); // returns all possible combinations of 3 elements of six-elements set.
Hope You make use of that.
I've ported the Python itertools code listed here (using generators). The advantage over the solutions posted so far is that it allows you to specify r (permutation size).
function permutations($pool, $r = null) {
$n = count($pool);
if ($r == null) {
$r = $n;
}
if ($r > $n) {
return;
}
$indices = range(0, $n - 1);
$cycles = range($n, $n - $r + 1, -1); // count down
yield array_slice($pool, 0, $r);
if ($n <= 0) {
return;
}
while (true) {
$exit_early = false;
for ($i = $r;$i--;$i >= 0) {
$cycles[$i]-= 1;
if ($cycles[$i] == 0) {
// Push whatever is at index $i to the end, move everything back
if ($i < count($indices)) {
$removed = array_splice($indices, $i, 1);
array_push($indices, $removed[0]);
}
$cycles[$i] = $n - $i;
} else {
$j = $cycles[$i];
// Swap indices $i & -$j.
$i_val = $indices[$i];
$neg_j_val = $indices[count($indices) - $j];
$indices[$i] = $neg_j_val;
$indices[count($indices) - $j] = $i_val;
$result = [];
$counter = 0;
foreach ($indices as $indx) {
array_push($result, $pool[$indx]);
$counter++;
if ($counter == $r) break;
}
yield $result;
$exit_early = true;
break;
}
}
if (!$exit_early) {
break; // Outer while loop
}
}
}
It works for me, but no promises!
Example usage:
$result = iterator_to_array(permutations([1, 2, 3, 4], 3));
foreach ($result as $row) {
print implode(", ", $row) . "\n";
}
This is my version of class. This class builds and returns permutated array as result
class Permutation {
private $result;
public function getResult() {
return $this->result;
}
public function permute($source, $permutated=array()) {
if (empty($permutated)){
$this->result = array();
}
if (empty($source)){
$this->result[] = $permutated;
} else {
for($i=0; $i<count($source); $i++){
$new_permutated = $permutated;
$new_permutated[] = $source[$i];
$new_source = array_merge(array_slice($source,0,$i),array_slice($source,$i+1));
$this->permute($new_source, $new_permutated);
}
}
return $this;
}
}
$arr = array(1,2,3,4,5);
$p = new Permutation();
print_r($p->permute($arr)->getResult());
The last three lines to test my class.
This is a simple recursive function that prints all permutations (written in pseudocode)
function rec(n, k) {
if (k == n) {
for i = 0 to n-1
print(perm[i], ' ');
print('\n');
}
else {
for i = 0 to n-1 {
if (not used[i]) {
used[i] = true;
perm[k] = i;
rec(n, k+1);
used[i] = false;
}
}
}
}
And it is called like this:
rec(9, 0);
Lexicographical order. There is no recursion. Almost no limits for array length.
There is no sort. It's running rather fast. It's easy to understand.
Minus: it gives a notice, but you can add a condition to start compare with the second element or error_reporting(0).
$a = array(
1,
2,
3,
4,
5
);
$b = array_reverse($a);
print_r($a);
//here need "br"
while ($a != $b)
{
foreach(array_reverse($a, true) as $k => $v)
{
if ($v < $a[$k + 1])
{
foreach(array_reverse($a, true) as $ka => $val)
{
if ($val > $v) break;
}
$ch = $a[$k];
$a[$k] = $a[$ka];
$a[$ka] = $ch;
$c = array_slice($a, 0, $k + 1);
print_r($a = array_merge($c, array_reverse(array_slice($a, $k + 1))));
//here need "br"
break;
}
}
}
You're basically talking about permutations where both n and k are 9 so you'll have 9! different permutations; see this: http://en.wikipedia.org/wiki/Permutation.
Here is my proposal, hope a little bit clearer than accepted answer.
function permutate($elements, $perm = array(), &$permArray = array())
{
if(empty($elements))
{
array_push($permArray,$perm); return;
}
for($i=0;$i<=count($elements)-1;$i++)
{
array_push($perm,$elements[$i]);
$tmp = $elements; array_splice($tmp,$i,1);
permutate($tmp,$perm,$permArray);
array_pop($perm);
}
return $permArray;
}
and usage:
$p = permutate(array('a','b','c'));
foreach($p as $perm)
print join(",",$perm)."|\n";
//function call
print_r(combinations([1,2,3,4,5,6,7,8,9,10,11,12,13]));
/**
* #param $mainArray
* #param int $size - optional
* #param array $combinations - optional
* #return mixed
*/
function combinations($mainArray, $size = 3, $combinations = [])
{
if (empty($combinations)) {
$combinations = $mainArray;
}
if ($size == 1) {
return str_replace('-','',$combinations);;
}
$newCombination = array();
foreach ($mainArray as $key => $val){
foreach ($combinations as $char) {
if(in_array($val, explode('-', $char))){
continue;
}
$newCombination[] = $val . '-' . $char;
}
}
return combinations($mainArray, $size - 1, $newCombination);
}
//========================= Next solution ==================================
function sampling($chars, $size, $combinations = array()) {
# if it's the first iteration, the first set
# of combinations is the same as the set of characters
if (empty($combinations)) {
$combinations = $chars;
}
# we're done if we're at size 1
if ($size == 1) {
return $combinations;
}
# initialise array to put new values in
$new_combinations = array();
# loop through existing combinations and character set to create strings
foreach ($combinations as $combination) {
foreach ($chars as $char) {
$new_combinations[] = $combination .'-'. $char ;
}
}
# call same function again for the next iteration
return $this->sampling($chars, $size - 1, $new_combinations);
}
function array_has_dupes($array) {
return count($array) !== count(array_unique($array));
}
function total() {
// Generate ticket price
$arrfinal = array();
// combinations
$chars = array(1,2,3,4,5,6,7,8,9,10,11,12,13); // for 10 digits
$combinations = $this->sampling($chars, 3);
//print_r($combinations); //exit;
foreach($combinations as $key => $val)
{
$arr = explode('-', $val);//str_split($val);
if(!$this->array_has_dupes($arr)){
$arrfinal[] = str_replace('-', '', $val);
}
}
echo '<pre>'; print_r($arrfinal); echo '</pre>';
}
Simple solution using recursion
function filterElement($element){
if(is_array($element[0])){
return $element[0];
}
# base case
return $element;
}
function permutation($input, $path){
// base case 1
if(count($input) == 0){
return [$path];
}
$output = [];
foreach($input as $index => $num){ # 1, 2,3, 4
$copyPath = $path; # copy the path - []
$copyPath[] = $num; # append the number [1]
# remove the current number
$inputLocal = $input;
unset($inputLocal[$index]); # [2, 3, 4]
$permute = permutation($inputLocal, $copyPath); # call [2, 3, 4], [1]
# for all element find add to output
foreach($permute as $ele){
# filter ouput
$output[] = filterElement($ele);
}
}
return $output;
}
print_r(permutation([1,2,3,4], []));
output
Array
(
[0] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
)
[1] => Array
(
[0] => 1
[1] => 2
[2] => 4
[3] => 3
)
[2] => Array
(
[0] => 1
[1] => 3
[2] => 2
[3] => 4
)
[3] => Array
(
[0] => 1
[1] => 3
[2] => 4
[3] => 2
)
[4] => Array
(
[0] => 1
[1] => 4
[2] => 2
[3] => 3
)
[5] => Array
(
[0] => 1
[1] => 4
[2] => 3
[3] => 2
)
[6] => Array
(
[0] => 2
[1] => 1
[2] => 3
[3] => 4
)
[7] => Array
(
[0] => 2
[1] => 1
[2] => 4
[3] => 3
)
[8] => Array
(
[0] => 2
[1] => 3
[2] => 1
[3] => 4
)
[9] => Array
(
[0] => 2
[1] => 3
[2] => 4
[3] => 1
)
[10] => Array
(
[0] => 2
[1] => 4
[2] => 1
[3] => 3
)
[11] => Array
(
[0] => 2
[1] => 4
[2] => 3
[3] => 1
)
[12] => Array
(
[0] => 3
[1] => 1
[2] => 2
[3] => 4
)
[13] => Array
(
[0] => 3
[1] => 1
[2] => 4
[3] => 2
)
[14] => Array
(
[0] => 3
[1] => 2
[2] => 1
[3] => 4
)
[15] => Array
(
[0] => 3
[1] => 2
[2] => 4
[3] => 1
)
[16] => Array
(
[0] => 3
[1] => 4
[2] => 1
[3] => 2
)
[17] => Array
(
[0] => 3
[1] => 4
[2] => 2
[3] => 1
)
[18] => Array
(
[0] => 4
[1] => 1
[2] => 2
[3] => 3
)
[19] => Array
(
[0] => 4
[1] => 1
[2] => 3
[3] => 2
)
[20] => Array
(
[0] => 4
[1] => 2
[2] => 1
[3] => 3
)
[21] => Array
(
[0] => 4
[1] => 2
[2] => 3
[3] => 1
)
[22] => Array
(
[0] => 4
[1] => 3
[2] => 1
[3] => 2
)
[23] => Array
(
[0] => 4
[1] => 3
[2] => 2
[3] => 1
)
)

i need a PHP code to find longest contiguous sequence of characters in the string

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;
?>

Is my number not good enough?

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.

Permutations - all possible sets of numbers

I have numbers, from 0 to 8. I would like in result, all possible sets of those numbers, each set should use all numbers, each number can occur only once in a set.
I would like to see solution made in PHP that could print out result. Or, at least, I would like some refreshment in theory of combinatorics, as I have long forgotten it. What is the formula to calculate how many permutations will there be?
Example sets:
0-1-2-3-4-5-6-7-8
0-1-2-3-4-5-6-8-7
0-1-2-3-4-5-8-6-7
0-1-2-3-4-8-5-6-7
0-1-2-3-8-4-5-6-7
0-1-2-8-3-4-5-6-7
and so on...
You're looking for the permutations formula:
nPk = n!/(n-k)!
In your case, you have 9 entries and you want to choose all of them, that's 9P9 = 9! = 362880
You can find a PHP algorithm to permutate in recipe 4.26 of O'Reilly's "PHP Cookbook".
pc_permute(array(0, 1, 2, 3, 4, 5, 7, 8));
Copied in from O'Reilly:
function pc_permute($items, $perms = array( )) {
if (empty($items)) {
print join(' ', $perms) . "\n";
} else {
for ($i = count($items) - 1; $i >= 0; --$i) {
$newitems = $items;
$newperms = $perms;
list($foo) = array_splice($newitems, $i, 1);
array_unshift($newperms, $foo);
pc_permute($newitems, $newperms);
}
}
}
Since PHP 5.5 you can use Generators. Generators save a lot of memory and are way faster (more than half compared to pc_permute()). So if you have any chance of having PHP 5.5 installed, you definitely want Generators.
This snipped is ported from Python: https://stackoverflow.com/a/104436/3745311
function permutations(array $elements)
{
if (count($elements) <= 1) {
yield $elements;
} else {
foreach (permutations(array_slice($elements, 1)) as $permutation) {
foreach (range(0, count($elements) - 1) as $i) {
yield array_merge(
array_slice($permutation, 0, $i),
[$elements[0]],
array_slice($permutation, $i)
);
}
}
}
}
Sample usage:
$list = ['a', 'b', 'c'];
foreach (permutations($list) as $permutation) {
echo implode(',', $permutation) . PHP_EOL;
}
Output:
a,b,c
b,a,c
b,c,a
a,c,b
c,a,b
c,b,a
Since this question often comes up in Google Search results, here's a modified version of the accepted answer that returns all combinations in an array and passes them as a return value of the function.
function pc_permute($items, $perms = array( )) {
if (empty($items)) {
$return = array($perms);
} else {
$return = array();
for ($i = count($items) - 1; $i >= 0; --$i) {
$newitems = $items;
$newperms = $perms;
list($foo) = array_splice($newitems, $i, 1);
array_unshift($newperms, $foo);
$return = array_merge($return, pc_permute($newitems, $newperms));
}
}
return $return;
}
To use:
$value = array('1', '2', '3');
print_r(pc_permute($value));
I've something that You may like
function combination_number($k,$n){
$n = intval($n);
$k = intval($k);
if ($k > $n){
return 0;
} elseif ($n == $k) {
return 1;
} else {
if ($k >= $n - $k){
$l = $k+1;
for ($i = $l+1 ; $i <= $n ; $i++)
$l *= $i;
$m = 1;
for ($i = 2 ; $i <= $n-$k ; $i++)
$m *= $i;
} else {
$l = ($n-$k) + 1;
for ($i = $l+1 ; $i <= $n ; $i++)
$l *= $i;
$m = 1;
for ($i = 2 ; $i <= $k ; $i++)
$m *= $i;
}
}
return $l/$m;
}
function array_combination($le, $set){
$lk = combination_number($le, count($set));
$ret = array_fill(0, $lk, array_fill(0, $le, '') );
$temp = array();
for ($i = 0 ; $i < $le ; $i++)
$temp[$i] = $i;
$ret[0] = $temp;
for ($i = 1 ; $i < $lk ; $i++){
if ($temp[$le-1] != count($set)-1){
$temp[$le-1]++;
} else {
$od = -1;
for ($j = $le-2 ; $j >= 0 ; $j--)
if ($temp[$j]+1 != $temp[$j+1]){
$od = $j;
break;
}
if ($od == -1)
break;
$temp[$od]++;
for ($j = $od+1 ; $j < $le ; $j++)
$temp[$j] = $temp[$od]+$j-$od;
}
$ret[$i] = $temp;
}
for ($i = 0 ; $i < $lk ; $i++)
for ($j = 0 ; $j < $le ; $j++)
$ret[$i][$j] = $set[$ret[$i][$j]];
return $ret;
}
Here is how to use it:
To get the number of combinations:
combination_number(3,10); // returns number of combinations of ten-elements set.
To get all possible combinations:
$mySet = array("A","B","C","D","E","F");
array_combination(3, $mySet); // returns all possible combinations of 3 elements of six-elements set.
Hope You make use of that.
I've ported the Python itertools code listed here (using generators). The advantage over the solutions posted so far is that it allows you to specify r (permutation size).
function permutations($pool, $r = null) {
$n = count($pool);
if ($r == null) {
$r = $n;
}
if ($r > $n) {
return;
}
$indices = range(0, $n - 1);
$cycles = range($n, $n - $r + 1, -1); // count down
yield array_slice($pool, 0, $r);
if ($n <= 0) {
return;
}
while (true) {
$exit_early = false;
for ($i = $r;$i--;$i >= 0) {
$cycles[$i]-= 1;
if ($cycles[$i] == 0) {
// Push whatever is at index $i to the end, move everything back
if ($i < count($indices)) {
$removed = array_splice($indices, $i, 1);
array_push($indices, $removed[0]);
}
$cycles[$i] = $n - $i;
} else {
$j = $cycles[$i];
// Swap indices $i & -$j.
$i_val = $indices[$i];
$neg_j_val = $indices[count($indices) - $j];
$indices[$i] = $neg_j_val;
$indices[count($indices) - $j] = $i_val;
$result = [];
$counter = 0;
foreach ($indices as $indx) {
array_push($result, $pool[$indx]);
$counter++;
if ($counter == $r) break;
}
yield $result;
$exit_early = true;
break;
}
}
if (!$exit_early) {
break; // Outer while loop
}
}
}
It works for me, but no promises!
Example usage:
$result = iterator_to_array(permutations([1, 2, 3, 4], 3));
foreach ($result as $row) {
print implode(", ", $row) . "\n";
}
This is my version of class. This class builds and returns permutated array as result
class Permutation {
private $result;
public function getResult() {
return $this->result;
}
public function permute($source, $permutated=array()) {
if (empty($permutated)){
$this->result = array();
}
if (empty($source)){
$this->result[] = $permutated;
} else {
for($i=0; $i<count($source); $i++){
$new_permutated = $permutated;
$new_permutated[] = $source[$i];
$new_source = array_merge(array_slice($source,0,$i),array_slice($source,$i+1));
$this->permute($new_source, $new_permutated);
}
}
return $this;
}
}
$arr = array(1,2,3,4,5);
$p = new Permutation();
print_r($p->permute($arr)->getResult());
The last three lines to test my class.
This is a simple recursive function that prints all permutations (written in pseudocode)
function rec(n, k) {
if (k == n) {
for i = 0 to n-1
print(perm[i], ' ');
print('\n');
}
else {
for i = 0 to n-1 {
if (not used[i]) {
used[i] = true;
perm[k] = i;
rec(n, k+1);
used[i] = false;
}
}
}
}
And it is called like this:
rec(9, 0);
Lexicographical order. There is no recursion. Almost no limits for array length.
There is no sort. It's running rather fast. It's easy to understand.
Minus: it gives a notice, but you can add a condition to start compare with the second element or error_reporting(0).
$a = array(
1,
2,
3,
4,
5
);
$b = array_reverse($a);
print_r($a);
//here need "br"
while ($a != $b)
{
foreach(array_reverse($a, true) as $k => $v)
{
if ($v < $a[$k + 1])
{
foreach(array_reverse($a, true) as $ka => $val)
{
if ($val > $v) break;
}
$ch = $a[$k];
$a[$k] = $a[$ka];
$a[$ka] = $ch;
$c = array_slice($a, 0, $k + 1);
print_r($a = array_merge($c, array_reverse(array_slice($a, $k + 1))));
//here need "br"
break;
}
}
}
You're basically talking about permutations where both n and k are 9 so you'll have 9! different permutations; see this: http://en.wikipedia.org/wiki/Permutation.
Here is my proposal, hope a little bit clearer than accepted answer.
function permutate($elements, $perm = array(), &$permArray = array())
{
if(empty($elements))
{
array_push($permArray,$perm); return;
}
for($i=0;$i<=count($elements)-1;$i++)
{
array_push($perm,$elements[$i]);
$tmp = $elements; array_splice($tmp,$i,1);
permutate($tmp,$perm,$permArray);
array_pop($perm);
}
return $permArray;
}
and usage:
$p = permutate(array('a','b','c'));
foreach($p as $perm)
print join(",",$perm)."|\n";
//function call
print_r(combinations([1,2,3,4,5,6,7,8,9,10,11,12,13]));
/**
* #param $mainArray
* #param int $size - optional
* #param array $combinations - optional
* #return mixed
*/
function combinations($mainArray, $size = 3, $combinations = [])
{
if (empty($combinations)) {
$combinations = $mainArray;
}
if ($size == 1) {
return str_replace('-','',$combinations);;
}
$newCombination = array();
foreach ($mainArray as $key => $val){
foreach ($combinations as $char) {
if(in_array($val, explode('-', $char))){
continue;
}
$newCombination[] = $val . '-' . $char;
}
}
return combinations($mainArray, $size - 1, $newCombination);
}
//========================= Next solution ==================================
function sampling($chars, $size, $combinations = array()) {
# if it's the first iteration, the first set
# of combinations is the same as the set of characters
if (empty($combinations)) {
$combinations = $chars;
}
# we're done if we're at size 1
if ($size == 1) {
return $combinations;
}
# initialise array to put new values in
$new_combinations = array();
# loop through existing combinations and character set to create strings
foreach ($combinations as $combination) {
foreach ($chars as $char) {
$new_combinations[] = $combination .'-'. $char ;
}
}
# call same function again for the next iteration
return $this->sampling($chars, $size - 1, $new_combinations);
}
function array_has_dupes($array) {
return count($array) !== count(array_unique($array));
}
function total() {
// Generate ticket price
$arrfinal = array();
// combinations
$chars = array(1,2,3,4,5,6,7,8,9,10,11,12,13); // for 10 digits
$combinations = $this->sampling($chars, 3);
//print_r($combinations); //exit;
foreach($combinations as $key => $val)
{
$arr = explode('-', $val);//str_split($val);
if(!$this->array_has_dupes($arr)){
$arrfinal[] = str_replace('-', '', $val);
}
}
echo '<pre>'; print_r($arrfinal); echo '</pre>';
}
Simple solution using recursion
function filterElement($element){
if(is_array($element[0])){
return $element[0];
}
# base case
return $element;
}
function permutation($input, $path){
// base case 1
if(count($input) == 0){
return [$path];
}
$output = [];
foreach($input as $index => $num){ # 1, 2,3, 4
$copyPath = $path; # copy the path - []
$copyPath[] = $num; # append the number [1]
# remove the current number
$inputLocal = $input;
unset($inputLocal[$index]); # [2, 3, 4]
$permute = permutation($inputLocal, $copyPath); # call [2, 3, 4], [1]
# for all element find add to output
foreach($permute as $ele){
# filter ouput
$output[] = filterElement($ele);
}
}
return $output;
}
print_r(permutation([1,2,3,4], []));
output
Array
(
[0] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
)
[1] => Array
(
[0] => 1
[1] => 2
[2] => 4
[3] => 3
)
[2] => Array
(
[0] => 1
[1] => 3
[2] => 2
[3] => 4
)
[3] => Array
(
[0] => 1
[1] => 3
[2] => 4
[3] => 2
)
[4] => Array
(
[0] => 1
[1] => 4
[2] => 2
[3] => 3
)
[5] => Array
(
[0] => 1
[1] => 4
[2] => 3
[3] => 2
)
[6] => Array
(
[0] => 2
[1] => 1
[2] => 3
[3] => 4
)
[7] => Array
(
[0] => 2
[1] => 1
[2] => 4
[3] => 3
)
[8] => Array
(
[0] => 2
[1] => 3
[2] => 1
[3] => 4
)
[9] => Array
(
[0] => 2
[1] => 3
[2] => 4
[3] => 1
)
[10] => Array
(
[0] => 2
[1] => 4
[2] => 1
[3] => 3
)
[11] => Array
(
[0] => 2
[1] => 4
[2] => 3
[3] => 1
)
[12] => Array
(
[0] => 3
[1] => 1
[2] => 2
[3] => 4
)
[13] => Array
(
[0] => 3
[1] => 1
[2] => 4
[3] => 2
)
[14] => Array
(
[0] => 3
[1] => 2
[2] => 1
[3] => 4
)
[15] => Array
(
[0] => 3
[1] => 2
[2] => 4
[3] => 1
)
[16] => Array
(
[0] => 3
[1] => 4
[2] => 1
[3] => 2
)
[17] => Array
(
[0] => 3
[1] => 4
[2] => 2
[3] => 1
)
[18] => Array
(
[0] => 4
[1] => 1
[2] => 2
[3] => 3
)
[19] => Array
(
[0] => 4
[1] => 1
[2] => 3
[3] => 2
)
[20] => Array
(
[0] => 4
[1] => 2
[2] => 1
[3] => 3
)
[21] => Array
(
[0] => 4
[1] => 2
[2] => 3
[3] => 1
)
[22] => Array
(
[0] => 4
[1] => 3
[2] => 1
[3] => 2
)
[23] => Array
(
[0] => 4
[1] => 3
[2] => 2
[3] => 1
)
)

php array iteration - unset

Back to my original question, on how to check if the next elem starts with a space, if it does, concatenate it to the previous elem. how would you deal with cases where the array has multiple levels.
[1] => Array (
[1] => Packages
[2] => Sources
[3] => Reading package
[4] => Sources
[5] => More Sources
[6] => volatile Sources
[7] => volatile
)
To output:
[2] => Array (
[1] => Packages
[2] => Sources Reading package Sources More Sources
[6] => volatile Sources volatile
)
Will do it for the first space.
for($i = 0; $i < count($array); $i++){
if($array[$i][0] == ' '){
if($i > 0){
$array[$i-1] .= $array[$i];
unset($array[$i]);
}
}
}
$t = array ( 'Packages',
'Sources',
' Reading package',
' Sources',
' More Sources',
'volatile Sources',
' volatile'
);
$n = '';
foreach($t as $k => $v) {
if (substr($v,0,1) == ' ') {
$t[$n] .= $v;
unset($t[$k]);
} else {
$n = $k;
}
}
var_dump($t);
If you can be sure that a particular character (e.g. |) is not present in any of your elements, you can do something like this:
$array = explode('|',str_replace('| ',' ',implode('|',$array)));
This should work (untested) :
$size = count($array);
for($i = 0; $i < $size; $i++){
$space = true;
for($j = $i + 1; $j < $size && $space; $j++) {
$space = $array[$j][0] == ' ';
if($space){
$array[$i] .= $array[$j];
unset($array[$j]);
}
}
}

Categories