Сплющить дерево и отслеживать путь к каждому листу - PullRequest
0 голосов
/ 06 июля 2019

У меня есть «рецепт еды», в котором все вспомогательные ингредиенты, которые используются для приготовления рецепта, структурированы в виде дерева.

. Ранее я получил некоторую помощь в создании некоторого кода для выравнивания дерева и вычисленияВес каждого базового ингредиента (листа): Как рассчитать количество каждого ингредиента?

Но теперь я также хочу отследить, как готовится каждый ингредиент (но все же суммирую вес ингредиентов).

Я добавил для каждого узла дополнительный атрибут, называемый «подготовка»

, но я пытаюсь выяснить, как я могу отслеживать всю цепочку подготовки.

Вот пример структуры дерева рецептов:

$tree = [
    [
        'name' => 'a',
        'weight' => 1,
        'preparation' => 'boiled',
        'tree' => [
            [
                'name' => 'c',
                'weight' => 3,
                'preparation' => 'baked',
            ],
            [
                'name' => 'c',
                'weight' => 3,
                'preparation' => 'fried',
            ],
        ]
    ],
    [
        'name' => 'b',
        'weight' => 1,
        'preparation' => 'boiled',
        'tree' => [
            [
                'name' => 'd',
                'weight' => 4,
                'preparation' => 'none',
                'tree' => [
                    [
                        'name' => 'e',
                        'weight' => 1,
                        'preparation' => 'fried',
                    ],
                    [
                        'name' => 'f',
                        'weight' => 1,
                        'preparation' => 'none',
                    ]
                ]
            ],
            [
                'name' => 'c',
                'weight' => 1,
                'preparation' => 'baked',              // b[1]c has the same "preperation chain" as a[0]c
            ]
        ]
    ],
    [
        'name' => 'c',
        'weight' => 1,
        'preparation' => 'none',
    ]
];

И я хочу, чтобы она была уменьшена до массива каждого "базового веса ингредиента" (лист) и цепочки приготовления (путь).

array (
  'c-baked,boiled'      => 0.7,
  'c-fried,boiled'      => 0.5,
  'e-fried,none,boiled' => 0.4,
  'f-none,none,boiled'  => 0.4,
  'c-none'              => 1,
)

Ради аргумента вот так выглядит результат без учета подготовки:

array (
  'c' => 2.2,   // 0.7 + 0.5 + 1
  'e' => 0.4,
  'f' => 0.4,
)

Мне удалось получить только код для отслеживания подготовки of базовый ингредиент (лист), а не полная цепочка:

array (
  'c-baked,boiled' => 0.2,
  'c-fried,boiled' => 0.5,
  'e-fried,none,boiled' => 0.4,
  'f-none,none,boiled' => 0.4,
  'c-none' => 1,
)

Вот как выглядит код:

//function getBaseIngredients(array $tree): array
function getBaseIngredients(array $tree, $preparation = null): array
{
    $leafs = [];

    // Loop through the nodes in the tree if the node 
    // is a leaf we sum the weight, otherwise we recursivly
    // call our self and resolve the branch
    foreach($tree as $node){
        if(empty($node['tree']))
        {

            // if there are no parts, just add the weight

            //$key = $node['name'] . '-' . $node['preparation'];
            $key = $node['name'] . '-' . $node['preparation'] . $preparation;

            if(!array_key_exists($node['name'], $leafs)) {
                $leafs[$key] = 0;
            }

            $leafs[$key] += $node['weight'];

        } else {

            // if there sub nodes, get the full weight node
            $nodes = getBaseIngredients($node['tree'], $preparation);
            $total = array_sum($nodes);

            // Scale each sub node according to the parent
            foreach($nodes as $key => $weight){

                if(!array_key_exists($key, $leafs)) {
                    //$leafs[$key] = 0;
                    $leafs[$key . ',' . $node['preparation']] = 0;
                }

                // Total weight of particular node is the 
                // sub node out of the sub node full weight
                // times the weight for this particular leaf

                // $leafs[$key] += $node['weight'] * ($weight / $total);
                $leafs[$key . ',' . $node['preparation']] += $node['weight'] * ($weight / $total);
            }
        }
    }

    return $leafs;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...