PHP Permutaion array with Priorities - php

Here I have a code with gives me required output but I would like to add priority order while choosing it
All possible combination code
$array = array('x2', 'y', 'm');
function depth_picker($arr, $temp_string, &$collect) {
if ($temp_string != "")
$collect []= $temp_string;
for ($i=0; $i<sizeof($arr);$i++) {
$arrcopy = $arr;
$elem = array_splice($arrcopy, $i, 1); // removes and returns the ith element
if (sizeof($arrcopy) > 0) {
depth_picker($arrcopy, $temp_string ." " . $elem[0], $collect);
} else {
$collect []= $temp_string. " " . $elem[0];
}
}
}
$collect = array();
depth_picker($array, "", $collect);
print_r($collect);
I found this code but I couldn't join them
function array_permutation(array $array)
{
$count = array_map('count', $array);
$finalSize = array_product($count);
$arraySize = count($array);
$output = array_fill(0, $finalSize, []);
$i = 0;
$c = 0;
for (; $i < $finalSize; $i++) {
for ($c = 0; $c < $arraySize; $c++) {
print $output[$i][] = $array[$c][$i % $count[$c]];
}
print "<br/>";
}
return $output;
}
$array = [['x2','x1'], ['y','k'], ['m', 'n']];
//print $output;
$output= array_permutation($array);
I am looking for making the script to output as
x2
x1
y
k
m
n
x2y
x1y
x2k
x1k
x2ym
x1ym
x2yn
x1yn
x2km
x1km
x2kn
x1kn
likewise...

Related

Find the subset of an array whose sum equal a given target using php

I am trying to implement a function below:
For example:
$a=array(1,10,25,50);
$number=15;
o/p : 15=1+1+1+1+1+10;
Done:
$a=array(1,10,25,50);
rsort($a);
$number=15;
$final = [];
$remainder = $number;
foreach($a as $num) {
do {
if($num <= $number) {
$final[] = $num;
$remainder -= $num;
}
if($remainder == 0) break;
} while($remainder >= $num);
}
echo $number . " = " . implode(' + ', $final);
Also this method:
$a=array(1,10,25,50);
rsort($a);
$number=15;
echo $number . " = ";
$final = [];
foreach($a as $num) {
if((int)($number / $num) > 0) {
$final = array_merge($final, array_fill(0, (int)($number / $num), $num));
$number -= (int)($number / $num) * $num;
}
}
echo implode(' + ', $final);
Make a recursive function for this:
function getcomb($arr,$actualNum, $total=0, $combination_array = array()){
foreach($arr as $k=>$v){
if($v > $actualNum) continue;
$shiftVal = $v;
if($total+$shiftVal <= $actualNum ){
$combination_array[] = $shiftVal;
$total += $shiftVal;
$reminder = $actualNum-$total;
//echo "<pre>combination_array";print_r($combination_array);
if($reminder <= 0){
return $shiftVal;
}else{
return $shiftVal .' + '.getcomb($arr, $actualNum,$total, $combination_array);
}
}
}
}
$a=array(1,10,25,50);
rsort($a);
$number=15;
echo $str = getcomb($a, $number);
Cleck here to check output

String compression in php

