How can I convert patterns into all of their possible combinations - php

I'm trying to convert numbers that are using variables into all of their possible results. Below are a few examples using US telephone numbers (sample numbers):
203618723[149] 7049164XXX 651280477[5-9] 203618717[01-7]
20361872[149]X
The output should be an array like:
2036187231 2036187234 2036187239 7049164000 7049164001 7049164002 .. 7049164010 7049164011 .. 7049164100 7047167101 .. 6512804775 6512804776 6512804777 6512804778 6512804779 2036187170 2036187171 2036187172 2036187273 .. 2036187210 2036187211 2036187212 .. 2036187240 2036187241 2036187242 .. 2036187290 2036187291 ..
What I have so far handles the last digit being a variable but fails with anything before that being one and doesn't handle ranges, I've been beating my head against the wall on this, any pointers or assistance would be appreciated.
echo "<pre>";
print_r(str_split((string)$extended['168']['pattern']));
echo "</pre>";
$string = str_split((string)$extended['9200']['pattern']);
$newnumber['168'] = array();
$c = 0;
$append = 0;
foreach($string as $number) {
if($number == "[") {
$append = 1;
$c2 = 0;
continue;
} elseif ($number == "]") {
$append = 0;
unset($c2);
continue;
} elseif ($number == "X") {
$newnumber['168'][$c]['0'] = 0;
$newnumber['168'][$c]['1'] = 1;
$newnumber['168'][$c]['2'] = 2;
$newnumber['168'][$c]['3'] = 3;
$newnumber['168'][$c]['4'] = 4;
$newnumber['168'][$c]['5'] = 5;
$newnumber['168'][$c]['6'] = 6;
$newnumber['168'][$c]['7'] = 7;
$newnumber['168'][$c]['8'] = 8;
$newnumber['168'][$c]['9'] = 9;
} else {
if($append == 1) {
if($number == "-") {
} else {
$newnumber['168'][$c][$c2] = $number;
$c2++;
continue;
}
} else {
$newnumber['168'][$c] = $number;
}
}
$c++;
}
echo "<pre>";
print_r($newnumber['168']);
echo "</pre>";
/*foreach ($newnumber['168'] as $num) {
if(is_array($num)) {
foreach ($num as $num1) {
$numbers[] = $numstart . $num1;
}
} else {
$numstart .= $num;
}
}*/
echo "<pre>";
print_r($numbers);
echo "</pre>";
My output is:
Array
(
[0] => 2
[1] => 0
[2] => 3
[3] => 6
[4] => 1
[5] => 8
[6] => 7
[7] => 2
[8] => 3
[9] => [
[10] => 1
[11] => 4
[12] => 9
[13] => ]
)
Array
(
[0] => 7
[1] => 0
[2] => 4
[3] => 9
[4] => 1
[5] => 6
[6] => 4
[7] => 9
[8] => Array
(
[0] => 0
[1] => 1
[2] => 2
[3] => 3
[4] => 4
[5] => 5
[6] => 6
[7] => 7
[8] => 8
[9] => 9
)
[9] => Array
(
[0] => 0
[1] => 1
[2] => 2
[3] => 3
[4] => 4
[5] => 5
[6] => 6
[7] => 7
[8] => 8
[9] => 9
)
)
Array
(
[0] => 704916490
[1] => 704916491
[2] => 704916492
[3] => 704916493
[4] => 704916494
[5] => 704916495
[6] => 704916496
[7] => 704916497
[8] => 704916498
[9] => 704916499
[10] => 704916490
[11] => 704916491
[12] => 704916492
[13] => 704916493
[14] => 704916494
[15] => 704916495
[16] => 704916496
[17] => 704916497
[18] => 704916498
[19] => 704916499
)

