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);
I have a array
$new_array=array('c','a','m','t','p');
Now I want to find the words combination which exists in the words table.
I have tried to achieve but not succeeded.
this is my php code .
$words = array();
$set = powerSet($new_array,2);
$mysql = new mysqli("localhost","root","","startup");
$sql = "SELECT wordid from words WHERE lemma = '%s'" ;
foreach ($set as $key => $value)
{
$word = implode("", $value);
$wordPermutation = permute($word);
foreach($wordPermutation as $keyWord)
{
if(!in_array($keyWord, $words))
{
if($result = $mysql->query(sprintf($sql,$keyWord)))
{
var_dump(sprintf($sql,$keyWord));
if($result->num_rows > 0)
{
$words[] = $keyWord;
}
}
}
}
}
print_r($words);
function powerSet($in, $minLength = 1, $max = 10) {
$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 && count ( $out ) <= $max) {
$return [] = $out;
}
}
return $return;
}
function permute($str) {
if (strlen($str) < 2) {
return array($str);
}
$permutations = array();
$tail = substr($str, 1);
foreach (permute($tail) as $permutation) {
$length = strlen($permutation);
for ($i = 0; $i <= $length; $i++) {
$permutations[] = substr($permutation, 0, $i) . $str[0] . substr($permutation, $i);
}
}
return $permutations;
}
I want to find only those combination from the array which exists in the table .
My code is fetching all the combination
I might have mis-understood this but couldn't you use a single database query for this?
Such as:
SELECT wordid FROM `words` WHERE lemma LIKE ("%c%") OR lemma LIKE ("%a%") OR lemma LIKE ("%m%") OR lemma LIKE ("%t%") OR lemma LIKE ("%p%")
That way you'll get an array of wordids for any words containing any of the specified characters.
I'd add it as a comment but not enough rep yet.
I would like to Convert simple string to another format based on below logic
Example 1 : if string is 3,4-8-7,5 then I need the set as (3,8,7),(4,8,5).
Example 2: If string is "4-5,6-4" then required set will be (4,5,4),(4,6,4).
More Clear Requirements:
if string is 5-6,7,8-2,3-1. It need to be divided first like [5] AND [(6) OR (7) OR (8)] AND [(2) OR (3)] AND [1]. Result must be All possible combination: (5,6,2,1),(5,6,3,1),(5,7,2,1),(5,7,3,1),(5,8,2,1),(5,8,3,1).
The Logic behind to building the set are we need to consider ',' as OR condition and '-' as AND condition.
I am trying my best using For loop but unable to find solution
$intermediate = array();
$arry_A = explode('-', '3,4-8-7,5');
for ($i = 0; $i < count($arry_A); $i++) {
$arry_B = explode(',', $arry_A[$i]);
for ($j = 0; $j < count($arry_B); $j++) {
if (count($intermediate) > 0) {
for ($k = 0; $k < count($intermediate); $k++) {
$intermediate[$k] = $intermediate[$k] . ',' . $arry_B[$j];
}
} elseif (count($intermediate) === 0) {
$intermediate[0] = $arry_B[$j];
}
}
}
echo $intermediate, should give final result.
Cool little exercise!
I would do it with the following code, which I will split up for readability:
I used an array as output, since it's easier to check than a string.
First, we initialize the $string and create the output array $solutions. We will calculate the maximum of possible combinations from the beginning ($results) and fill the $solutions array with empty arrays which will be filled later with the actual combinations.
$string = '3,4-8-7,5';
$solutions = array();
$results = substr_count($string,',')*2;
for($i = 0; $i < $results; $i++) {
array_push($solutions,array());
}
We will need two helper functions: checkSolutions which makes sure, that the combination does not yet exist more than $limit times. And numberOfORAfterwards which will calculate the position of an OR pattern in the $string so we can calculate how often a combination is allowed in the single steps of the walkthrough.
function checkSolutions($array,$solutions,$limit) {
$count = 0;
foreach($solutions as $solution) {
if($solution === $array) $count++;
}
if($count < $limit) return true;
else return false;
}
function numberOfORAfterwards($part,$parts) {
foreach($parts as $currPart) {
if($currPart === $part) $count = 0;
if(isset($count)) if(!ctype_digit($currPart)) $count++;
}
return $count;
}
Now the main part: We are going to loop over the "parts" of the $string a part are the digits between AND operations.
If you need further explanation on this loop, just leave a comment.
$length = 0;
// split by all AND operations
$parts = explode('-',$string);
foreach($parts as $part) {
if(ctype_digit($part)) {
// case AND x AND
foreach($solutions as &$solution) {
array_push($solution,$part);
}
} else {
// case x OR x ...
$digits = explode(',',$part);
foreach($digits as $digit) {
for($i = 0; $i < $results/count($digits); $i++) {
foreach($solutions as &$solution) {
if(count($solution) == $length) {
$test = $solution;
array_push($test,$digit);
$limit = numberOfORAfterwards($part,$parts);
echo $digit.' '.$limit.'<br>';
if(checkSolutions($test,$solutions,$limit)) {
array_push($solution,$digit);
break;
}
}
}
}
}
}
$length++;
}
print_r($solutions);
Some tests:
String: 3,4-8-7,5
Combinations: (3,8,7)(3,8,5)(4,8,7)(4,8,7)
String: 5-6,7,8-2,3-1
Combinations: (5,6,2,1)(5,6,3,1)(5,7,2,1)(5,7,3,1)(5,8,2,1)(5,8,2,1)
String: 2,1-4-3,2-7,8-9
Combinations: (2,4,3,7,9)(2,4,3,8,9)(2,4,2,7,9)(1,4,3,7,9)(1,4,2,8,9)(1,4,2,8,9)
String: 1,5-3,2-1
Combinations: (1,3,1)(1,2,1)(5,3,1)(5,3,1)
I have been asked a question in an interview to sort a string by length of its words in php without using built in functions.No idea how to do this. Can somebody help me with this?
String: Sort a string by length of its words
Thanks in advance
$array = array('harish', 'mohan', 'jaideep', 'hari');
for ($i = 1; $i < count($array); $i++) {
for ($j = $i; $j > 0; $j--) {
if (strlen($array[$j]) < strlen($array[$j - 1])) {
$tmp = $array[$j];
$array[$j] = $array[$j - 1];
$array[$j - 1] = $tmp;
}
}
}
var_dump($array);
you could try this:
$string = "this is my test string";
$array = explode(" ", $string);
$result = array();
foreach ($array as $key => $string){
$counter = 0;
for($i = 0;;$i++){
if (!isset($string[$i])){
break;
}
$counter++;
}
$result[$counter][] = $string;
}
This splits your string and puts it into an array, where the keys are the counted characters. The problem now is, that you need to sort the array by the keys, which can be acquired by using ksort.
I do not know if you may use it, if not, refer to this answer (use of sort) or this answer (no sort), this should do the trick (though I didn't test it).
This is the solution that I propose. I added some comments.
<?php
/* First part split the string in their words and store them in an array called $words.
* The key is the length of the word and the value is an array with all the words having the same length as the key.
* e.g
* Array
(
[4] => Array( [0] => Sort )
[1] => Array( [0] => a )
[6] => Array( [0] => string, [1] => length)
[2] => Array( [0] => by, [1] => of)
[3] => Array( [0] => its )
)
*/
$str = "Sort a string by length of its words";
$word = '';
$i = 0;
$word_length = 0;
$words = [];
$max = -1;
while( isset($str[$i]) ) {
if( $str[$i] !== ' ' ){
$word .= $str[$i];
$word_length++;
}else{
//This is going to save the size of the longhest word in the array:
$max = ($word_length > $max) ? $word_length : $max;
//store the
$words[$word_length][] = $word;
$word = '';
$word_length = 0;
}
$i++;
}
//print_r($words); // uncomment this if you wanna see content of the array.
//The if-condition is for ascending order or descending order.
$order = "DESC"; // "ASC" | "DESC"
$res = '';
if( $order === "DESC") {
for( $i = $max; $i>=0 ; $i--) {
if( ! isset($words[$i]) ) { continue; }
foreach($words[$i] as $word){
$res .= $word . ' ';
}
}
}else {
//ascending order:
for( $i = 0; $i<=$max; $i++) {
if( ! isset($words[$i]) ) { continue; }
foreach($words[$i] as $word){
$res .= $word . ' ';
}
}
}
echo $res . "\n";
?>
Is this what you want?
Note: isset, echo, print, etc are PHP language constructs whereas print_r(), strlen(), etc. are built in functions. If you have doubts, you can see what's the difference in this post. What is the difference between a language construct and a "built-in" function in PHP?
I have an associative array in PHP like this:
$weight["a"]=1;
$weight["b"]=4;
$weight["c"]=5;
$weight["d"]=9;
Here I want to calculate pair-wise difference between consecutive array elements, e.g.,
"b-a" = 3
"c-b" = 1
"d-c" = 4
How should this be computed?
Try this:
$i = 0;
foreach ($weight AS $curr) {
if ($i > 0) {
echo '"'.array_keys($weight)[$i].'-'.array_keys($weight)[$i-1].'" = '.($curr-$prev)."<br />";
}
$i++;
$prev = $curr;
}
Store keys on a temporary array where keys are integers on which you can easily get the next key, and use it to parse your main array.
$tmp_array = array();
foreach ($weight as $key => $val) {
$tmp_array[] = $key;
}
$array_length = count($tmp_array);
for ($i = 0; i < array_length - 2; ++$i) {
echo $weight[$tmp_array[$i+1]], '-', $weight[$tmp_array[$i]], ' = ', ($weight[$tmp_array[$i+1]] - $weight[$tmp_array[$i]], PHP_EOL;
}