За последние 24 часа нас посетили 22686 программистов и 1279 роботов. Сейчас ищут 792 программиста ...

[задачка] Сумма конкатенаций

Тема в разделе "Прочие вопросы по PHP", создана пользователем artoodetoo, 23 дек 2020.

Метки:
  1. johovich

    johovich Активный пользователь

    С нами с:
    24 авг 2016
    Сообщения:
    146
    Симпатии:
    17
    Устранил ошибку ( round(log10($n), 0) ) и добавил комментарии на русском.
    Код (Text):
    1. function sum_jo5($a) {
    2.     $size = count($a); //длина массива
    3.     $s = 0; //здесь будет результат
    4.     $ranks = array_fill(1, 9, 0); //для разрядов чисел и кол-ва повторений
    5.  
    6.     array_walk($a, //тут посчитаем разряды чисел и повторения
    7.         function(&$n) use(&$ranks)
    8.         {
    9.             if ($n == 0) return;
    10.             ++$ranks[(int)round(log10($n) + 0.5, 0)];
    11.         }
    12.     );
    13.  
    14.     $ranks = array_filter($ranks); //удалим разряды, для которых ни 1 повторения не было найдено
    15.  
    16.     foreach($ranks as $i=>$rank){//для каждого разряда
    17.         $pow = pow(10, $i);
    18.         array_walk($a, //берем само число и дописываем к нему нулей по числу разрядов
    19.         function(&$n) use (&$s, $pow, $rank, $size)
    20.             {$s += $n * $pow * $rank + $n * $size;} //само число войдет в сумму столько раз,
    21.         );                                            //сколько было чисел всего
    22.     }
    23.  
    24.     return  $s;
    25. }
     
  2. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.553
    Симпатии:
    631
    @johovich честно говоря результат снова не сходится.
    Еще заметил, что у других функций, кроме функции @artoodetoo производительность падает если массив состоит из уникальных значений. Потому что там перебираются ключи дважды, а в этом случае число ключей та же тысяча.
     
  3. johovich

    johovich Активный пользователь

    С нами с:
    24 авг 2016
    Сообщения:
    146
    Симпатии:
    17
    Да. Хорошо, что заметил. Нашел 2 ошибки. Спасибо.


    Вот нормальный код:
    Код (Text):
    1.  
    2. function sum_jo5($a) {
    3.     $size = count($a); //длина массива
    4.     $s = 0; //здесь будет результат
    5.     $ranks = array_fill(1, 9, 0); //для разрядов чисел и кол-ва повторений
    6.  
    7.  
    8.     array_walk($a, //тут посчитаем разряды в числе и повторения
    9.         function($n) use(&$ranks, &$s, $size)
    10.         {
    11.             $rank = $n == 0 ? 1 : (int)round(log10($n) + 0.5, 0);
    12.             ++$ranks[$rank];
    13.             $s += $n * $size; //Каждое число обязательно входит в сумму такое число раз, сколько чисел в исходном наборе
    14.         }
    15.     );
    16.  
    17.     $ranks = array_filter($ranks); //удалим разряды, для которых ни 1 повторения не было найдено
    18.  
    19.     foreach($ranks as $i=>$rank){//для каждого разряда
    20.         $pow = pow(10, $i);
    21.         array_walk($a, //берем само число и дописываем к нему нулей по числу разрядов, умножаем на число вхождений этого разряда
    22.         function($n) use (&$s, $pow, $rank)
    23.             {$s += $n * $pow * $rank;}
    24.         );                                          
    25.     }
    26.  
    27.     return  $s;
    28. }
     
    #28 johovich, 25 дек 2020
    Последнее редактирование: 25 дек 2020
  4. Chushkin

    Chushkin Активный пользователь

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    Просто немного поправил код и вставил сётчики.
     

    Вложения:

  5. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.553
    Симпатии:
    631
    В итоге на оригинальном массиве:
    Код (Text):
    1.  
    2. sum_vs    | Time: 0.000034, Iterations:     256, Sum: 60059300
    3. sum_fel   | Time: 0.000042, Iterations:     256, Sum: 60059300
    4. sum_arte  | Time: 0.000203, Iterations:    3000, Sum: 60059300
    5. sum_jo5   | Time: 0.000795, Iterations:       5, Sum: 60059300
    на твоем массиве:
    Код (Text):
    1. sum_arte  | Time: 0.000254, Iterations:    4000, Sum: 454594950000
    2. sum_jo5   | Time: 0.000969, Iterations:       7, Sum: 454594950000
    3. sum_vs    | Time: 0.098036, Iterations: 1000000, Sum: 454594950000
    4. sum_fel   | Time: 0.164514, Iterations: 1000000, Sum: 454594950000
    Твой метод и метод @artoodetoo дают наиболее постоянный результат по количеству итераций и скорости, два других сильно зависят от количества повторений.