I have an array something like that:
array('A','B','C','D','E');
and I want to make pairs of each value like that :
A, AB, ABC, ABCD, ABCDE
B, BC, BCD, BCDE
C, CD, CDE
D, DE
E
as an Array (ALL PAIRS SHOULD BE IN A SAME ARRAY).
And I have followed this Question:
How do I make pairs of array values?
But i'm not able to do that.
Please Help
For each of your inputs, loop between it and the end of the input array. For each result, add the range between the present and end inputs to your result.
$input = array('A', 'B', 'C', 'D', 'E');
$output = array();
for ($i = 0; $i < count($input); $i++) {
$row = array($input[$i]);
for ($j = $i + 1; $j < count($input); $j++) {
$row[] = implode('', range($input[$i], $input[$j]));
}
$output[] = $row;
}
$data = array('A','B','C','D','E');
$chars = count($data);
$combinations = array();
foreach ($data as $key => $startChar) {
$length = 0;
while ($length < $chars - $key) {
$combinations[] = implode(array_slice($data, $key, ++$length));
}
}
var_dump($combinations);
Looks like the format output:
$letters = array('A','B','C','D','E');
$result = array();
$x = 0;
while(count($letters) > 0) {
$l = array_shift($letters);
$result[$x][] = $l;
foreach($letters as $k => $letter){
$result[$x][] = $l . implode(array_slice($letters, 0, $k+1));
}
$result[$x] = implode(', ', $result[$x]);
$x++;
}
echo '<pre>';
print_r($result);
Related
I have a string composed by many letters, at some point, one letter from a group can be used and this is represented by letters enclosed in []. I need to expand these letters into its actual strings.
From this:
$str = 'ABCCDF[GH]IJJ[KLM]'
To this:
$sub[0] = 'ABCCDFGIJJK';
$sub[1] = 'ABCCDFHIJJK';
$sub[2] = 'ABCCDFGIJJL';
$sub[3] = 'ABCCDFHIJJL';
$sub[4] = 'ABCCDFGIJJM';
$sub[5] = 'ABCCDFHIJJM';
UPDATE:
Thanks to #Barmar for the very valuable suggestions.
My final solution is:
$str = '[GH]DF[IK]TF[ADF]';
function parseString(string $str) : array
{
$i = 0;
$is_group = false;
$sub = array();
$chars = preg_split('//', $str, -1, PREG_SPLIT_NO_EMPTY);
foreach ($chars as $key => $value)
{
if(ctype_alpha($value))
{
if($is_group){
$sub[$i][] = $value;
} else {
if(!isset($sub[$i][0])){
$sub[$i][0] = $value;
} else {
$sub[$i][0] .= $value;
}
}
} else {
$is_group = !$is_group;
++$i;
}
}
return $sub;
}
The recommended function for combinations is (check the related post):
function array_cartesian_product($arrays)
{
$result = array();
$arrays = array_values($arrays);
$sizeIn = sizeof($arrays);
$size = $sizeIn > 0 ? 1 : 0;
foreach ($arrays as $array)
$size = $size * sizeof($array);
for ($i = 0; $i < $size; $i++) {
$result[$i] = array();
for ($j = 0; $j < $sizeIn; $j++)
array_push($result[$i], current($arrays[$j]));
for ($j = ($sizeIn - 1); $j >= 0; $j--) {
if (next($arrays[$j]))
break;
elseif (isset($arrays[$j]))
reset($arrays[$j]);
}
}
return $result;
}
Check the solution with:
$combinations = array_cartesian_product(parseString($str));
$sub = array_map('implode', $combinations);
var_dump($sub);
Convert your string into a 2-dimensional array. The parts outside brackets become single-element arrays, while each bracketed trings becomes an array of single characters. So your string would become:
$array =
array(array('ABCCDF'),
array('G', 'H', 'I'),
array('IJJ'),
array('K', 'L', 'M'));
Then you just need to compute all the combinations of those arrays; use one of the answers at How to generate in PHP all combinations of items in multiple arrays. Finally, you concatenate each of the resulting arrays with implode to get an array of strings.
$combinations = combinations($array);
$sub = array_map('implode', $combinations);
What I need to add to this script to get 3 longest words from string?
<?php
$text = 'one four eleven no upstairs';
$arr = explode(" ", $text);
$max = $arr[0];
for ($i = 0; $i < count($arr); $i++) {
if (strlen($arr[$i]) > strlen($max)) {
$max = $arr[$i];
}
}
echo $max;
?>
Please help to modify the script. We have to not use the usort function.
The solution would be like this:
Use explode() to get the words of the string in an array
"Partially" sort the array elements in descending order of length
Use a simple for loop to print the longest three words from the array.
So your code should be like this:
$text = 'one four eleven no upstairs';
$arr = explode(" ", $text);
$count = count($arr);
for($i=0; $i < $count; $i++){
$max = $arr[$i];
$index = $i;
for($j = $i + 1; $j < $count; ++$j){
if(strlen($arr[$j]) > strlen($max)){
$max = $arr[$j];
$index = $j;
}
}
$tmp = $arr[$index];
$arr[$index] = $arr[$i];
$arr[$i] = $tmp;
if($i == 3) break;
}
// print the longest three words
for($i=0; $i < 3; $i++){
echo $arr[$i] . '<br />';
}
Alternative method: (Using predefined functions)
$text = 'one four eleven no upstairs';
$arr = explode(" ", $text);
usort($arr,function($a, $b){
return strlen($b)-strlen($a);
});
$longest_string_array = array_slice($arr, 0, 3);
// display $longest_string_array
var_dump($longest_string_array);
You need to create your own comparative function and pass it with array to usort php function.
Ex.:
<?php
function lengthBaseSort($first, $second) {
return strlen($first) > strlen($second) ? -1 : 1;
}
$text = 'one four eleven no upstairs';
$arr = explode(" ", $text);
usort($arr, 'lengthBaseSort');
var_dump(array_slice($arr, 0, 3));
It will output 3 longest words from your statement.
According to author changes:
If you have no ability to use usort for some reasons (may be for school more useful a recursive function) use following code:
<?php
$text = 'one four eleven no upstairs';
$arr = explode(" ", $text);
function findLongest($inputArray) {
$currentIndex = 0;
$currentMax = $inputArray[$currentIndex];
foreach ($inputArray as $key => $value) {
if(strlen($value) > strlen($currentMax)){
$currentMax = $value;
$currentIndex = $key;
}
}
return [$currentIndex, $currentMax];
}
for($i = 0; $i < 3; $i++) {
$result = findLongest($arr);
unset($arr[$result[0]]);
var_dump($result[1]);
}
?>
I am trying to create function that allows me to get all combinations of an array to later generate a list.
But my problem is that currently my function treat "ab" as different from "ba". I dont know how to explain it in words but I guess the picture below exemplify what I try to achieve.
function everyCombination($array) {
$arrayCount = count($array);
$maxCombinations = pow($arrayCount, $arrayCount);
$returnArray = array();
$conversionArray = array();
foreach ($array as $key => $value) {
$conversionArray[base_convert($key, 10, $arrayCount)] = $value;
}
for ($i = 0; $i < $maxCombinations; $i++) {
$combination = base_convert($i, 10, $arrayCount);
$combination = str_pad($combination, $arrayCount, "0", STR_PAD_LEFT);
$returnArray[] = strtr($combination, $conversionArray);
}
return $returnArray;
}
$a = everyCombination(array('a', 'b', 'c','d'));
print_r($a);
The desired ouput would be
a
ab
abc
abcd
b
bc
bcd
c
cd
d
What you need to do is iterate through the array recursively, for each recursion you should only iterate through all the greater elements. Like so:
function everyCombination($arr) {
$combos = array();
$len = count($arr);
for( $i=0; $i<$len; $i++) {
for( $j=$i+1; $j<=$len; $j++) {
$combos[] = implode("",array_slice($arr,$i,$j-$i));
}
}
return $combos;
}
Example call:
everyCombination(['a','b','c','d']);
Returns:
['a','ab','abc','abcd','b','bc','bcd','c','cd','d']
It seems that you're after consecutive results, so a double loop would be a better choice here; recursion requires more control.
function combos($array)
{
if (!$array) {
return [];
}
$n = count($array);
$r = [];
for ($i = 0; $i < $n; ++$i) {
$prefix = '';
for ($j = $i; $j < $n; ++$j) {
$r[] = $prefix . $array[$j];
$prefix .= $array[$j];
}
}
return $r;
}
print_r(combos([1, 2, 3, 4]));
Using PHP, let's say I have this string:
$letters = "abcde";
I would like to add the character "7" between every character, but so it only occurs once. The result should be an array as follows:
$lettersArray = array(
7abcde,
a7bcde,
ab7cde,
abc7de,
abcd7e,
abcde7
);
Note: the length of $letters is dynamic from 1 to 12 characters
I have tried using loops with array_splice and str_split with implode, but I can't quite figure out the right logic.
It is very simple , do like this
echo implode("+", str_split('vimal')); // OUTPUT : v+i+m+a+l
Have a nice day
Try this:
$letters ='abcdefghi';
$lettersArray = array();
for($i=0;$i < strlen($letters)+1; $i++) {
$new = substr($letters, 0, $i);
$new .= '7';
$new .= substr($letters, $i);
$lettersArray[] = $new;
}
print_r($lettersArray);
What this does is take each element of the array, and inserts the letter 7 in an incrementing fashion into the array item.
$split_letters = str_split($letters);
$letters_array = array();
for($i = 0; $i <= count($split_letters); $i++) {
$start_letters = array_slice($split_letters, 0, $i);
$end_letters = array_slice($split_letters, $i);
$letters_array[] = array_merge($start_letters, array(7), $end_letters);
}
After 2 hours (including writing this question) I finally also came up with a solution that is similar to the others posted here. It's posted below, but I prefer other solutions posted here.
$letters = "abcde";
$results = array();
$lettersArray = str_split($letters);
foreach ($lettersArray as $key => $lets) {
$tempArray = $lettersArray;
array_splice($tempArray, $key, 0, "7");
$results[] = implode($tempArray);
}
$results[] = $letters . "7"; //required for the final combination
print_r($results);
Try this
$letters = "abcde";
$character = "7";
$len = strlen($letters);
$lettersArray = array();
for($i=0; $i <= $len; $i++)
{
$temp = "";
$temp = substr($letters, 0, $i) . $character . substr($letters, $i);
$lettersArray[] = $temp;
}
http://codepad.viper-7.com/gFByJb
Here is my code to get all possibilities:
$seq[1] = 'd';
$seq[2] = 'f';
$seq[3] = 'w';
$seq[4] = 's';
for($i = 1; $i < 5; $i++)
{
$s['length_1'][] = $seq[$i];
$c1++;
for($i2 = $i+1; $i2 < 5; $i2++)
{
$s['length_2'][] = $seq[$i].$seq[$i2];
$last = $seq[$i].$seq[$i2];
$c2++;
for($i3 = $i2+1; $i3 < 5; $i3++)
{
$s['length_3'][] = $last.$seq[$i3];
$last = $last.$seq[$i3];
$c3++;
for($i4 = $i3+1; $i4 < 5; $i4++)
{
$s['length_4'][] = $last.$seq[$i4];
$c4++;
}
}
}
}
for($i = 0; $i < $c1; $i++)
echo $s['length_1'][$i].'<br>';
for($i = 0; $i < $c2; $i++)
echo $s['length_2'][$i].'<br>';
for($i = 0; $i < $c3; $i++)
echo $s['length_3'][$i].'<br>';
for($i = 0; $i < $c4; $i++)
echo $s['length_4'][$i].'<br>';
But if I want to add more, then I will have to add one more loop. So, how can I do it with recursion? I try, I try, but I really can't do it.
Please help and post example as simple as possible.
Thank you.
One algorithm is here,
function getCombinations($base,$n){
$baselen = count($base);
if($baselen == 0){
return;
}
if($n == 1){
$return = array();
foreach($base as $b){
$return[] = array($b);
}
return $return;
}else{
//get one level lower combinations
$oneLevelLower = getCombinations($base,$n-1);
//for every one level lower combinations add one element to them that the last element of a combination is preceeded by the element which follows it in base array if there is none, does not add
$newCombs = array();
foreach($oneLevelLower as $oll){
$lastEl = $oll[$n-2];
$found = false;
foreach($base as $key => $b){
if($b == $lastEl){
$found = true;
continue;
//last element found
}
if($found == true){
//add to combinations with last element
if($key < $baselen){
$tmp = $oll;
$newCombination = array_slice($tmp,0);
$newCombination[]=$b;
$newCombs[] = array_slice($newCombination,0);
}
}
}
}
}
return $newCombs;
}
I know it is not efficent in any way, but using in small sets should not be a problem
first base parameter is an array containing elements to be considered when generating combinations.
for simple usage and output:
var_dump(getCombinations(array("a","b","c","d"),2));
and output is
array
0 =>
array
0 => string 'a' (length=1)
1 => string 'b' (length=1)
1 =>
array
0 => string 'a' (length=1)
1 => string 'c' (length=1)
2 =>
array
0 => string 'a' (length=1)
1 => string 'd' (length=1)
3 =>
array
0 => string 'b' (length=1)
1 => string 'c' (length=1)
4 =>
array
0 => string 'b' (length=1)
1 => string 'd' (length=1)
5 =>
array
0 => string 'c' (length=1)
1 => string 'd' (length=1)
To list all subsets of an array, using this combinations algorithm just execute
$base =array("a","b","c","d");
for($i = 1; $i<=4 ;$i++){
$comb = getCombinations($base,$i);
foreach($comb as $c){
echo implode(",",$c)."<br />";
}
}
And output is
a
b
c
d
a,b
a,c
a,d
b,c
b,d
c,d
a,b,c
a,b,d
a,c,d
b,c,d
a,b,c,d
Here's a simple algo. Iterate from 1 to 2count(array)-1. On each iteration, if j-th bit in a binary representation of the loop counter is equal to 1, include j-th element in a combination.
As PHP needs to be able to calculate 2count(array) as an integer, this may never exceed PHP_INT_MAX. On a 64-bit PHP installation your array cannot have more than 62 elements, as 262 stays below PHP_INT_MAX while 263 exceeds it.
EDIT: This computes all possible combinations, not permutations (ie, 'abc' = 'cba'). It does so by representing the original array in binary and "counting up" from 0 to the binary representation of the full array, effectively building a list of every possible unique combination.
$a = array('a', 'b', 'c', 'd');
$len = count($a);
$list = array();
for($i = 1; $i < (1 << $len); $i++) {
$c = '';
for($j = 0; $j < $len; $j++)
if($i & (1 << $j))
$c .= $a[$j];
$list[] = $c;
}
print_r($list);
Here it is:
<?php
function combinations($text,$space)
{
// $text is a variable which will contain all the characters/words of which we want to make all the possible combinations
// Let's make an array which will contain all the characters
$characters=explode(",", $text);
$x=count($characters);
$comb = fact($x);
// In this loop we will be creating all the possible combinations of the positions that are there in the array $characters
for ($y=1; $y<= $comb; $y++)
{
$ken = $y-1;
$f = 1;
$a = array();
for($iaz=1; $iaz<=$x; $iaz++)
{
$a[$iaz] = $iaz;
$f = $f*$iaz;
}
for($iaz=1; $iaz<=$x-1; $iaz++)
{
$f = $f/($x+1-$iaz);
$selnum = $iaz+$ken/$f;
$temp = $a[$selnum];
for($jin=$selnum; $jin>=$iaz+1; $jin--)
{
$a[$jin] = $a[$jin-1];
}
$a[$iaz] = $temp;
$ken = $ken%$f;
}
$t=1;
// Let’s start creating a word combination: we have all the necessary positions
$newtext="";
// Here is the while loop that creates the word combination
while ($t<=$x)
{
$newtext.=$characters[$a[$t]-1]."$space";
$t++;
}
$combinations[] = $newtext ;
}
return $combinations;
}
function fact($a){
if ($a==0) return 1;
else return $fact = $a * fact($a-1);
}
$a = combinations("d,f,w,s","");
foreach ($a as $v) {
echo "$v"."\n";
}
?>
Output:
dfws
dfsw
dwfs
dwsf
dsfw
dswf
fdws
fdsw
fwds
fwsd
fsdw
fswd
wdfs
wdsf
wfds
wfsd
wsdf
wsfd
sdfw
sdwf
sfdw
sfwd
swdf
swfd
Also, read this;
You can do this:
function combinations($arr) {
$combinations = array_fill(0, count($arr)+1, array());
$combinations[0] = array('');
for ($i = 0, $n = count($arr); $i < $n; ++$i) {
for ($l = $n-$i; $l > 0; --$l) {
$combinations[$l][] = implode('', array_slice($arr, $i, $l));
}
}
return $combinations;
}
Here’s an example:
$arr = array('d', 'f', 'w', 's');
var_dump(combinations($arr));
This produces the following array:
array(
array(''), // length=0
array('d', 'f', 'w', 's'), // length=1
array('df', 'fw', 'ws'), // length=2
array('dfw', 'fws'), // length=3
array('dfws') // length=4
)
A brief explanation:
For each i with 0 ≤ i < n, get all sub-arrays arr[i,i+l] with each possible length of 0 < l ≤ n - i.
Here is my function to print all possible character combinations:
function printCombinations($var, $begin = 0, $preText = "") {
for($i = $begin; $i < count($var); $i++) {
echo $preText . $var[$i] . "\n";
if(($i+1) < count($var))
printCombinations($var, $i+1, $preText . $var[$i]);
}
}
printCombinations(array('a','b','c','d','e'));
here is another way to do it in codeigniter/php.
`function recursiveCombinations($var,$n = '') {
$len = count($var);
if ($n == 0){
return array(array());
}
$arr = [];
for ($i = 0;$i<$len;$i++){
$m = $var[$i];
$remLst = array_slice($var, $i + 1);
$remainlst_combo = $this->recursiveCombinations($remLst, $n-1);
foreach ($remainlst_combo as $key => $val){
array_push($arr,array_merge(array($m),$val));
}
}
return $arr;
}
$arr = ['a','b','c','d','e','f','g','h','i','j','l','m','n','o','p'];
$n = $this->recursiveCombinations($arr,5);`