Logical path generation algorithm

I am trying to develop an algorithm for creating a symfony template service. I want to check if a pattern exists in a subset of the paths ordered.

Given an array of parameters like this (already ordered as I want):

$params = ['O', 'U', 'W', 'P']

How can I infer this array?

$urls = [
    'O/U/W/P/template',
    'O/U/W/template',
    'O/U/P/template',
    'O/U/template',
    'O/W/P/template',
    'O/W/template',
    'O/P/template',
    'O/template',
    'U/W/P/template',
    'U/W/template',
    'U/P/template',
    'U/template',
    'W/P/template',
    'W/template',
    'P/template',
    'template'
];

I can execute for a small list of parameters (for example, anyone can do this, I suppose) with this code:

private function getPaths($template, $params)
{
    $urls           = [];
    $alreadyPerform = [];
    $paramsCounter = count($params);

    for ($i = 0; $i < $paramsCounter; $i++) {
        for ($j = 0; $j < $paramsCounter; $j++) {
            if ($i !== $j && !in_array($params[$j], $alreadyPerform, true)) {
                $urls[] = sprintf(
                    '/%s/%s/%s.html.twig', $params[$i], $params[$j], $template
                );
            }
        }
        $alreadyPerform[] = $params[$i];
        $urls[] = sprintf('/%s/%s.html.twig', $params[$i], $template);
    }
    $urls[] = sprintf('%s.html.twig', $template);

    return $urls;
}

This function works the way I wanted until today (maximum 3 parameters), but I want to add one parameter today, possibly more after.

Many thanks for your help!

Greetings.

+4
source share
2 answers

Using recursion, you can do the following:

/**
 * @param array $elements
 * @param array $extra
 *
 * @return Generator
 */
function gen(array $elements, array $extra = []): \Generator {

    foreach ($elements as $i => $head) {
        foreach (gen(array_slice($elements, $i + 1), $extra) as $tail) {
            yield array_merge([$head], $tail);
        }
    }

    yield $extra;
}

demo: https://3v4l.org/gJB8q


Or without recursion:

/**
 * @param array $elements
 *
 * @return Generator
 */
function gen2(array $elements): \Generator {

    for ($num = count($elements), $i = pow(2, $num) - 1; $i >= 1; $i -= 2) {
        $r = [];
        for ($j = 0; $j < $num; $j += 1) {
            if ($i & (1 << ($num - $j - 1))) {
                $r[] = $elements[$j];
            }
        }

        yield $r;
    }
}

demo: https://3v4l.org/grKXo

+2

:

https://github.com/drupol/phpermutations

, :

$permutations = new \drupol\phpermutations\Generators\Permutations(['A', 'B', 'C'], 2);
foreach ($permutations->generator() as $permutation) {
    echo implode('/', $permutation);
    echo "\n";
}

A/B
B/A
A/C
C/A
B/C
C/B
+1

Source: https://habr.com/ru/post/1690264/


All Articles