
Требуется элегантное решение вопроса...
Имеем биллинговую систему через смс биллинг..
Имеем кучу стран, в которых смс стоят по разному..
имеем товары , которые тоже стоят по разному..
во время запроса в биллинг систему можем вытянуть список кодов смс для данной страны, с ценами по каждому коду..
например
sdfs = 0.25USD
fras = 0.5USD
dfas = 1USD
dasa = 6USD
и тд
к примеру мой товар стоит 3 доллара, но нет смс с ценой 3 доллара, нужно определить стоимость ближайшей смс:
есть три способа определения ближайшей цены
1. определить ближайшую цену но меньше цены товара, например в данном случае подойдет код dfas = 1USD
2. определить ближайшую цену выше стоимости товара, в данном случае dasa = 6USD
3. определить цену с наименьшим расхождением, тоесть в данном случае 6-3 = 2 доллара разницы, а 3-1 = 2, тоесть наименьшее расхождение = dfas = 1USD
все цены смс приходят в массиве, настройка по какой методике определять стоимость = значение переменной в конфигурации, например
$method = 'nearest';
//$method = 'higher';
//$method = 'lower';
Интересует кто предложит более элегантное решение вопроса выбора кода, который показать пользователю.
p.s вариантов цен может придти куча...
приходят они в массиве в виде
[0] => Array
(
[workingPrice] => 9.990
[code] => 'dasdsa'
)
[1] => Array
(
[workingPrice] => 6.990
[code] => 'gggdr'
)
//Все имена и события вымышленные, любое совпадение считать случайностью

Спустя 19 минут, 31 секунда (20.10.2009 - 13:39) sergeiss написал(а):
Если я правильно понял задачу, на входе имеет массив стоимостей СМС, отсотрированный по ценам, и стоимость товара в виде одного числа.
Используем метод половинного деления. Проще вряд ли что будет.
Используем метод половинного деления. Проще вряд ли что будет.
Спустя 10 минут, 39 секунд (20.10.2009 - 13:49) jetistyum написал(а):
sergeiss, я ща конечно буду гуглить, но если не сложно, мог бы ты объяснить что за метод такой и применение этого метода, т.к. математика не мой конек

Спустя 9 минут, 56 секунд (20.10.2009 - 13:59) jetistyum написал(а):
вроде понял более-мене.. только для десятка значений, думаю будет проще методом перебора...
Спустя 29 секунд (20.10.2009 - 14:00) sergeiss написал(а):
ОК, показываю на примере 
Предложи человеку загадать любое число в диапазоне от 1 до 100, и скажи, что ты угадаешь его не более, чем за 7 шагов. Ты будешь называть число, а человек будет только говорить, что его число больше или меньше твоего.
Например, он загадал 33.
Ты находишь среднее (целое) между 1 и 100... Называешь 50. Тебе говорят: меньше.
ОК. 1-50 - среднее 25. Называешь 25. Говорят: больше.
25-50... Среднее 38. Говорят: меньше.
25-38... Среднее 32. Говорят: больше.
32-38... Среднее 36. Меньше.
32-36... Среднее 34. Меньше.
32-34... Уже угадали
Ответ 33.
Сколько шагов? Ровно 7 получилось. Но это - максимум. Может быть и меньше.
Если же ты будешь перебирать последовательно, то при загадывании 99 будет 99 шагов, больше в 14 (!) раз.
И кстати. Если загадать число "до 1000" (а если уж совсем точно, до 1024), то будет не более 10 шагов на отгадывание... Только устно считать уже сложнее, чем "до 100"
Я надеюсь, что на примере понятно всё было.

Предложи человеку загадать любое число в диапазоне от 1 до 100, и скажи, что ты угадаешь его не более, чем за 7 шагов. Ты будешь называть число, а человек будет только говорить, что его число больше или меньше твоего.
Например, он загадал 33.
Ты находишь среднее (целое) между 1 и 100... Называешь 50. Тебе говорят: меньше.
ОК. 1-50 - среднее 25. Называешь 25. Говорят: больше.
25-50... Среднее 38. Говорят: меньше.
25-38... Среднее 32. Говорят: больше.
32-38... Среднее 36. Меньше.
32-36... Среднее 34. Меньше.
32-34... Уже угадали

Сколько шагов? Ровно 7 получилось. Но это - максимум. Может быть и меньше.
Если же ты будешь перебирать последовательно, то при загадывании 99 будет 99 шагов, больше в 14 (!) раз.
И кстати. Если загадать число "до 1000" (а если уж совсем точно, до 1024), то будет не более 10 шагов на отгадывание... Только устно считать уже сложнее, чем "до 100"

Я надеюсь, что на примере понятно всё было.
Спустя 31 минута, 35 секунд (20.10.2009 - 14:31) jetistyum написал(а):
Спасибо, я так примерно и представлял!
в любом случае в копилку еще один алгоритм!
я реализовал у себя на простом переборе, т.к. кол-во возможных смс не более 10 обычно....
в любом случае в копилку еще один алгоритм!
я реализовал у себя на простом переборе, т.к. кол-во возможных смс не более 10 обычно....
PHP |
//получили xml, распарсили его в объект, далее: |
вроде работает, но может кто=то что-то более логичное предложит?
Спустя 1 минута, 20 секунд (20.10.2009 - 14:33) jetistyum написал(а):
вот такой вот блин код, со смайликами ...
Спустя 1 час, 13 секунд (20.10.2009 - 15:33) Sylex написал(а):
Цитата (jetistyum @ 20.10.2009 - 16:19) |
есть три способа определения ближайшей цены |
есть 1 способ, и тот, который тебе нужен... К примеру, если я продаю товар в 4$, но SMS с ценой ближайшая - 3$, то я не собираюсь переплачивать сам за товар =)
PHP |
<?php |
На счет красоты - не парился, описал общий алгоритм - нужно найти мин. абс. разницу
Спустя 1 час, 7 минут, 21 секунда (20.10.2009 - 16:40) jetistyum написал(а):
Sylex
Нет, как раз таки админ должен в настройках указывать метод определения цены....
то есть все три метода должны работать, это в ТЗ... не обсуждается. мне интересен сам способ перебора массива.. элегантное решение
Нет, как раз таки админ должен в настройках указывать метод определения цены....
то есть все три метода должны работать, это в ТЗ... не обсуждается. мне интересен сам способ перебора массива.. элегантное решение
Спустя 18 минут, 41 секунда (20.10.2009 - 16:59) glock18 написал(а):
Цитата |
Ты находишь среднее (целое) между 1 и 100... Называешь 50. Тебе говорят: меньше. ОК. 1-50 - среднее 25. Называешь 25. Говорят: больше. 25-50... Среднее 38. Говорят: меньше. 25-38... Среднее 32. Говорят: больше. 32-38... Среднее 36. Меньше. 32-36... Среднее 34. Меньше. 32-34... Уже угадали Ответ 33. |
я бы первым называл влюбом случае только степень двойки

Спустя 17 минут, 17 секунд (20.10.2009 - 17:16) Sylex написал(а):
jetistyum
ну тогда наверное ты сделал нормально
ну тогда наверное ты сделал нормально

Спустя 1 месяц, 2 дня, 13 часов, 26 минут, 38 секунд (23.11.2009 - 07:43) dr_Lev написал(а):
jetistyum Зачем на каждой итерации вычислять $delta... Можно так : перебор массива начинаешь не с 0-го элемента, а с 1-го, и смотришь, если цена тек. эл-а стала больше, чем твоя, останавливаешь цикл и у обрабатываешь два эл-а (текущий и предыдущий), из которых, уже в зависимости от метода выбираешь нужную тебе цену. Но тогда нужно сделать проверку перед циклом, вдруг твоя цена уже меньше 0-го эл-та, и по выходу из цикла проверить, вдруг у тебя в массиве большей цены так и не нашлось
$NeedCost = 100;
$PrevCost = NULL;
$NextCost = NULL;
if ($items[0]['priceMatched'] != 'false' ) // если первый эл-т подходит
if ($NeedCost <= $items[0]['workingPrice']){
// Все, цикл делать не нужно, т.к. самая первая цена уже больше нужной нам.
return $items[0]['workingPrice'];
}else{
$PrevCost = $items[0]['workingPrice']; // Запоминаем первую цену
}
for ($i=1; $i<count($items); $i++){
if ($item[$i]['priceMatched'] != 'false'){
if ($NeedCost <= $items[$i]['workingPrice']){ // Если дошли до эл-та, у которого цена больше чем нужна, то
$NextCost = $items[$i]['workingPrice']; // запоминаем эту цену
break; // и завершаем массив
}else{ // иначе
$PrevCost = $items[$i]['workingPrice']; //запоминаем эту цена как "предыдущыю"
}
}
}
if ($PrevCost == NULL){ /* это значит, что в массиве либо цен вообще нет, либо самая первая валидная (($item[$i]['priceMatched'] != 'false'))
уже больше чем нужная нам цена, но она стоит не в первом эл-те.*/
if ($NextCost == NULL){ /*это значит, что в массиве всетаки цен вообще нет.*/
echo "В массиве нет цен";
return 0;
}else{/*Первая валидная цена уже больше нужной*/
echo "Нашли - ".$NextCost;
return $NextCost;
}
}else{
if ($NextCost == NULL){ /*Первая валидная цена уже больше нужной*/
echo "Нашли - ".$PrevCost;
return $PrevCost;
}else{/*нашли две цены*/
switch ($method){
case 0: return $PrevCost; break; /*Ближайшее меньшее*/;
case 1: return $NextCost; break; /*Ближайшее большее*/;
default: /*Просто ближайшее*/
if (($NeedCost - $PrevCost) > ($NextCost - $PrevCost)){
return $NextCost;
}else{
return $PrevCost;
}
}
}
}
Спустя 1 месяц, 18 дней, 23 часа, 22 минуты, 11 секунд (12.01.2010 - 07:05) php-master написал(а):
Начинать перебор массива не с нуля действительно толково в этом случае. Вот реально элегантное решение на лицо.