Here is my input
aaaabbaaaababbbcccccccccccc
And this is my expected output
a4b2a4b1a1b3c12
I tried like doing foreach and then concating the count of values. It seems like brutforcing. Is there any way to do it efficiently in php .
Help pls
You can use regular expression to get the result
preg_match_all('/(.)\1*/', $str, $m, PREG_SET_ORDER);
$m = array_map(function($i) { return $i[1] . strlen($i[0]); } , $m);
echo implode('', $m); // a4b2a4b1a1b3c12
demo
Here's an example of how to do it with a few for loops (encoding and decoding):
$input = 'aaaabbaaaababbbcccccccccccc';
$encoded = SillyEncoding::encode($input);
$decoded = SillyEncoding::decode($encoded);
echo "input = \t", var_export($input, true), "\n";
echo "encoded = \t", var_export($encoded, true), "\n";
echo "decoded = \t", var_export($decoded, true), "\n";
Output:
input = 'aaaabbaaaababbbcccccccccccc'
encoded = 'a4b2a4b1a1b3c12'
decoded = 'aaaabbaaaababbbcccccccccccc'
The SillyEncoding class:
class SillyEncoding
{
private static $digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
static function encode($string)
{
$output = '';
if (strlen($string) > 0) {
$count = 0;
$char = $string[0];
for ($i = 0; isset($string[$i]); ++$i) {
if (isset(self::$digits[$string[$i]])) {
throw new \InvalidArgumentException(sprintf('The input string must not contain a digit at offset %d, got "%s"', $i, $string[$i]));
}
if ($string[$i] === $char) {
++$count;
} else {
$output .= "{$char}{$count}";
$count = 1;
$char = $string[$i];
}
if (!isset($string[$i + 1])) {
$output .= "{$char}{$count}";
}
}
}
return $output;
}
static function decode($string)
{
$output = '';
$length = strlen($string);
if ($length > 0) {
$char = $string[0];
$count = null;
if ($length < 2) {
throw new \InvalidArgumentException(sprintf('Input string must be empty or at least 2 bytes long, got %d bytes', $length));
}
if (isset(self::$digits[$string[0]])) {
throw new \InvalidArgumentException(sprintf('Input string must not start with a digit, got "%s"', $string[0]));
}
for ($i = 1; isset($string[$i]); ++$i) {
$isDigit = isset(self::$digits[$string[$i]]);
if ($isDigit) {
$count .= $string[$i];
}
if (!$isDigit || !isset($string[$i + 1])) {
if (null === $count) {
throw new \InvalidArgumentException(sprintf('Expected a digit at offset %d, got "%s"', $i, $string[$i]));
}
$count = (int) $count;
for ($j = 0; $j < $count; ++$j) {
$output .= $char;
}
$char = $string[$i];
$count = null;
}
}
}
return $output;
}
}
A few things to note:
this isn't an efficient compression algorithm - it might reduce the size if there are many repeated characters, but if you feed it "normal" text the output will be about twice the size of the input
the input cannot contain any digits whatsoever (OP: "the input will be strictly alphabets")
$str = str_split('aaaabbaaaababbbcccccccccccc');
$count = 0;
$a=$result=$b='';
for ($i=0; $i <= count($str); $i++) {
if($a==$str[$i]){
$count++;
$result = $a.$count;
} else{
if ($count > 0) {
$b .= $result;
}
$count = 1;
$a = $str[$i];
$result = $a.$count;
}
}
print_r($b);
See result

php - permutation - possible number

already look around but cant find what i want for PHP.
just say i have a number : 1234 ( can be splitted first into array )
and i want to get how many number combination possible for 2 digits, 3 digits , and 4 digits
for example :
possible 4 digits will be :
1234,1243,1324,1342, and so on. ( i dont know how many more )
possible 2 digits will be :
12,13,14,21,23,24,31,32,34,41,42,43
the closest one i get is :
$p = permutate(array('1','2','3','4'));
$result = array();
foreach($p as $perm) {
$result[]=join("",$perm);
}
$result = array_unique($result);
print join("|", $result);
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;
}
but how can i edit this so i can display for 3 and 2 digits ?
Thanks
i got what i want
it's from #mudasobwa link. and i edit to what i want.
<?php
$in = array(1,2,3,4,5,6);
$te = power_perms($in);
// print_r($te);
$thou=0;
$hun =0;
$pu = 0;
for($i=0;$i<count($te);$i++)
{
$jm = count($te[$i]);
for($j=0;$j<$jm;$j++)
{
$hsl[$i] = $hsl[$i] . $te[$i][$j];
}
if($hsl[$i] >=100 && $hsl[$i] < 1000 )
{
$ratus[$hun] = intval($hsl[$i]);
$hun = $hun + 1;
}
if($hsl[$i] <100 && $hsl[$i] >=10)
{
$pul[$pu] = intval($hsl[$i]);
$pu = $pu + 1;
}
if($hsl[$i] >=1000 && $hsl[$i] < 10000)
{
$th[$thou] = intval($hsl[$i]);
$thou = $thou + 1;
}
}
$th=array_unique($th);
$pul = array_unique($pul);
$ratus = array_unique($ratus);
sort($ratus);
sort($pul);
sort($th);
print_r($th);
function power_perms($arr) {
$power_set = power_set($arr);
$result = array();
foreach($power_set as $set) {
$perms = perms($set);
$result = array_merge($result,$perms);
}
return $result;
}
function power_set($in,$minLength = 1) {
$count = count($in);
$members = pow(2,$count);
$return = array();
for ($i = 0; $i < $members; $i++) {
$b = sprintf("%0".$count."b",$i);
$out = array();
for ($j = 0; $j < $count; $j++) {
if ($b{$j} == '1') $out[] = $in[$j];
}
if (count($out) >= $minLength) {
$return[] = $out;
}
}
// usort($return,"cmp"); //can sort here by length
return $return;
}
function factorial($int){
if($int < 2) {
return 1;
}
for($f = 2; $int-1 > 1; $f *= $int--);
return $f;
}
function perm($arr, $nth = null) {
if ($nth === null) {
return perms($arr);
}
$result = array();
$length = count($arr);
while ($length--) {
$f = factorial($length);
$p = floor($nth / $f);
$result[] = $arr[$p];
array_delete_by_key($arr, $p);
$nth -= $p * $f;
}
$result = array_merge($result,$arr);
return $result;
}
function perms($arr) {
$p = array();
for ($i=0; $i < factorial(count($arr)); $i++) {
$p[] = perm($arr, $i);
}
return $p;
}
function array_delete_by_key(&$array, $delete_key, $use_old_keys = FALSE) {
unset($array[$delete_key]);
if(!$use_old_keys) {
$array = array_values($array);
}
return TRUE;
}
?>

