Здравствуйте, Есть массив с динамикой чисел: PHP: $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 пунктов (или число в %).
Не хватит. Алгоритм состоит из двух частей: сначала найти пары максимум+минимум, затем рассчитать разницу и найти максимум.
Не очень понимаю, о каком максимуме идет речь и для чего? Если, говоря о максимуме выше, имелось в виду максимальное значение в массиве, то да, нужно будет еще добавить функцию max. Но опять же - для каких целей? А так, больше ничего и не нужно.
Именно так я и понял задачу. Не обязательно первые четыре. Максимальная разница может быть и между двумя подряд идущими элементами.
Если я понял, то все решается циклом и парочкой переменных для сравнений. PHP: $arr = [1,2,3,4,10,5,10,12,14,12]; $temp = array_shift($arr); $maximum_fall = 0; foreach($arr as $num){ $diff = $temp - $num; if($num < $temp && $maximum_fall < $diff){ $maximum_fall = $diff; } $temp = $num; } print $maximum_fall;
P.S. Задачу-то я решил, но @Fell-x27 задал вопрос ТС и пока не хочу выкладывать. --- Добавлено --- Похоже, что @Abyss не удержался.
@Deonis ну вы ещё можете похоливарить как упростить этот говнокод (или усложнить) и помучать тса на предмет состоятельности как личности.
@Abyss ни холиварить, ни мучатся я не собираюсь. Моё решение мало отличается от вашего. PHP: <?php $arr = [1, 2, 3, 10, 6, 1, 4, 5, 6, 7, 42, 30, 38]; $max_drop = 0; array_reduce($arr, function ($carry, $item) use (&$max_drop) { if($item < $carry && $max_drop < ($n = $carry - $item)) { $max_drop = $n; } return $item; }); echo 'Максимальное падение на ', $max_drop, ' пункт(ов)';
В среднем ~ 0.000013 foreach, tempvars ~ 0.000025 closure, pointer PHP: $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 Больше чем уверен в несостоятельности тестов, но если углубится, то думаю результат не изменится.
Вы прям как будто ПО для космического аппарата разрабатываете, а не задачку для ленивого студента, которому "лишь бы работало".
Замените 10 на 15 и протестируйте ещё раз. --- Добавлено --- Тоже самое, - замените 10 на 15 и протестируйте.
Я был неправ, - можно обойтись без промежуточных массивов и решить задачку с помощью трёх внешних (относительно цикла) переменных.
Deonis Большое спасибо ! А как получить падание в % ? вот данные моего массива, здесь 91 запись: HTML: [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 пункта !?
Если построить график, то я наблюдаю (чисто визуально) максимальное падение от 301 до 153. Это без промежуточных подъёмов, как между 344 и 153. В любом случае, код мой работает не верно. Немного поправил, но судя по вашему предыдущему комментарию, ощущение, что вам нужен другой результат. PHP: <?php $max_drop = 0; $pick = 0; array_reduce($arr, function ($carry, $item) use (&$pick, &$max_drop) { if ($carry > $item && $pick < $carry) { $pick = $carry; } elseif ($carry < $item && $pick > $carry) { $drop = $pick - $carry; if ($max_drop < $drop) { $max_drop = $drop; } $pick = $carry; } return $item; }); echo 'Максимальное падение на ', $max_drop, ' пункт(ов) или на ', ($max_drop * 100 / max($arr)), '%';
PHP: $arr = [1,2,3,4,15,5,15,12,14,12]; result = 10 --- Добавлено --- Между примером в начале и в конце есть разница, не ? Массив и массив массивов.
Deonis Это не массив массивов, я так пронумеровал данные. Это одномерный массив ... http://piccy.info/view3/10505944/b977a18633c29d85a8f65b8d5081856f/ На следующем рисунке цифрами показаны основные стадии изменения величины просадки в процессе. Итоговое значение максимальной просадки выделено утолщенными стрелками. просадка - это максимальная разница между одним из локальных верхних экстремумов графика и последующих нижних экстремумов. 301 идет после 344 ... значит больше 344 (344-153) просадка = Max of (Maximal Peak - next Minimal Peak)
@lemonl, давайте еще одну попытку: PHP: <?php $max_drop = 0; $top_point = 0; $tmp = []; array_reduce($arr, function ($carry, $item) use (&$tmp, &$top_point, &$max_drop) { if($item > $top_point) { if( !empty($tmp) && ($diff = $top_point - min($tmp)) > $max_drop) { $max_drop = $diff; } $top_point = $item; $tmp = []; } else { $tmp[] = $item; } return $item; }); echo 'Максимальное падение на ', $max_drop, ' пункт(ов)';
Deonis Громадно спасибо ! Если считать падение в % наверно логичней брать максимальное число пика (после которого началось падение), а не max($arr) макс. число массива ). Как это можно сделать ?
@lemonl, что касается процентов, то это вам должно быть видней. Я в форекс-клубе не состоял, поэтому не знаю, какое значение, в данном случае, принято брать за 100%.
Судя по написанному, вначале задача была описана неправильно. Теперь я не уверен, что задачу можно решить с помощью трёх внешних переменных. Тут опять думать надо, но уже не интересно.