@sergeyflancer

Как получить группы чисел из массива PHP сумма которых равна = N?

Нужно получить комбинацию чисел сумма которых равна заданному значению. Пока остановился на таком, но код очень долго работает.
$array = [
    '0' => 2000,
    '1' => 2000,
    '2' => 2000,
    '3' => 2000,
    '4' => 2000,
    '5' => 2000,
    '6' => 2000,
    '7' => 1000,
    '8' => 200,
    '9' => 200,
    '10' => 200,
    '11' => 200,
    '12' => 200,
    '13' => 200,
    '14' => 200,
    '15' => 200,
    '16' => 100,
    '17' => 100,
    '18' => 100,
    '19' => 100,
    '20' => 100,
    '21' => 100,
    '22' => 100,
    '23' => 100,
    '24' => 100,
    '25' => 100,
    '26' => 100,
    '27' => 100,
    '28' => 100,
    '29' => 100,
    '30' => 100,
    '31' => 100,
    '32' => 100,
    '33' => 100,
    '34' => 50,
    '35' => 50,
    '36' => 50,
    '37' => 50,
    '38' => 50,
    '39' => 50,
    '40' => 50,
    '41' => 50,
    '42' => 50,
    '43' => 50,
    '44' => 50,
    '45' => 50,
    '46' => 50,
    '47' => 50,
    '48' => 50,
    '49' => 50,
    '50' => 50,
    '51' => 50
];

function getCombos($array, $cost){

    if(in_array($cost, $array))  return [$cost];

    $array = array_filter($array, function ($item) use($cost){
        return $item <= $cost;
    });
    $array = array_values($array);

    for ($dec = 1; $dec < pow(2, count($array)); $dec++) {
        $curterm = array();
        foreach (str_split(strrev(decbin($dec))) as $i => $bit) {
            if ($bit) {
                $curterm[] = $array[$i];
            }

            if((array_sum($curterm) > $cost)) continue 2;

            if((array_sum($curterm) == $cost)){
                return $curterm;
            }
        }

        if((array_sum($curterm) == $cost)){
            return $curterm;
        }
    }

    return false;
}


print_r(getCombos($array, 250));


Опишу подробнее задачу.
В базе есть сертификаты с определенным номиналом(могут повторяться). Нужно при заказе выдавать сертификаты на сумму заказа(желательно выдавать сертификаты с большим номиналом в первую очередь, например на сумму 550 выдавать 500+50 или 200+200+100+50).
Средствами mysql решить задачу не удалось поэтому решил попробовать на уровне PHP
  • Вопрос задан
  • 143 просмотра
Пригласить эксперта
Ответы на вопрос 1
kawabanga
@kawabanga
Не вижу проблемы.

1) Вы знаете, что сертификаты у вас
50 100 200 300 500 2000 рублей к примеру. Лучше, чтобы было меньше вариаций.

2) Клиенту надо дать купонов на 5000

Делаем выборку по кол-ву купонов (group by coupon_value where coupon active) , получаем массив из 5-15 элементов.
Далее идем от большего значения и набираем максимальными купонами скидку.
получаем, что то типа такого массива [2000=>2, 500=>2]
А дальше делаем запросы на погашение купонов на базу.

Итого запросов 2-~10 на базу очень простых.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы