I am building a web app which user type special kind of code (see below), which my this script "decodes" and creates individual variations of the code and then send each of this code to the SQL query. For now, I am stuck in the part where codes need to convert this:
A1 B2 - C3 + D4 / E5 / E6 C3 / A5
to these (interpreting slash "/" as OR):
A1 B2 - C3 + D4 C3
A1 B2 - C3 + E5 C3
A1 B2 - C3 + E6 C3
A1 B2 - C3 + D4 A5
A1 B2 - C3 + E5 A5
A1 B2 - C3 + E6 A5
This is what I got for now:
// User input
$input = "A1 B2 - C3 + D4 / E5 / E6 C3 / A5";
print_r($input);
// Check how many times user input have "/" (returns INT in $occurencesOfOR and makes complex array $matches of matched substrings)
$occurencesOfOR = preg_match_all("/(?: \/ )?(?:[A-IK-Za-ik-z]|Aa)[1-9][0-9]{0,2}[A-Za-z]? \/ (?:[A-IK-Za-ik-z]|Aa)[1-9][0-9]{0,2}[A-Za-z]?(?: \/ (?:[A-IK-Za-ik-z]|Aa)[1-9][0-9]{0,2}[A-Za-z]?)*/", $input, $matches);
print_r($occurencesOfOR);
// Replacing places of matched pattern with X
$dummyCode = "X";
$inputStripped = preg_replace("/(?: \/ )?(?:[A-IK-Za-ik-z]|Aa)[1-9][0-9]{0,2}[A-Za-z]? \/ (?:[A-IK-Za-ik-z]|Aa)[1-9][0-9]{0,2}[A-Za-z]?(?: \/ (?:[A-IK-Za-ik-z]|Aa)[1-9][0-9]{0,2}[A-Za-z]?)*/", $dummyCode, $input);
print_r($inputStripped);
print_r($matches);
// Creating simple array with individual OR codes
$orCodesArray = [];
foreach ($matches[0] as $match) {
array_push($orCodesArray, $match);
}
print_r($orCodesArray);
// Creating multidimensional array from individual codes created by preg_split()
$individualCodesSubarrays = [];
foreach ($orCodesArray as $code) {
$codeSet = preg_split("/ \/ /", $code);
array_push($individualCodesSubarrays, $codeSet);
}
print_r($individualCodesSubarrays);
// Count how many subarrays has $individualCodesArray (returns INT)
$counterOfArrays = count($individualCodesSubarrays);
echo $counterOfArrays;
// Getting position of X-es in stripped user input
$lastPos = 0;
$positions = [];
$position = "";
while (($lastPos = strpos($inputStripped, $dummyCode, $lastPos)) !== false) {
$positions[] = $lastPos;
$lastPos = $lastPos + strlen($dummyCode);
}
foreach ($positions as $position) {
echo $position."\n";
}
But from there I don't know how to pursue further. I cannot find a solution how to make a function that will replace 1st X
with each of D4 / E5 / E6
and 2nd X
with each of C3 / A5
to make all possible combinations as stated above. Any help is appreciated.
UPDATE
I succeeded in progress to make this, but still have a problem to make it work.
// Addition to the upper code at the end
$inputStripped2 = [];
for ($c=0; $c < $counterOfArrays; $c++) {
$individualCodesSubrray = $individualCodesSubarrays[$c];
print_r($individualCodesSubrray);
$countCodes = count($individualCodesSubrray);
echo $countCodes."\n";
for ($x=0; $x < $countCodes; $x++) {
$dummyCodeX = "X".$c;
array_push($inputStripped2, str_replace($dummyCodeX, $individualCodesSubrray[$x], $inputStripped));
}
print_r($inputStripped2);
}
One way you could achieve what you want is to first split the string on either space (on its own), '+' or '-', e.g.
$input = "A1 B2 - C3 + D4 / E5 / E6 C3 / A5";
$parts = preg_split('/(?<=[A-Za-z0-9])\s+(?=[A-IK-Za-ik-z])|\s+([+-])\s+/', $input, -1, PREG_SPLIT_DELIM_CAPTURE);
This gives:
Array (
[0] => A1
[1] => B2
[2] => -
[3] => C3
[4] => +
[5] => D4 / E5 / E6
[6] => C3 / A5
)
These values can then be further split on /
using:
foreach ($parts as &$part) {
$part = preg_split('#\s+/\s+#', $part);
}
This gives the following array of arrays:
Array (
[0] => Array (
[0] => A1
)
[1] => Array (
[0] => B2
)
[2] => Array (
[0] => -
)
[3] => Array (
[0] => C3
)
[4] => Array (
[0] => +
)
[5] => Array (
[0] => D4
[1] => E5
[2] => E6
)
[6] => Array (
[0] => C3
[1] => A5
)
)
You can now take the cross-products of these arrays using array_reduce
and a function like this:
function cross_product($array, $value) {
$output = array();
foreach ($array as $arr) {
foreach ($value as $val) {
$output[] = array_merge($arr, array($val));
}
}
return $output;
}
$init = array_map(function ($v) { return array($v); }, array_shift($parts));
$outputs = array_reduce($parts, 'cross_product', array($init));
Finally you can output imploded versions of each of the $outputs
array to give your desired result:
foreach ($outputs as $output) {
echo implode(' ', $output) . "\n";
}
Output:
A1 B2 - C3 + D4 C3
A1 B2 - C3 + D4 A5
A1 B2 - C3 + E5 C3
A1 B2 - C3 + E5 A5
A1 B2 - C3 + E6 C3
A1 B2 - C3 + E6 A5
Alternatively, for input "A1 / B2 - C3 + D4 / E5 / E6 C3 + A5"
you will get:
A1 - C3 + D4 C3 + A5
A1 - C3 + E5 C3 + A5
A1 - C3 + E6 C3 + A5
B2 - C3 + D4 C3 + A5
B2 - C3 + E5 C3 + A5
B2 - C3 + E6 C3 + A5