gifts2017

Задача - как подобрать из бухт кабеля двух длин на складе (бухты не режутся) количество с минимальным отклонением от заказа клиента

Опубликовал Sergey Boltach (ser6702) в раздел Обработки - Универсальные обработки

Много читал обсуждений, но не нашел готового решения. Не претендую на оптимальность. Рабочая версия для УПП
Условие задачи:
Мы продаем витую пару, в бухтах по 30 метров и по 70 метров, бухты не разрезаются, продаются целиком.
Имеем на складе какое-то произвольное количество тех и других бухт.
Что требуется:
Приходит клиент и просит какую-либо длину, произвольную, допустим 150 метров, необходимо написать процедуру, которая одним запросом подберет необходимое количество тех и других бухт как можно ближе к этой длине с учетом товаров на складе.


Начальные условия:
По условиям задачи введены две номенклатуры на один склад поступление
Разработка решения может быть просмотрена в файле запроса.
Выполнялся на консоли запросов  Чистова
Прикладываю файл запроса и обработку для подбора, где запрос формируется динамически.
Выводятся первые 10 записей для подбора

Запрос

 

ВЫБРАТЬ
 0 КАК Цифра
ПОМЕСТИТЬ Цифры
ОБЪЕДИНИТЬ
ВЫБРАТЬ
 1
ОБЪЕДИНИТЬ
ВЫБРАТЬ
 2
ОБЪЕДИНИТЬ
ВЫБРАТЬ
 3
ОБЪЕДИНИТЬ
ВЫБРАТЬ
 4
ОБЪЕДИНИТЬ
ВЫБРАТЬ
 5
ОБЪЕДИНИТЬ
ВЫБРАТЬ
 6
ОБЪЕДИНИТЬ
ВЫБРАТЬ
 7
ОБЪЕДИНИТЬ
ВЫБРАТЬ
 8
ОБЪЕДИНИТЬ
ВЫБРАТЬ
 9
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
 Цифры.Цифра + Цифры1.Цифра * 10 + Цифры2.Цифра * 100 + Цифры3.Цифра * 1000 КАК Поле1
ПОМЕСТИТЬ Тысяча
ИЗ
 Цифры КАК Цифры,
 Цифры КАК Цифры1,
 Цифры КАК Цифры2,
 Цифры КАК Цифры3
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
 ТоварыНаСкладахОстатки.Номенклатура,
 ТоварыНаСкладахОстатки.КоличествоОстаток
ПОМЕСТИТЬ Бобины30
ИЗ
 РегистрНакопления.ТоварыНаСкладах.Остатки(
   &Дата,
   Склад = &Склад
    И Номенклатура = &Бобины30) КАК ТоварыНаСкладахОстатки
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
 ТоварыНаСкладахОстатки.Номенклатура,
 ТоварыНаСкладахОстатки.КоличествоОстаток
ПОМЕСТИТЬ Бобины70
ИЗ
 РегистрНакопления.ТоварыНаСкладах.Остатки(
   &Дата,
   Склад = &Склад
    И Номенклатура = &Бобины70) КАК ТоварыНаСкладахОстатки
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ РАЗЛИЧНЫЕ ПЕРВЫЕ 70
 30 * ВЫБОР
  КОГДА Тысяча.Поле1 <= 70
   ТОГДА Тысяча.Поле1
  ИНАЧЕ 0
 КОНЕЦ КАК СуммыПо30,
 ВЫБОР
  КОГДА Тысяча.Поле1 <= 70
   ТОГДА Тысяча.Поле1
  ИНАЧЕ 0
 КОНЕЦ КАК КоличествоБобинПо30м,
 Бобины30.Номенклатура
ПОМЕСТИТЬ БобиныПо30
ИЗ
 Тысяча КАК Тысяча,
 Бобины30 КАК Бобины30
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ РАЗЛИЧНЫЕ ПЕРВЫЕ 30
 70 * ВЫБОР
  КОГДА Тысяча.Поле1 <= 30
   ТОГДА Тысяча.Поле1
  ИНАЧЕ 0
 КОНЕЦ КАК СуммыПо70,
 ВЫБОР
  КОГДА Тысяча.Поле1 <= 30
   ТОГДА Тысяча.Поле1
  ИНАЧЕ 0
 КОНЕЦ КАК КоличествоБобинПо70м,
 Бобины70.Номенклатура