Seven flags to concise list of days of the week?

I have an array/string/integer of 7 flags, one for each day of the week (of a recurring event). How can I convert this to a brief list of the days?
So, for example
Given 1011001, return 'Su, T-W, Sa'.
Given 0111011, return 'M-W, F-Sa'.
What's the shortest way to accomplish this?
EDIT
For comparison, here's my own inelegant code:
<?php
function dowstring($dow) {
if ($dow == 0) return "Error";
$ddow = ["Su", "M", "T", "W", "Th", "F", "Sa"];
$t = strrev( sprintf('%07b', $dow) );
$u = str_split($t);
$out = '';
$cu = count($u);
$nn = 0; // number of days thus far counted
$v = 0; // number in the run
for($i = 0; $i < $cu; $i++) {
if ($u[$i]) {
if ($v == 0) {
$out .= ($nn) ? ", " : '';
$out .= $ddow[$i];
}
$nn++;
$v++;
}
else {
if ($v > 1) {
$out .= ($nn) ? "-" . $ddow[$i-1] : '';
}
$v = 0;
}
}
// in case Saturday is part of a run
if ($v > 1) {
$out .= ($nn) ? "-" . $ddow[$i-1] : '';
}
return $out;
}
echo "<pre>";
// testing script
for ($i = 1; $i < pow(2, 7); $i++) {
$ds = dowstring($i);
$j = strrev( sprintf("%07b", $i) );
printf("%s %s\n", $j, $ds);
}
echo "</pre>";
?>
EDIT
Another attempt, inspired by Prasanth:
function dowstring($dow) {
if ($dow == 0) return "Error";
$ddow = ["Su", "M", "T", "W", "Th", "F", "Sa"];
$t = strrev( sprintf('%07b', $dow) );
$v = array_keys( array_filter( str_split($t) ) );
$cv = count($v); $w = array();
$out = $ddow[$v[0]];
for ($i = 1; $i < $cv; $i++) $w[] = $v[$i] - $v[$i - 1] - 1;
$w = ( $cv == 1 ) ? array($w) : $w;
for ($i = 1; $i < $cv; $i++) {
if (!$w[$i - 1]) $last = $ddow[$v[$i]];
else {
if ( isset($last) ) $out .= '-' . $last;
$out .= ', ' . $ddow[$v[$i]];
unset($last);
}
}
if ($i > 1 && !$w[$i-2] ) $out .= '-' . $ddow[ $v[$i-1] ];
return $out;
}
I'd like to see something better. Anyone?
Try this:
$days=array('1'=>'Monday','2'=>'Tuesay','3'=>'Wednesday','4'=>'Thursday','5'=>'Friday','6'=>'Saturday','7'=>'Sunday');
$pattern = '1000110';
$arr1 = str_split($pattern);
$i=0;
foreach($days as $key => $tes) {
if($key - $arr1[$i] != $key) {
echo $tes;
}
$i++;
}
Adjust days array according to the sequence of days you want
Try this :
<?php
$days = array('Su','M','T','W','Th','F','Sa');
function checkConsec($d) {
for($i=0;$i<count($d);$i++) {
if(isset($d[$i+1]) && $d[$i]+1 != $d[$i+1]) {
return false;
}
}
return true;
}
$str = '0111011';
$array = array_keys(array_filter(str_split($str)));
$temp = array();
$res = array();
for($i=0;$i<count($array);$i++){
$temp[] = $array[$i];
if(checkConsec($temp) && count($temp) > 1){
$res[$temp[0]] = $days[$temp[0]]."-".$days[$temp[count($temp)-1]];
}else{
$res[$array[$i]] = $days[$array[$i]];
$temp = array();
$temp[] = $array[$i];
}
}
echo implode(",",$res);
?>

