За последние 24 часа нас посетили 19139 программистов и 1643 робота. Сейчас ищут 903 программиста ...

Максимальное падение или просадка в массиве %

Тема в разделе "PHP для новичков", создана пользователем lemonl, 10 ноя 2016.

  1. lemonl

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

    С нами с:
    10 июн 2009
    Сообщения:
    164
    Симпатии:
    0
    Здравствуйте,

    Есть массив с динамикой чисел:

    PHP:
    1. $array_data = array(1,2,3,10,6,1,4,5,6,7,42,30,38);
    нужно найти максимальное падение или просадка в массиве в %.

    Например: в порядку очереди максимально число после которого началось падание было 10, максимально падение было до 1 (10-1 = 9), дале макс число 42 максимально падение было до 30 (42-30 = 12) Значит максимально падение было на 12 пунктов (или число в %).
     
    #1 lemonl, 10 ноя 2016
    Последнее редактирование модератором: 10 ноя 2016
  2. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.771
    Адрес:
    :сердА
    Показывай, как решал, что получилось, что не работает.
     
  3. Deonis

    Deonis Старожил

    С нами с:
    15 фев 2013
    Сообщения:
    1.521
    Симпатии:
    504
    Как по мне, то array_reduce должно хватить.
     
  4. Chushkin

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

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    Не хватит.
    Алгоритм состоит из двух частей: сначала найти пары максимум+минимум, затем рассчитать разницу и найти максимум.
     
  5. Deonis

    Deonis Старожил

    С нами с:
    15 фев 2013
    Сообщения:
    1.521
    Симпатии:
    504
    Не очень понимаю, о каком максимуме идет речь и для чего?
    Если, говоря о максимуме выше, имелось в виду максимальное значение в массиве, то да, нужно будет еще добавить функцию max. Но опять же - для каких целей? А так, больше ничего и не нужно.
     
  6. [vs]

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

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Чел хочет найти соседние элементы с максимальной разницей
     
  7. hust0

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

    С нами с:
    6 июл 2013
    Сообщения:
    321
    Симпатии:
    8
    А я как понял надо брать первые 4 числа и в них найти макс и мин значение и с макс отнять мин и т.д.
     
  8. Deonis

    Deonis Старожил

    С нами с:
    15 фев 2013
    Сообщения:
    1.521
    Симпатии:
    504
    Именно так я и понял задачу.
    Не обязательно первые четыре. Максимальная разница может быть и между двумя подряд идущими элементами.
     
  9. Abyss

    Abyss Старожил

    С нами с:
    12 дек 2015
    Сообщения:
    1.298
    Симпатии:
    218
    Адрес:
    Default city
    Если я понял, то все решается циклом и парочкой переменных для сравнений.
    PHP:
    1. $arr = [1,2,3,4,10,5,10,12,14,12];
    2. $temp = array_shift($arr);
    3. $maximum_fall = 0;
    4. foreach($arr as $num){
    5.     $diff = $temp - $num;
    6.     if($num < $temp && $maximum_fall < $diff){
    7.         $maximum_fall = $diff;
    8.     }
    9.     $temp = $num;
    10. }
    11. print $maximum_fall;
     
    lemonl нравится это.
  10. Deonis

    Deonis Старожил

    С нами с:
    15 фев 2013
    Сообщения:
    1.521
    Симпатии:
    504
    P.S. Задачу-то я решил, но @Fell-x27 задал вопрос ТС и пока не хочу выкладывать.
    --- Добавлено ---
    Похоже, что @Abyss не удержался.
     
  11. Abyss

    Abyss Старожил

    С нами с:
    12 дек 2015
    Сообщения:
    1.298
    Симпатии:
    218
    Адрес:
    Default city
    @Deonis ну вы ещё можете похоливарить как упростить этот говнокод (или усложнить) и помучать тса на предмет состоятельности как личности.
     
  12. Deonis

    Deonis Старожил

    С нами с:
    15 фев 2013
    Сообщения:
    1.521
    Симпатии:
    504
    @Abyss ни холиварить, ни мучатся я не собираюсь. Моё решение мало отличается от вашего.
    PHP:
    1. <?php
    2. $arr = [1, 2, 3, 10, 6, 1, 4, 5, 6, 7, 42, 30, 38];
    3. $max_drop = 0;
    4. array_reduce($arr, function ($carry, $item) use (&$max_drop) {
    5.    if($item < $carry && $max_drop < ($n = $carry - $item)) {
    6.      $max_drop = $n;
    7.    }
    8.   return $item;
    9. });
    10. echo 'Максимальное падение на ', $max_drop, ' пункт(ов)';
     
    lemonl нравится это.
  13. Abyss

    Abyss Старожил

    С нами с:
    12 дек 2015
    Сообщения:
    1.298
    Симпатии:
    218
    Адрес:
    Default city
    В среднем
    ~ 0.000013 foreach, tempvars
    ~ 0.000025 closure, pointer

    PHP:
    1. $arr = [1,2,3,10,6,1,4,5,6,7,42,30,38,1,2,3,10,6,1,4,5,6,7,42,30,38,1,2,3,10,6,1,4,5,6,7,42,30,38,1,2,3,10,6,1,4,5,6,7,42,30,38,1,2,3,10,6,1,4,5,6,7,42,30,38,1,2,3,10,6,1,4,5,6,7,42,30,38,1,2,3,10,6,1,4,5,6,7,42,30,38,45];
    http://sandbox.onlinephpfunctions.com/
    7.0.5
    Прогонов по 20

    Больше чем уверен в несостоятельности тестов, но если углубится, то думаю результат не изменится.
     
  14. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.771
    Адрес:
    :сердА
    Вы прям как будто ПО для космического аппарата разрабатываете, а не задачку для ленивого студента, которому "лишь бы работало".
     
  15. Chushkin

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

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    Замените 10 на 15 и протестируйте ещё раз.
    --- Добавлено ---
    Тоже самое, - замените 10 на 15 и протестируйте.
     
  16. Chushkin

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

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    Я был неправ, - можно обойтись без промежуточных массивов и решить задачку с помощью трёх внешних (относительно цикла) переменных.
     
  17. lemonl

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

    С нами с:
    10 июн 2009
    Сообщения:
    164
    Симпатии:
    0
    Deonis

    Большое спасибо ! А как получить падание в % ?

    вот данные моего массива, здесь 91 запись:

    HTML:
    1. [1,-5],[2,-14],[3,49],[4,35],[5,-7],[6,-15],[7,48],[8,36],[9,99],[10,67],[11,70],[12,90],[13,107],[14,170],[15,233],[16,296],[17,269],[18,243],[19,237],[20,223],[21,220],[22,200],[23,196],[24,195],[25,199],[26,262],[27,265],[28,328],[29,296],[30,281],[31,344],[32,318],[33,277],[34,258],[35,257],[36,240],[37,215],[38,229],[39,203],[40,198],[41,261],[42,261],[43,233],[44,201],[45,216],[46,279],[47,278],[48,301],[49,284],[50,289],[51,286],[52,276],[53,301],[54,300],[55,279],[56,247],[57,192],[58,182],[59,172],[60,153],[61,216],[62,214],[63,277],[64,285],[65,348],[66,341],[67,404],[68,411],[69,412],[70,391],[71,390],[72,453],[73,516],[74,510],[75,505],[76,490],[77,454],[78,466],[79,467],[80,460],[81,439],[82,502],[83,499],[84,562],[85,577],[86,546],[87,491],[88,519],[89,499],[90,468],[91,531]
    Если построить график по этим данным, можно будет увидеть что есть падание с 344 до 153 ... а функция показывает падение на 95 пункта !?
     
    #17 lemonl, 11 ноя 2016
    Последнее редактирование: 11 ноя 2016
  18. Deonis

    Deonis Старожил

    С нами с:
    15 фев 2013
    Сообщения:
    1.521
    Симпатии:
    504
    Если построить график, то я наблюдаю (чисто визуально) максимальное падение от 301 до 153. Это без промежуточных подъёмов, как между 344 и 153. В любом случае, код мой работает не верно. Немного поправил, но судя по вашему предыдущему комментарию, ощущение, что вам нужен другой результат.
    PHP:
    1. <?php
    2. $max_drop = 0;
    3. $pick = 0;
    4. array_reduce($arr, function ($carry, $item) use (&$pick, &$max_drop) {
    5.    if ($carry > $item && $pick < $carry) {
    6.      $pick = $carry;
    7.    } elseif ($carry < $item && $pick > $carry) {
    8.      $drop = $pick - $carry;
    9.      if ($max_drop < $drop) {
    10.        $max_drop = $drop;
    11.      }
    12.      $pick = $carry;
    13.    }
    14.    return $item;
    15. });
    16. echo 'Максимальное падение на ', $max_drop, ' пункт(ов)
    17. или на ', ($max_drop * 100 / max($arr)), '%';
     
  19. Abyss

    Abyss Старожил

    С нами с:
    12 дек 2015
    Сообщения:
    1.298
    Симпатии:
    218
    Адрес:
    Default city
    PHP:
    1. $arr = [1,2,3,4,15,5,15,12,14,12];
    result = 10
    --- Добавлено ---
    Между примером в начале и в конце есть разница, не ? Массив и массив массивов.
     
  20. Chushkin

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

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    Ты не понял. Используй исходные данные ТС, а не свои доморощенные.
     
  21. lemonl

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

    С нами с:
    10 июн 2009
    Сообщения:
    164
    Симпатии:
    0
    Deonis

    Это не массив массивов, я так пронумеровал данные. Это одномерный массив ...

    [​IMG]
    http://piccy.info/view3/10505944/b977a18633c29d85a8f65b8d5081856f/

    На следующем рисунке цифрами показаны основные стадии изменения величины просадки в процессе. Итоговое значение максимальной просадки выделено утолщенными стрелками.

    просадка - это максимальная разница между одним из локальных верхних экстремумов графика и последующих нижних экстремумов.

    301 идет после 344 ... значит больше 344 (344-153)

    просадка = Max of (Maximal Peak - next Minimal Peak)
     
    #21 lemonl, 11 ноя 2016
    Последнее редактирование: 11 ноя 2016
  22. Deonis

    Deonis Старожил

    С нами с:
    15 фев 2013
    Сообщения:
    1.521
    Симпатии:
    504
    @lemonl, давайте еще одну попытку:
    PHP:
    1. <?php
    2. $max_drop = 0;
    3. $top_point = 0;
    4. $tmp = [];
    5. array_reduce($arr, function ($carry, $item) use (&$tmp, &$top_point, &$max_drop) {
    6.    if($item > $top_point) {
    7.      if( !empty($tmp) && ($diff = $top_point - min($tmp)) >  $max_drop) {
    8.        $max_drop = $diff;
    9.      }
    10.      $top_point = $item;
    11.      $tmp = [];
    12.    } else {
    13.      $tmp[] = $item;
    14.    }
    15.    return $item;
    16. });
    17. echo 'Максимальное падение на ', $max_drop, ' пункт(ов)';
     
    denis01 и lemonl нравится это.
  23. lemonl

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

    С нами с:
    10 июн 2009
    Сообщения:
    164
    Симпатии:
    0
    Deonis

    Громадно спасибо ! Если считать падение в % наверно логичней брать максимальное число пика (после которого началось падение), а не max($arr) макс. число массива ). Как это можно сделать ?
     
  24. Deonis

    Deonis Старожил

    С нами с:
    15 фев 2013
    Сообщения:
    1.521
    Симпатии:
    504
    @lemonl, что касается процентов, то это вам должно быть видней. Я в форекс-клубе не состоял, поэтому не знаю, какое значение, в данном случае, принято брать за 100%.
     
    denis01 нравится это.
  25. Chushkin

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

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    Судя по написанному, вначале задача была описана неправильно.
    Теперь я не уверен, что задачу можно решить с помощью трёх внешних переменных. Тут опять думать надо, но уже не интересно. :(
     
    denis01 нравится это.