ПОМЕСТИТЬ БобиныПо70
ИЗ
 Тысяча КАК Тысяча,
 Бобины70 КАК Бобины70
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ РАЗЛИЧНЫЕ
 БобиныПо30.СуммыПо30 + БобиныПо70.СуммыПо70 КАК Сумма,
 БобиныПо30.Номенклатура КАК БобиныПо30Метров,
 БобиныПо30.КоличествоБобинПо30м КАК КоличествоБобинПо30м,
 БобиныПо70.Номенклатура КАК БобиныПо70Метров,
 БобиныПо70.КоличествоБобинПо70м КАК КоличествоБобинПо70м
ПОМЕСТИТЬ ВыборкаВсехВариантов
ИЗ
 БобиныПо30 КАК БобиныПо30,
 БобиныПо70 КАК БобиныПо70
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ ПЕРВЫЕ 10
 МИНИМУМ(ВыборкаВсехВариантов.Сумма - &ДлинаЗаказчика) КАК МинимальноеОтклонение,
 ВыборкаВсехВариантов.КоличествоБобинПо30м,
 ВыборкаВсехВариантов.КоличествоБобинПо70м
ИЗ
 ВыборкаВсехВариантов КАК ВыборкаВсехВариантов
ГДЕ
 ВыборкаВсехВариантов.Сумма - &ДлинаЗаказчика >= 0
СГРУППИРОВАТЬ ПО
 ВыборкаВсехВариантов.КоличествоБобинПо30м,
 ВыборкаВсехВариантов.КоличествоБобинПо70м
УПОРЯДОЧИТЬ ПО
 МинимальноеОтклонение

Скачать файлы

Наименование Файл Версия Размер Кол. Скачив.
Обработка подбора
.epf 9,03Kb
25.08.15
0
.epf 1 9,03Kb 0 Скачать
запрос
.sel 14,15Kb
24.08.15
0
.sel 1 14,15Kb 0 Скачать

См. также

PowerTools от 1 000
Подписаться Добавить вознаграждение

Комментарии

1. Александр Хомяк (logarifm) 23.08.15 16:27
С русским очень плохо, боюсь скачивать даже сей шедевр. Не вобиду но я не понимаю зачем вообще такое выкладывать, кому оно вообще надо? У меня есть масса одноразовых или специфичиских работ но я же ими не засоряю ис...
2. борян петров (TODD22) 23.08.15 18:42
Не очень понятно требование к задаче решить это одним запросом. А несколькими запросами и объектной моделью уже не модно? Или в чём принципиальность?
3. Артано Майаров (Артано) 24.08.15 07:15
(2) TODD22, не задавай вопросы, быстрее скачивай все файлы =)
4. борян петров (TODD22) 24.08.15 07:27
(3) Артано, Ну тогда уж лучше "Нет времени объяснять, качай все файлы" :)
5. mpudy mpudy (mpudy) 24.08.15 08:16
Консоль в которой проверяется запрос - лол.
6. Sergey Boltach (ser6702) 24.08.15 09:51
Коллеги, задачка только для того чтобы размять мозги. Задавалась на собеседовании. На мисте обсуждалось как ее решить. Было сказано, что решение выложено на инфостарте. Но как такого решения не было. Дополнил пробел.
8. Sergey Boltach (ser6702) 24.08.15 10:54
может кому то поможет пройти собеседование
9. Sergey Boltach (ser6702) 24.08.15 10:57
И в данной ветке вы только разминали мозги
а здесь предложно конкретное решение. Рабочее. Быстрое. А мозги размять размяли - но результат как обычно российский))) языками почесать
10. Sergey Boltach (ser6702) 24.08.15 10:59
7 - и решены ваши сомнения в том, что задачка решается одним запросом
11. борян петров (TODD22) 24.08.15 11:29
(8) ser6702,
может кому то поможет пройти собеседование