Okay so this is probably NOT the cleanest way to do this but just in case anybody needs to do anything similar in the future:
This only works for 10 digit numbers and I haven't built in any error handling yet but that cleanup will start now.
$string = str_split((string)$value['pattern']);
$newnumber[$key] = array();
$c = 0;
$append = 0;
foreach($string as $number) {
if($number == "[") {
$append = 1;
$c2 = 0;
continue;
} elseif ($number == "]") {
$append = 0;
unset($c2);
continue;
} elseif ($number == ".") {
continue;
} elseif ($number == "X") {
$newnumber[$key][$c]['0'] = 0;
$newnumber[$key][$c]['1'] = 1;
$newnumber[$key][$c]['2'] = 2;
$newnumber[$key][$c]['3'] = 3;
$newnumber[$key][$c]['4'] = 4;
$newnumber[$key][$c]['5'] = 5;
$newnumber[$key][$c]['6'] = 6;
$newnumber[$key][$c]['7'] = 7;
$newnumber[$key][$c]['8'] = 8;
$newnumber[$key][$c]['9'] = 9;
} else {
if($append == 1) {
if($number == "-") {
$dash = 1;
continue;
} elseif ($dash == 1) {
$s = $newnumber[$key][$c][$c2-1];
for ($s = $s+1; $s <= $number; $s++) {
$newnumber[$key][$c][$c2] = $s;
$c2++;
}
unset($s);
unset($dash);
} else {
$newnumber[$key][$c][$c2] = $number;
$c2++;
continue;
}
} else {
$newnumber[$key][$c][] = $number;
}
}
$c++;
}
/*echo "<pre>";
print_r($newnumber[$key]);
echo "</pre>";*/
$numbers = array();
//Process first digit
$d1 = 0;
$n1arr = array();
foreach ($newnumber[$key][0] as $digit1) {
$n1arr[$d1] .= $digit1;
$d1++;
}
$d2 = 0;
$n2arr = array();
foreach ($newnumber[$key][1] as $digit2) {
foreach ($n1arr as $n1n) {
$n2arr[$d2] = $n1n . $digit2;
$d2++;
}
}
$d3 = 0;
$n3arr = array();
foreach ($newnumber[$key][2] as $digit3) {
foreach ($n2arr as $n2n) {
$n3arr[$d3] = $n2n . $digit3;
$d3++;
}
}
$d4 = 0;
$n4arr = array();
foreach ($newnumber[$key][3] as $digit4) {
foreach ($n3arr as $n3n) {
$n4arr[$d4] = $n3n . $digit4;
$d4++;
}
}
$d5 = 0;
$n5arr = array();
foreach ($newnumber[$key][4] as $digit5) {
foreach ($n4arr as $n4n) {
$n5arr[$d5] = $n4n . $digit5;
$d5++;
}
}
$d6 = 0;
$n6arr = array();
foreach ($newnumber[$key][5] as $digit6) {
foreach ($n5arr as $n5n) {
$n6arr[$d6] = $n5n . $digit6;
$d6++;
}
}
$d7 = 0;
$n7arr = array();
foreach ($newnumber[$key][6] as $digit7) {
foreach ($n6arr as $n6n) {
$n7arr[$d7] = $n6n . $digit7;
$d7++;
}
}
$d8 = 0;
$n8arr = array();
foreach ($newnumber[$key][7] as $digit8) {
foreach ($n7arr as $n7n) {
$n8arr[$d8] = $n7n . $digit8;
$d8++;
}
}
$d9 = 0;
$n9arr = array();
foreach ($newnumber[$key][8] as $digit9) {
foreach ($n8arr as $n8n) {
$n9arr[$d9] = $n8n . $digit9;
$d9++;
}
}
$d10 = 0;
$n10arr = array();
foreach ($newnumber[$key][9] as $digit10) {
foreach ($n9arr as $n9n) {
$n10arr[$d10]['pattern'] = $n9n . $digit10;
$n10arr[$d10]['description'] = $extended[$key]['description'];
$n10arr[$d10]['translation'] = $extended[$key]['translation'];
$n10arr[$d10]['prefix'] = $extended[$key]['prefix'];
$d10++;
}
}

Related

Random Unique IDs for Secret Santa/Kris Kindle

I gat a database table, which filed in with names and unique EntryIDs.
My goal is to Match every unique EntryID to another Unique EntryID.
I all ready tried this post here but it doesn't work for that what I want.
Here is my code:
$query = "SELECT * FROM `names`";
$stmt = $db->prepare($query);
$stmt->execute();
$result = $stmt->get_result();
$stmt->close();
while($obj = $result->fetch_object()) {
$id = $obj->entryid;
if (isset($matches)) {
$matches[$id] = randomizer_II($id, $matches);
}
else {
$matches[$id] = randomizer_I($id);
}
}
print_r($matches);
$db->close();
FUNCTION randomizer_I($id) {
$random = rand(1,4);
if ($id != $random) {
return $random;
}
else {
randomizer_I($id);
}
}
FUNCTION randomizer_II($id, $matches) {
$random = rand(1,4);
if ($id != $random) {
if (!in_array($random, $matches)) {
return $random;
}
else {
randomizer_II($id, $matches);
}
}
else {
randomizer_II($id, $matches);
}
}
But all I get is for example:
Array ( [1] => 3 [2] => 4 [3] => [4] => 2 )
But this have an empty array spot in it or I get Following Error:
Fatal error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 262144 bytes) in C:\xampp\htdocs\Wichteln\index.php on line 43
What I expected (example):
Array ( [1] => 3 [2] => 4 [3] => 1 [4] => 2 ) or Array ( [1] => 4 [2] => 1 [3] => 2 [4] => 3 )
Something like that.
What have I done wrong here?
I gat it.
Some times PHP is a bi*** xD
$count = 0;
$collectNumbers = [];
while ($count < 4) {
for ($i = 0; $i < 4; $i++) {
$rand = mt_rand(0, 3);
if ($count == $rand) {
while ($count == $rand) {
$rand = mt_rand(0, 3);
}
}
$collectNumbers[] = $rand;
}
$unique = array_unique($collectNumbers);
$count = count($unique);
}
$finalArray = array_slice($unique, 0, 4);
print_r($finalArray);
echo("<br>");
foreach ($finalArray as $key => $value) {
echo "".(intval($key)+1)." => ".(intval($value)+1) ."<br>";
}
Here is the resault:
Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 0 )
1 => 2
2 => 3
3 => 4
4 => 1
No duplicates like [0] => 0 or 1 => 1
Works fine now.

Sort Array by time in the value while maintaining the name

I have the following array:
Array ( [10] => 06:30pm [20] => 04:00pm [30] => 05:15pm )
The number in [] is the id and follow by the value is time. I need to sort this array by time while maintaining the id like this
Array ( [20] => 04:00pm [30] => 05:15pm [10] => 06:30pm )
Please also note that the time can be in AM or PM also.
I would then need to extract the id in the [] as comma separated value.
Can anyone help?
try this
<?php
$time= ['10' => '06:30pm','20' => '04:00pm', '30' => '05:15am'];
$temp_time=array();
foreach ($time as $key => $value) {
if(sizeof(explode("pm", $value))>1){
$data=explode(":", $value);
$data[0]=(int)$data[0]+12;
$value=$data[0].':'.$data[1];
}else{
$data=explode(":", $value);
if($data[0]=='12'){
$value='00:'.$data[1];
}else{
$value=$data[0].':'.$data[1];
}
}
$temp_time+=[$key => $value];
}
asort($temp_time);
$new_time=array();
foreach ($temp_time as $key => $value) {
$new_time+=[$key => $time[$key]];
}
print_r($new_time);
output:
Array ( [30] => 05:15am [20] => 04:00pm [10] => 06:30pm )
Here is the solution:
$source_array = array(10 => '06:30pm', 20 => '04:00pm', 30 => '05:15pm', 40 => '04:00am');
function arr_swap_elements(&$arr, $a_index, $b_index) {
$tmp = $arr[$a_index];
$arr[$a_index] = $arr[$b_index];
$arr[$b_index] = $tmp;
return;
}
function arr_sort_by_time(&$source_array, $start_index = 0, $arr_keys = null, $arr_len = null) {
if (is_null($arr_keys)) {
$arr_keys = array_keys($source_array);
}
if (is_null($arr_len)) {
$arr_len = count($source_array);
}
for ($i = $start_index; $i < $arr_len; $i++) {
if ($i > 0) {
if (strtotime($source_array[$arr_keys[$i]]) > strtotime($source_array[$arr_keys[$i - 1]])) {
$was_swapped = true;
arr_swap_elements($source_array, $arr_keys[$i], $arr_keys[$i - 1]);
}
}
}
if ($start_index + 1 < $arr_len) {
arr_sort_by_time($source_array, $start_index + 1, $arr_keys, $arr_len);
}
}
arr_sort_by_time($source_array);
var_dump($source_array);

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
)
)