Combining of array items

I have a problem with an advanced loop, this are my arrays
$array1 = array(1,2,3);
$array2 = array(4,5);
$array3 = array(6,7,8,9);
$array4 = array(10,11);
I want to loop with the following result:
1,4,6,10
1,4,6,11
1,4,7,10
1,5,7,11
With the last: 3,5,8,11
How can I do that?
Solution for a variable number of arrays. Can probably be written a bit shorter, but I leave that to you. ;)
<?php
$array1 = array(1,2,3);
$array2 = array(4,5);
$array3 = array(6,7,8,9);
$array4 = array(10,11);
function turboArray()
{
$arrays = func_get_args();
$indexes = array_fill(0, count($arrays), 0);
function turboSubArray(&$arrays, &$indexes, $l){
for ($a = 0; $a < count($arrays[$l]); $a++){
$indexes[$l] = $a;
if ($l == count($arrays) - 1) {
for ($i = 0; $i < count($indexes); $i++)
{
echo $arrays[$i][$indexes[$i]];
if ($i == count($indexes) - 1){
echo "\n<br/>";
$indexes[$i] = 0;
if ($i == 0) return;
}
else {
echo ', ';
}
}
} else if ($l < count($indexes)) {
turboSubArray($arrays, $indexes, $l + 1);
}
}
}
$l = 0;
turboSubArray($arrays, $indexes, $l);
}
turboArray($array1, $array2, $array3, $array4);
This should do it... ?
foreach ($array1 as $first) {
foreach ($array2 as $second) {
foreach ($array3 as $third) {
foreach ($array4 as $fourth) {
echo "$first $second $third $fourth";
}
}
}
}
I got bored and decided to overengineer a bit. Enjoy.
class CrossJoin implements Iterator {
private $arrays = array();
private $index = 0;
public function __construct(/* $array1, ... */) {
foreach (func_get_args() as $arr) {
// ArrayIterator's iteration stuff is cleaner than arrays',
// and less prone to breakage when objects are passed around
if (count($arr)) $this->arrays[] = new ArrayIterator($arr);
}
// if any of the arrays were empty, a cross join should fail.
// fudge a single empty array to prevent special-casing later
if (count($this->arrays) !== func_num_args()) {
$this->arrays = array(new ArrayIterator(array()));
}
}
public function next() {
for ($i = count($this->arrays) - 1; $i >= 0; --$i) {
// carry til we don't have to anymore
$place = $this->arrays[$i];
$place->next();
if ($place->valid()) break;
}
// if $i<0, then we carried right off the edge of the list.
// don't let $arrays[0] be reset, cause that's our indicator
// that we're done.
if ($i<0) return;
++$this->index;
for (++$i; $i < count($this->arrays); ++$i) {
$this->arrays[$i]->rewind();
}
}
public function current() {
$result = array();
foreach ($this->arrays as $arr) { $result[] = $arr->current(); }
return $result;
}
public function key() { return $this->index; }
public function valid() {
return !empty($this->arrays) && $this->arrays[0]->valid();
}
public function rewind() {
foreach ($this->arrays as $arr) $arr->rewind();
$this->index = 0;
}
}
$combos = new CrossJoin(
array(1, 2, 3),
array(4, 5),
array(6, 7, 8, 9),
array(10, 11)
);
foreach ($combos as $combo) {
echo implode(', ', $combo), "\n";
}
Hope that helps:
for ($i = 0; $i < count($a1); ++i) {
for ($j = 0; $j < count($a2); ++j) {
for ($k = 0; $k < count($a3); ++k) {
for ($l = 0; $l < count($a4); ++l) {
echo $a1[$i] . ' ' . $a2[$j] . ' ' . $a3[$k] . ' ' . $a4[$l] . '\n';
}
}
}
}
Cheers!
You are looking for the PHP array_merge function.

Categories