За это спасибо. Но там где дают такие задачи делать скорее всего нечего.
12. Сергей (ildarovich) 24.08.15 12:35
Не хватает ссылки на исходное обсуждение:
Задачка про оптимальный запрос.

В комментарии /17/ того обсуждения я приводил свое решение. Оно довольно простое. Повторю его здесь:

ВЫБРАТЬ
    0 КАК Х
ПОМЕСТИТЬ Число0_1

ОБЪЕДИНИТЬ

ВЫБРАТЬ
    1
;

////////////////////////////////////////////////////////////­­////////////////////
ВЫБРАТЬ
    Инь.Х + 2 * Янь.Х КАК Х
ПОМЕСТИТЬ Число0_3
ИЗ
    Число0_1 КАК Инь,
    Число0_1 КАК Янь
;

////////////////////////////////////////////////////////////­­////////////////////
ВЫБРАТЬ
    Инь.Х + 4 * Янь.Х КАК Х
ПОМЕСТИТЬ Число0_15
ИЗ
    Число0_3 КАК Инь,
    Число0_3 КАК Янь
;

////////////////////////////////////////////////////////////­­////////////////////
ВЫБРАТЬ
    Инь.Х + 16 * Янь.Х КАК Х
ПОМЕСТИТЬ Число0_255
ИЗ
    Число0_15 КАК Инь,
    Число0_15 КАК Янь
;

////////////////////////////////////////////////////////////­­////////////////////
ВЫБРАТЬ
    Инь.Х + 256 * Янь.Х КАК Х
ПОМЕСТИТЬ Число0_65535
ИЗ
    Число0_255 КАК Инь,
    Число0_255 КАК Янь
;

////////////////////////////////////////////////////////////­­////////////////////
ВЫБРАТЬ
    Число.Х КАК По70,
    ВЫБОР
        КОГДА &НужноМетров <= Число.Х * 70
            ТОГДА 0
        ИНАЧЕ ВЫРАЗИТЬ((&НужноМетров - Число.Х * 70) / 30 + 0.499999 КАК ЧИСЛО(10, 0))
    КОНЕЦ КАК По30,
    Число.Х * 70 + ВЫБОР
        КОГДА &НужноМетров <= Число.Х * 70
            ТОГДА 0
        ИНАЧЕ ВЫРАЗИТЬ((&НужноМетров - Число.Х * 70) / 30 + 0.499999 КАК ЧИСЛО(10, 0))
    КОНЕЦ * 30 - &НужноМетров КАК Остаток
ПОМЕСТИТЬ Варианты
ИЗ
    Число0_65535 КАК Число
ГДЕ
    Число.Х <= &Остаток70
    И ВЫРАЗИТЬ((&НужноМетров - Число.Х * 70) / 30 + 0.499999 КАК ЧИСЛО(10, 0))<= &Остаток30
;

////////////////////////////////////////////////////////////­­////////////////////
ВЫБРАТЬ
    Варианты.По70,
    Варианты.По30,
    Варианты.Остаток
ИЗ
    Варианты КАК Варианты
ГДЕ
    Варианты.Остаток В
            (ВЫБРАТЬ
                МИНИМУМ(Варианты.Остаток)
            ИЗ
                Варианты)
...Показать Скрыть


