как можно оптимизировать код, код внутри

266
21 сентября 2017, 17:23
$W1 = "a";
For($Q = 1; $Q <= 12; $Q++){
        $TVal = $W1 . "_" . $Q;
        For($W = $Q; $W <= 12; $W++){
            If($W > $Q) $TVal = $W1 . "_" . $Q . "_" . $W;
            If(!In_Array($TVal, $PreSetArray)) $PreSetArray[] = $TVal;
            For($E = $W; $E <= 12; $E++){
                If($W > $Q && $E > $W) $TVal = $W1 . "_" . $Q . "_" . $W . "_" . $E;
                If(!In_Array($TVal, $PreSetArray)) $PreSetArray[] = $TVal;
                For($R = $E; $R <= 12; $R++){
                    If($W > $Q && $E > $W && $R > $E) $TVal = $W1 . "_" . $Q . "_" . $W . "_" . $E . "_" . $R;
                    If(!In_Array($TVal, $PreSetArray)) $PreSetArray[] = $TVal;
                    For($T = $R; $T <= 12; $T++){
                        If($W > $Q && $E > $W && $R > $E && $T > $R) $TVal = $W1 . "_" . $Q . "_" . $W . "_" . $E . "_" . $R . "_" . $T;
                        If(!In_Array($TVal, $PreSetArray)) $PreSetArray[] = $TVal;
                        For($Y = $T; $Y <= 12; $Y++){
                            If($W > $Q && $E > $W && $R > $E && $T > $R && $Y > $T) $TVal = $W1 . "_" . $Q . "_" . $W . "_" . $E . "_" . $R . "_" . $T . "_" . $Y;
                            If(!In_Array($TVal, $PreSetArray)) $PreSetArray[] = $TVal;
                            For($U = $Y; $U <= 12; $U++){
                                If($W > $Q && $E > $W && $R > $E && $T > $R && $Y > $T && $U > $Y) $TVal = $W1 . "_" . $Q . "_" . $W . "_" . $E . "_" . $R . "_" . $T . "_" . $Y . "_" . $U;
                                If(!In_Array($TVal, $PreSetArray)) $PreSetArray[] = $TVal;
                                For($I = $U; $I <= 12; $I++){
                                    If($W > $Q && $E > $W && $R > $E && $T > $R && $Y > $T && $U > $Y && $I > $U) $TVal = $W1 . "_" . $Q . "_" . $W . "_" . $E . "_" . $R . "_" . $T . "_" . $Y . "_" . $U . "_" . $I;
                                    If(!In_Array($TVal, $PreSetArray)) $PreSetArray[] = $TVal;
                                    For($O = $I; $O <= 12; $O++){
                                        If($W > $Q && $E > $W && $R > $E && $T > $R && $Y > $T && $U > $Y && $I > $U && $O > $I) $TVal = $W1 . "_" . $Q . "_" . $W . "_" . $E . "_" . $R . "_" . $T . "_" . $Y . "_" . $U . "_" . $I. "_" . $O;
                                        If(!In_Array($TVal, $PreSetArray)) $PreSetArray[] = $TVal;
                                        For($P = $O; $P <= 12; $P++){
                                            If($W > $Q && $E > $W && $R > $E && $T > $R && $Y > $T && $U > $Y && $I > $U && $O > $I && $P > $O) $TVal = $W1 . "_" . $Q . "_" . $W . "_" . $E . "_" . $R . "_" . $T . "_" . $Y . "_" . $U . "_" . $I . "_" . $O . "_" . $P;
                                            If(!In_Array($TVal, $PreSetArray)) $PreSetArray[] = $TVal;
                                            For($A = $P; $A <= 12; $A++){
                                                If($W > $Q && $E > $W && $R > $E && $T > $R && $Y > $T && $U > $Y && $I > $U && $O > $I && $P > $O && $A > $P) $TVal = $W1 . "_" . $Q . "_" . $W . "_" . $E . "_" . $R . "_" . $T . "_" . $Y . "_" . $U . "_" . $I . "_" . $O . "_" . $P . "_" . $A;
                                                If(!In_Array($TVal, $PreSetArray)) $PreSetArray[] = $TVal;
                                                For($S = $A; $S <= 12; $S++){
                                                    If($W > $Q && $E > $W && $R > $E && $T > $R && $Y > $T && $U > $Y && $I > $U && $O > $I && $P > $O && $A > $P && $S > $A) $TVal = $W1 . "_" . $Q . "_" . $W . "_" . $E . "_" . $R . "_" . $T . "_" . $Y . "_" . $U . "_" . $I . "_" . $O . "_" . $P . "_" . $A . "_" . $S;
                                                    If(!In_Array($TVal, $PreSetArray)) $PreSetArray[] = $TVal;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

Этот код генерит строки вида … "a_1_4_7"… "a_5_6_10_12"… и так далее, т.е в строке от 1 до 12 цифр, цифра слева всегда должна быть меньше цифры справа. Этот код выполняется 271 секунду :-) есть идеи как его оптимизировать? Умникам, которые закрывают посты просьба питлять мимо… С рекурсией не дружу пока,если это возможно сделать рекурсией поделитесь пожалуйста кодом, цель не сократить код, а уменьшить время выполнения

Answer 1

Шаг 1.

Все эти конструкции:

If(..) $TVal = $W1 . "_" ...;
If(!In_Array($TVal, $PreSetArray)) $PreSetArray[] = $TVal;

Замените на:

If(..) { $TVal = $W1 . "_" ...; $PreSetArray[$TVal] = $TVal; }

А в самом конце кода добавьте (чтоб получить тот же массив что вы получаете сейчас):

$PreSetArray = array_values($PreSetArray);

Время сократится на порядок. Или даже больше.

Шаг 2.

Все циклы явно начинайте с подходящего значения. Т.е. всё это:

For($W = $Q; $W <= 12; $W++){

Замените на это (для всех циклов for в вашем коде добавить + 1):

For($W = $Q + 1; $W <= 12; $W++){

И после этого уберите условия внутри цикла:

If($W > $Q) .. // такое условие можно убрать везде

Время сократится ещё примерно на 2 порядка.

Шаг 3.

Очевидно, что действия внутри каждого цикла - шаблонные. И их можно попробовать вынести в функцию. Для начала напишем не рекурсивную, для самого глубоко-вложенного цикла (тот, что не вызывает других внутри себя):

function append(&$target, $from, $prefix)
{
    for ($i = $from; $i < 13; $i++) {
        $val = "{$prefix}_{$i}";
        $target[$val] = $val;
    }
}

.. и заменим этот старый цикл ..

For($S = $A + 1; $S <= 12; $S++){
    $TVal = $W1 . "_" . $Q . "_" . $W . "_" . $E . "_" . $R . "_" . $T . "_" . $Y . "_" . $U . "_" . $I . "_" . $O . "_" . $P . "_" . $A . "_" . $S;
    $PreSetArray[$TVal] = $TVal;
}

На вызов функции:

append($PreSetArray, $A + 1, $W1 . "_" . $Q . "_" . $W . "_" . $E . "_" . $R . "_" . $T . "_" . $Y . "_" . $U . "_" . $I . "_" . $O . "_" . $P . "_" . $A);

Шаг 4.

Теперь циклов стало на 1 меньше. Посмотрим на самый глубоко-вложенный. Заметим, что он вызывал вложенного в себя увеличивая стартовое значение цикла и меняя префикс. Давайте сделаем это прямо внутри функции превратив её в рекурсивную:

function append(&$target, $from, $prefix)
{
    for ($i = $from; $i < 13; $i++) {
        $val = "{$prefix}_{$i}";
        $target[$val] = $val;
        append($target, $i + 1, $val);
    }
}

И сразу же удаляем все циклы заменяя их одним единственным вызовом функции. Итоговый код всего скрипта:

function append(&$target, $from, $prefix)
{
    for ($i = $from; $i < 13; $i++) {
        $val = "{$prefix}_{$i}";
        $target[$val] = $val;
        append($target, $i + 1, $val);
    }
}
$PreSetArray = [];
append($PreSetArray, 1, "a");
$PreSetArray = array_values($PreSetArray);

У меня скрипт отрабатывает за 0.0016 sec. Для сравнения ваш исходный отрабатывал за 10-12 секунд.

READ ALSO
update sql foreach php array

update sql foreach php array

Добрый день или вечер)

246
как вывести нужную запись по id из БД

как вывести нужную запись по id из БД

Доброго времени суток, есть БД news из которой на индексной странице выводится заголовок и анонс новостиС помощью ссылки, через id осуществляется...

286
Оптимизация выборки из базы данных

Оптимизация выборки из базы данных

Есть две таблицы b_stat_city_ip (поля таблицы START_IP, END_IP, COUNTRY_ID, CITY_ID), b_stat_city (поля ID, COUNTRY_ID, REGION, NAME)Необходимо получить ip адрес и узнать входит ли он в диапазон...

191