how to merge some elements array in php? [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
example:
Array (
[0] => 35
[1] => -
[2] => 59
[3] => *
[4] => 2
[5] => /
[6] => 27
[7] => *
[8] => 2 )
then calculated:
59*2=118
and the new array is:
Array (
[0] => 35
[1] => -
[2] => 118
[3] => /
[4] => 27
[5] => *
[6] => 2 )
this is my original source :
input ($_POST['numbers']) is a string, LIKE:
65*6/6+5-5
class calculator {
//property
private $str='';
private $len=0;
private $ar_str=array();
private $ar_design=array();
private $ar_sum=array();
private $ar_min=array();
private $ar_mult=array();
private $ar_divi=array();
//Method
public function __construct($str1=''){
$this->str=$str1;
$this->len=strlen($this->str);
$this->ar_str=str_split($this->str);
if($this->ar_str[0] == '+' ||
$this->ar_str[0] == '-' ||
$this->ar_str[0] == '*' ||
$this->ar_str[0] == '/' ||
$this->ar_str[$this->len-1] == '+' ||
$this->ar_str[$this->len-1] == '-' ||
$this->ar_str[$this->len-1] == '*' ||
$this->ar_str[$this->len-1] == '/'
){
exit("Syntax error!");
}else if(!filter_var($this->ar_str[0], FILTER_VALIDATE_INT)){
exit("just use numbers and 4 operators!");
}
$this->ar_design[0]=$this->ar_str[0];
//start for
$j=1;
for($i=1;$i<$this->len;$i++){
if($this->ar_str[$i] == '+' || $this->ar_str[$i] == '-' || $this->ar_str[$i] == '*' || $this->ar_str[$i] == '/'){
if($this->ar_str[$i-1] == '+' || $this->ar_str[$i-1] == '-' || $this->ar_str[$i-1] == '*' || $this->ar_str[$i-1] == '/'){
exit("Syntax error!");
}else{
$this->ar_design[$j]=$this->ar_str[$i];
$j++;
}
}else if(filter_var($this->ar_str[$i], FILTER_VALIDATE_INT)){
if($this->ar_str[$i-1] == '+' || $this->ar_str[$i-1] == '-' || $this->ar_str[$i-1] == '*' || $this->ar_str[$i-1] == '/'){
$this->ar_design[$j]=$this->ar_str[$i];
}else{
$j--;
$this->ar_design[$j]=$this->ar_design[$j].$this->ar_str[$i];
}
$j++;
}else{
exit("just use numbers and 4 operators!");
}
}//end of for
print_r($this->ar_design);//array this array should be calculate!!!!!
}//end construct
}
if(isset($_POST['numbers'])){
$num_str=trim($_POST['numbers']);
if($num_str!=''){
$num_str = str_replace('`','+',$num_str);
new calculator($num_str);
}
}
i could find the answer:
$this->len_d=count($this->ar_design);
$this->ar_cal[0]=$this->ar_design[0];
$k=1;
for($i=1;$i<$this->len_d;$i++){
if($this->ar_design[$i] == '*'){
$k--;
$this->ar_cal[$k]=$this->ar_design[$i-1]*$this->ar_design[$i+1];
$i++;
}else{
$this->ar_cal[$k]=$this->ar_design[$i];
}
$k++;
}
print_r($this->ar_cal);
You could do it with a loop and then executing it.
$array=Array (35,'-',59,'*',2,'/',27,'*',2);
foreach ($array as $value){
$stringify.=$value;
}
echo 'Calculation looks like this: '.$stringify.'<br/>';
function calculate( $math ){
$calc = create_function("", "return (" .$math. ");" );
return $calc();
}
echo calculate($stringify);
could be imroved, for example by validating the input...
Working example: http://allanthya.net/arrcalc2.php
<?php
$array = array( 35, '-', 59, '*', 2, '/', 27, '*', 2 );
print_r($array);
echo "<p>";
while ( true ) {
$div = array_keys($array, '/');
$mult = array_keys($array, '*');
$add = array_keys($array, '+');
$sub = array_keys($array, '-');
if ( count($div) >= 1 ) {
$index = $div[0];
$op1 = $array[$index-1];
$op2 = $array[$index+1];
$array[$index] = $op1 / $op2;
unset($array[$index-1]);
unset($array[$index+1]);
$array = array_values($array);
continue;
} else if ( count($mult) >= 1 ) {
$index = $mult[0];
$op1 = $array[$index-1];
$op2 = $array[$index+1];
$array[$index] = $op1 * $op2;
unset($array[$index-1]);
unset($array[$index+1]);
$array = array_values($array);
continue;
} else if ( count($add) >= 1 ) {
$index = $add[0];
$op1 = $array[$index-1];
$op2 = $array[$index+1];
$array[$index] = $op1 + $op2;
unset($array[$index-1]);
unset($array[$index+1]);
$array = array_values($array);
continue;
} else if ( count($sub) >= 1 ) {
$index = $sub[0];
$op1 = $array[$index-1];
$op2 = $array[$index+1];
$array[$index] = $op1 - $op2;
unset($array[$index-1]);
unset($array[$index+1]);
$array = array_values($array);
continue;
}
else {
break;
}
}
print_r($array);
echo "<p>";
?>
Heres the output of a print_r() after each iteration of the while loop so you can see it running through the divisions, multiplications, additions and subtractions one by one and thn modifying the array as it goes:
Array ( [0] => 35 [1] => - [2] => 59 [3] => * [4] => 2 [5] => / [6] => 27 [7] => * [8] => 2 )
Array ( [0] => 35 [1] => - [2] => 59 [3] => * [4] => 0.0740740740741 [5] => * [6] => 2 )
Array ( [0] => 35 [1] => - [2] => 4.37037037037 [3] => * [4] => 2 )
Array ( [0] => 35 [1] => - [2] => 8.74074074074 )
Array ( [0] => 26.2592592593 )
Why not calculate as you go splitting the input into an array, and then just output the result?
Just as an example:
$input = "35-59*2/27*2";
if (preg_match('/[^-+*\/\\d]/', $input)) // simple checking
{
echo "just use numbers and 4 operators!";
}
else
{
$substraction = explode('-', $input);
foreach ($substraction as $pos_s => $sub)
{
$addition = explode('+', $sub);
foreach ($addition as $pos_a => $add)
{
$multiplication = explode('*', $add);
foreach ($multiplication as $pos_m => $mult)
{
$division = explode('/', $mult);
$d = $division[0];
for ($i=1; $i < count($division);$i++)
$d = $d / $division[$i];
$multiplication[$pos_m] = $d;
}
$m = $multiplication[0];
for ($i=1; $i < count($multiplication);$i++)
$m = $m * $multiplication[$i];
$addition[$pos_a] = $m;
}
$a = $addition[0];
for ($i=1; $i < count($addition);$i++)
$a = $a + $addition[$i];
$substraction[$pos_s] = $a;
}
$result = $substraction[0];
for ($i=1; $i < count($substraction);$i++)
$result = $result - $substraction[$i];
echo $input . " = " . $result;
}
prints
35-59*2/27*2 = 26.259259259259

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
)
)

Categories