В статье другое решение?
13. Евгений Фербер (omut) 24.08.15 13:02
(12) ildarovich, все верно. Строим заведомо достаточное поле сочетаний и просто выбираем наиболее подходящий под условия задачи. Но в целом и правда не ясно, зачем делать все одним запросом, накладывая - пусть и теоретическое - ограничение на максимально возможную сумму комбинации. По идее, можно ведь и текст запроса генерировать в обработке динамически (например, ограничив уже практической необходимостью максимальные значения по остаткам на складе и соотношению длин бухт и общей необходимой длины. Т.е. совсем просто соединив две таблицы, в одной из которых последовательность длин по первой номенклатуре, во второй - по второй и высчитав отклонение результата по модулю. Формально задача решена (запрос один), но сам запрос будет разный в зависимости от исходных данных. Зато на все случаи жизни.
Поэтому, можно согласиться с (11)
14. Сергей (ildarovich) 24.08.15 14:01
(13) omut, я против "тупого" лишнего перебора. Когда типоразмеров бухт ДВА, то выбрав число бухт-семидесяток, мы однозначно получаем нужное число бухт-тридцаток. То есть задача очень простая: ОДНОМЕРНАЯ.
В моем запросе "цикл" поиска делается по бухтам бОльшей размерности, чтобы сократить число "итераций". То есть запрос максимально быстрый. Такой же подход нужно применять при решении задачи в коде.

Если Вы под универсальным подходом понимаете динамическое построение текста запроса для бухт трех, четырех и так далее типоразмеров, то все равно лучше сокращать перебор, исключая лишний перебор числа бухт последнего типоразмера.

Кстати, запрос не обязательно строить динамически:
в статье Запрос-комбинатор показано, как "скомбинировать", например, длины бухт для нахождения решения перебором.
15. Sergey Boltach (ser6702) 24.08.15 14:57
(12) решение похожее. Но не такое ).
16. Sergey Boltach (ser6702) 24.08.15 14:59
(11) значит в R-Stily делать Вам нечего
17. Sergey Boltach (ser6702) 24.08.15 15:00
(13) да - именно по такому пути решена задачка
18. Sergey Boltach (ser6702) 24.08.15 15:02
(14) Дело в том, что можно предложить клиенту варианты... сколько бухт какой размерности он может взять, чтоб набрать нужную длину. может он предпочтет взять примерно равное количество разных бухт. Или одну бухту одной длинны, а остальные все другие
19. Сергей (ildarovich) 24.08.15 15:33
(18) ser6702, любую задачу теоретически можно решить перебором. Можно сложить радиодетали в ящик и трясти его пока не получится телевизор. Вопрос в том, сколько это займет времени.
Знание закономерностей сокращает перебор. Иногда, как в данной задаче, весьма существенно. Игнорирование закономерностей (тупой подбор, а не вычисление количества бухт второй размерности) - это бессмысленное прожигание времени. Даже если это работает на текущих данных, может не работать (слишком долго работать) в других случаях.
Для примера задайте требуемую длину 4587450 метров. - Сколько ваша обработка потратит времени на нахождение ответа (пусть текущие остатки это допускают)? - А мой запрос? - Сравните и сделайте выводы!
Было бы легче общаться, если бы ваш запрос (или результат построения запроса) был приведен прямо в статье. А так остается только предположения строить о том, что на самом деле вы имеете ввиду.
20. борян петров (TODD22) 24.08.15 15:56
(16) ser6702, И что такое R-style? Я что то не в курсе.
Гугл говорит что есть такой "системный интегратор", но я у них вакансии 1сника не увидел.
ojiojiowka; +1 Ответить 1
21. Евгений Фербер (omut) 24.08.15 15:59
(19) ildarovich, я, видимо, не совсем ясно выразился в части "перебора". Перебор подразумевает создание таблицы не так, как в вашем случае (создание последовательности чисел от 1 до n), а через создание текста запроса, который выдаст эту последовательность от 1 до заданного n. Не велика разница за исключением того, что вы получаете заранее известное максимальное значение числа, полученную таблицу потом ограничиваете через условие (но таблица все равно изначально создана полная). В предложенном мной варианте таблица ограничена изначально нужным числом. Вы тоже можете добавить такое ограничение на этапе формирования Число0_65535 через сравнение Х с максимально необходимым. Это будет некоторой оптимизацией.
22. Sergey Boltach (ser6702) 25.08.15 08:30
23. Sergey Boltach (ser6702) 25.08.15 09:19
(19) - да, на этих данных работать будет долго
Но с практической точки зрения сколько в реальности может быть бухт на складе? Ну пусть по несколько тысяч...
какая тогда разница по скорости выполнения между запросам?
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа