Имя: Пароль:
1C
1С v8
Задача по долгам.Помогите решить
0 KarpovDeniska
 
18.10.11
02:13
Есть таблица:
Орг1 | Орг2 |Долг
A    | B    |300
B    | C    |400
C    | A    | 500

В таблице показан долг организации 1 перед организацией 2, требуется найти наиболее оптимальный путь погашения долга организациями( по другому не знаю как сформулировать)

Из этой таблицы наиболее оптимальным получается :
Организация В должна Организации А 100
И Организация С должна Организации А 100. КАК решить такую задачу запросом?? Помогите кто решал такое
1 pwei
 
18.10.11
05:15
оптимальный путь погашения долга - что значит?
2 Luhtas
 
18.10.11
05:22
(0) Если запросом, то используй функцию:
ВЫБОР
   КОГДА <Выражение> ТОГДА <Выражение>
       ИНАЧЕ <Выражение>
   КОНЕЦ
3 Alexandr Puzakov
 
18.10.11
05:33
Интересно... А организации-то в курсе, что за них программа будет решать, кто, сколько и кому будет платить? :)
4 Начинающий Программер
 
18.10.11
07:00
(3) Может у них холдинг.
5 Alexandr Puzakov
 
18.10.11
07:15
(4) ну и что?
6 KarpovDeniska
 
18.10.11
12:07
Это задача с собеседования, я вот не придумал как её решить, т.к. не сталкивался с такими, вот и интересно увидеть её решение, знаю только что как то можно замутить хитрый алгоритм через нарастающие итоги вроди
7 KarpovDeniska
 
18.10.11
12:12
(1) оптимальный путь: А должна Б 100 , а Б должна С 100, следовательно А может отдать С 100 и всё (ничего не отдавая Б)
8 neckto
 
18.10.11
12:14
Смотри в сторону динамического программирования
9 KarpovDeniska
 
18.10.11
12:16
(8) весь смысл решить её обычным запросом (
10 tdm
 
18.10.11
12:20
(0) загнать в проводки на АП счет - и получить итоги;
кредитовый остаток должен заплатить, дебетовый получить (ну или наоборот - всегда путаю что слева что справа))))
11 KarpovDeniska
 
18.10.11
12:26
(10) мож я не полностью описал начальные данные: вот есть пустая конфа , создаём какой нить регистр долги, в нём измерения Орг1 , орг2, ресурс долг  и всё, больше нет ничего
12 KarpovDeniska
 
18.10.11
12:29
(10) кстати так  вроди не будет видно кто кому должен заплатить: так же можно сделать проще, выбрать должника с минусом , выбрать получателей с плюсом и объединить всё, только опять же не видно кто кому должен
13 KarpovDeniska
 
18.10.11
12:34
что то вроде того:
А - 300
В - 400
С - 500

Объеденить всё

В  300
С  400
А  500

Получим А  200
       В -100
       С -100  чисто логически можно догадаться что В должна А 100 и С должна А 100,
но это простейший пример, а если будет гораздо больше данных, то и не разберёшь кто кому должен
14 Sk0rp
 
18.10.11
12:42
Может как-то так:
Развернуть таблицу в:

A: -300
B: +300
B: -400
C: +400
C: -500
A: +500

Объединить, получается:
А: +200
B: -100
C: -100

Дальше у кого "минус", отдают тем у кого "плюс" (Так примерно долги по FIFO гасятся).
15 Широкий
 
18.10.11
12:50
Если количество организаций ограничено?
16 PR
 
18.10.11
12:52
Определить общие суммы платежей организаций очень просто, сложно определить кому именно должны заплатить организации :))
17 KarpovDeniska
 
18.10.11
12:56
(16) вот и я про это же
18 PR
 
18.10.11
12:57
(17) А ты уже придумал, как определить общие суммы платежей? :))
19 KarpovDeniska
 
18.10.11
12:57
(15) коичество не ограничено
20 KarpovDeniska
 
18.10.11
12:58
(13) и (14) вроди это и есть
22 PR
 
18.10.11
13:01
(20) В (13) и (14) ни о чем :))
23 KarpovDeniska
 
18.10.11
13:02
ну значит я тупой )))
24 Широкий
 
18.10.11
13:05
(19) Если не ограничено, то ИМХО в запросе (1с-ком) это не решаемо
25 PR
 
18.10.11
13:06
(24) Да пока и сам алгоритм-то не ясен, пусть даже без запроса :))
26 KarpovDeniska
 
18.10.11
13:06
(24) а если ограничено???
27 Axel2009
 
18.10.11
13:08
в запросах нет нарастающего итога
28 PR
 
18.10.11
13:08
(27) При чем здесь нарастающий итог?
29 KarpovDeniska
 
18.10.11
13:11
(28) да это я предположил что возможно её как то так решить,т.к. где то видел подобную задачу котрая решается через нарастающие итоги
30 asady
 
18.10.11
13:11
(0) Задача решается рекурсивно.
31 PR
 
18.10.11
13:13
(30) Как? :))
32 Широкий
 
18.10.11
13:16
(26) Я бы начал в эту сторону копать

ВЫБРАТЬ
   "А" КАК Кто,
   "Б" КАК Кому,
   300 КАК Сумма
ПОМЕСТИТЬ ТаблДолгов

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   "Б",
   "С",
   400
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
   ТаблДолгов.Кто,
   ТаблДолгов.Кому,
   ТаблДолгов.Сумма,
   ТаблДолгов1.Кто КАК Кто1,
   ТаблДолгов1.Кому КАК Кому1,
   ТаблДолгов1.Сумма КАК Сумма1,
   ТаблДолгов2.Кто КАК Кто2,
   ТаблДолгов2.Кому КАК Кому2,
   ТаблДолгов2.Сумма КАК Сумма2,
   ЕСТЬNULL(ТаблДолгов2.Кому, ЕСТЬNULL(ТаблДолгов1.Кому, ТаблДолгов.Кому)) КАК ИтогоКому
ИЗ
   ТаблДолгов КАК ТаблДолгов
       ЛЕВОЕ СОЕДИНЕНИЕ ТаблДолгов КАК ТаблДолгов1
           ЛЕВОЕ СОЕДИНЕНИЕ ТаблДолгов КАК ТаблДолгов2
           ПО ТаблДолгов1.Кому = ТаблДолгов2.Кто
       ПО ТаблДолгов.Кому = ТаблДолгов1.Кто
33 PR
 
18.10.11
13:18
Может все-таки стоит начать с общего алгоритма, с идеи так сказать? :))
34 ДемонМаксвелла
 
18.10.11
13:23
(16) какая разница кому ? сумма минусов равна сумме плюсов. каждый должник платит свою задолженность ЛЮБОМУ кредитору.

всё это чистая математика, ни один суд таких расчетов не примет :)
35 PR
 
18.10.11
13:27
(34) Да ты чо, правда что ли?
То есть А должна меньше на 100 рублей неважно кому и получила 100 рублей неважно от кого? :)))
36 ДемонМаксвелла
 
18.10.11
13:28
(35) именно так. и после платежа задолженность обоих изменяется.
37 ДемонМаксвелла
 
18.10.11
13:29
всё равно это применимо только к платежам внутри холдинга.
38 Starhan
 
18.10.11
13:30
По условию задачи организации расчитаются в ноль? или не обязательно?
39 PR
 
18.10.11
13:30
(36) Задолженность - это всегда _кто_ и _кому_.
Разве нет?
Как по-твоему трансформируется таблица из (0)? Последовательный алгоритм можно? :))
40 KarpovDeniska
 
18.10.11
13:32
(38) не обязательно
41 PR
 
18.10.11
13:32
(38) LOL
Если бы в ноль, то просто все платят всем и всё :))
42 ДемонМаксвелла
 
18.10.11
13:33
(39) мне нравится способ из (14)
43 PR
 
18.10.11
13:35
(42) А разве в (14) не ерунда написана? :))
44 PCcomCat
 
18.10.11
13:36
Нахождением кратчайшего пути графа пахнет. ;)
45 ДемонМаксвелла
 
18.10.11
13:36
нет. в любой базе сумма дебета равна сумме кредита. даже если ето торговля и проводок вообще нет.
46 ДемонМаксвелла
 
18.10.11
13:38
(43) разъясни мне, что я ошибаюсь. а то ты только многозначительно улыбаться можешь пока
47 Starhan
 
18.10.11
13:39
(41) лол, не все и всем, а сокращаем и получаем, кто кому остался.
48 Axel2009
 
18.10.11
13:41
(43) в (14) написана не ерунда, а сам факт - организация является дебитором или кредитором. это единственная задача, которую можно решить запросом. а на счет нарастающего итога, если организаций будет 10 и между каждыми из них будет долг, тогда порядок погашения без нарастающего итога/рекурсии врядли обойтись.
49 PR
 
18.10.11
13:42
(46) Да на уровне определения того, кто сколько должен дать и взять без определения кому все просто :))
При взаимозачете после всех манипуляций каждый должен заплатить столько же, сколько заплатят ему.
Таким образом, считаем в разрезе по организациям, кто сколько заплатил и сколько получил.
Каждая организация должна заплатить минимум из этих двух сумм :))

А вот кому, это уже интересно :))
50 PR
 
18.10.11
13:43
(47) Что значит "организации расчитаются в ноль"?
51 PR
 
18.10.11
13:44
(48) В (14) вообще непонятно что написано. Что решается в (14)?
52 ДемонМаксвелла
 
18.10.11
13:44
(49) не вижу отличий от (14)
53 Axel2009
 
18.10.11
13:45
(51) "организация является дебитором или кредитором"
54 PR
 
18.10.11
13:45
(53) Зачем?
55 Axel2009
 
18.10.11
13:45
(53)+ фактически получается после этого в общак кидают все кто кредитор, и из общака забирают все кто кредитор. в итоге в общаке "0" останется
56 Axel2009
 
18.10.11
13:46
(55)+ *в общак кидают все кто дебитор
57 ДемонМаксвелла
 
18.10.11
13:46
(55) и я про то же
58 PR
 
18.10.11
13:46
(52) Где в (14) 300?
Именно эту сумму можно заплатить по кругу и погасить взаимных долгов на эту сумму.
59 PR
 
18.10.11
13:47
(55) Да это круто, но кто кому сколько после этого должен? :))
60 Starhan
 
18.10.11
13:48
(50 как в данном пример) А = - 200 В = 100 С = 100
Когда В и С заплатят А в итоге никто никому не останется должен.

А если А было бы долнжо В - 400.
61 Axel2009
 
18.10.11
13:48
(59) а какая разница кто кому сколько должен? сам факт, ты должен, значит давай денег. так в любых "играх" решается
62 KarpovDeniska
 
18.10.11
13:49
Пример 2:
Орг1| Орг2| Долг
А   | B   | 300
B   | C   | 400
C   | D   | 500
D   | E   | 300
E   | A   | 600

Сворачиваем таблицу методом (14) получаем:  А  300
                                           В -100
                                           С -100
                                           D  200
                                           E -300
По хорошему Е отдаёт А 300, В и С отдают D по 100 ( это будет кратчайший путь) , но
можно и так Е отдаст D 200, потом Е отдаст А 100, а потом B и С отдадут А ещё по сто ( это не оптимально), вот и требуется определить кто и кому должен отдать наиболее оптимально
63 PR
 
18.10.11
13:51
А, пардоньте :))
Задача изощреннее, чем я думал, хотя смысл не меняется :))
Нужно взять все платежи и вычесть из них взаимозачеты :))
Таким образом, задача та же, нужно взаимозачеты разложить по получателям.
Разве нет?
64 KarpovDeniska
 
18.10.11
13:52
(63) ага
65 ДемонМаксвелла
 
18.10.11
13:52
это две задачи в одной
66 PR
 
18.10.11
13:53
(64) Ну тогда значит да, задача та же, как определить суммы взаимозачетов с определением того, кто кому сколько должен заплатить :))
67 Axel2009
 
18.10.11
13:54
(62) давай расскажи критерий "кратчайшего пути".
68 PR
 
18.10.11
13:55
(65) Это три :))
1. Определить суммы платежей каждой компании в рамках взаимозачетов.
2. Разбить полученные в 1 суммы на получателей.
3. Вычесть из начальных платежей платежи, полученные в 2, это и есть необходимые платежи :))
69 Axel2009
 
18.10.11
13:55
(66) а нафига? вот я ща напишу любые суммы хоть по рублю и пусть скажут что я не прав.
70 KarpovDeniska
 
18.10.11
13:55
ну как я себе это представляю можно связать таблицу саму с собой и смотреть если суммы должника хватает для погашения то берём её, если нет прибавляем следующего должника, и так пока всё не закроется, вроди эт и есть нарастающий итог если я не ошибаюсь, хотя возможно и ошибаюсь
71 PR
 
18.10.11
13:55
(67) Минимальное количество платежей, разве нет?
72 PR
 
18.10.11
13:56
(69) Ты о чем?
73 PR
 
18.10.11
13:56
(70) >>следующего должника
Какого именно? :))
74 ДемонМаксвелла
 
18.10.11
13:58
(71) или минимальная сумма? или расстяние между плательщиками?
75 ДемонМаксвелла
 
18.10.11
13:58
хотя протелепатировал ты логично
76 Starhan
 
18.10.11
14:03
разделить на две таблицы должников и получателей, а потом связать по Минмальной разнице между модулями чисел.

хотя тут может быть задвоение строк.если будет две мин разницы от разных должников по одному получателю :(
77 Axel2009
 
18.10.11
14:13
(76) ну вот тут и всплыл нарастающий итог.
78 Sk0rp
 
18.10.11
14:15
(62) Я бы делал так:
1. Свертка (14)
2. Поиск одинаковых по модулю и разных по знаку сумм и закрытие их.
3. Отсортировать что осталось по убыванию модуля.
4. Брать первую отрицательную сумму и гасить положительные как в (70)

Но не берусь доказать, что это всегда будет давать минимальное количество платежей.
79 YurOK_51
 
18.10.11
14:17
Можно упростить и элементы бреда но все же

ВЫБРАТЬ
   ВЫБОР
       КОГДА ВложенныйЗапрос.СуммаДолга < 0
           ТОГДА NULL
       ИНАЧЕ ВложенныйЗапрос.Кому
   КОНЕЦ КАК Кому,
   ВЫБОР
       КОГДА (НЕ ВложенныйЗапрос.СуммаДолга < 0)
           ТОГДА NULL
       ИНАЧЕ ВложенныйЗапрос.Кому
   КОНЕЦ КАК Кто,
   ВЫБОР
       КОГДА (НЕ ВложенныйЗапрос.СуммаДолга < 0)
           ТОГДА ВложенныйЗапрос.СуммаДолга
       ИНАЧЕ -ВложенныйЗапрос.СуммаДолга
   КОНЕЦ КАК Сколько
ИЗ
   (ВЫБРАТЬ
       ВложенныйЗапрос.Кому КАК Кому,
       СУММА(ВложенныйЗапрос.СуммаДолга) КАК СуммаДолга
   ИЗ
       (ВЫБРАТЬ
           ВложенныйЗапрос.Кому КАК Кому,
           ВложенныйЗапрос.СуммаДолга КАК СуммаДолга
       ИЗ
           (ВЫБРАТЬ
               ТаблицаИсходныхДанных.Кто КАК Кому,
               СУММА(-ТаблицаИсходныхДанных.Сумма) КАК СуммаДолга
           ИЗ
               (ВЫБРАТЬ
                   "A" КАК Кто,
                   "B" КАК Кому,
                   300 КАК Сумма
               
               ОБЪЕДИНИТЬ
               
               ВЫБРАТЬ
                   "B",
                   "C",
                   400
               
               ОБЪЕДИНИТЬ
               
               ВЫБРАТЬ
                   "C",
                   "A",
                   500) КАК ТаблицаИсходныхДанных
           
           СГРУППИРОВАТЬ ПО
               ТаблицаИсходныхДанных.Кто
           
           ОБЪЕДИНИТЬ ВСЕ
           
           ВЫБРАТЬ
               ТаблицаИсходныхДанных.Кому,
               СУММА(ТаблицаИсходныхДанных.Сумма)
           ИЗ
               (ВЫБРАТЬ
                   "A" КАК Кто,
                   "B" КАК Кому,
                   300 КАК Сумма
               
               ОБЪЕДИНИТЬ
               
               ВЫБРАТЬ
                   "B",
                   "C",
                   400
               
               ОБЪЕДИНИТЬ
               
               ВЫБРАТЬ
                   "C",
                   "A",
                   500) КАК ТаблицаИсходныхДанных
           
           СГРУППИРОВАТЬ ПО
               ТаблицаИсходныхДанных.Кому) КАК ВложенныйЗапрос) КАК ВложенныйЗапрос
   
   СГРУППИРОВАТЬ ПО
       ВложенныйЗапрос.Кому) КАК ВложенныйЗапрос
80 PVV65
 
18.10.11
14:32
ВЫБРАТЬ
   Т.Орг1,
   Т.Орг2,
   Т.Долг
ПОМЕСТИТЬ Табл
ИЗ
   &ТЗ КАК Т
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
   Т1.Орг1 КАК Плательщик,
   Т1.Орг2 КАК Получатель,
   ВЫБОР КОГДА (Т1.Долг <= Т2.Долг) И (Т1.Долг <= Т3.Долг) Тогда Т1.Долг
   ИНАЧЕ
   ВЫБОР КОГДА (Т2.Долг <= Т3.Долг) И (Т2.Долг <= Т1.Долг) Тогда Т2.Долг
   ИНАЧЕ Т3.Долг Конец КОНЕЦ КАК СуммаВзаиморасчетов
ИЗ
   Табл КАК Т1
Левое Соединение Табл КАК Т2
ПО Т1.Орг2 = Т2.Орг1
Левое Соединение Табл КАК Т3
ПО Т2.Орг2 = Т3.Орг1
ГДЕ (Т1.Орг1 = Т3.Орг2) ИЛИ (Т1.Орг1 = Т2.Орг2 И Т1.Орг2 = Т3.Орг2)


Этот запрос работает для цепочек не более чем из трех организаций (для большего числа - больше соединений и условий).
Умеет отсеивать не замкнутые цепочки. Умеет считать более короткие цепочки.

Проверил в обработке - вроде работает.
81 KarpovDeniska
 
18.10.11
14:35
Спасибо, за 10 данных минут я бы её явно не осилил, так что я спокоен ))
82 Axel2009
 
18.10.11
14:47
(80) упс

ВЫБРАТЬ
   "А" КАК Орг1,
   "Б" КАК Орг2,
   300 КАК Долг
ПОМЕСТИТЬ Табл

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   "Б",
   "В",
   400

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   "В",
   "А",
   500

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   "В",
   "Б",
   100
83 PVV65
 
18.10.11
14:58
(82) И запрос из (80) посчитал правильно.
АБ - 300
БВ - 300
БВ - 100
ВА - 300
ВБ - 100

Это правильно.
84 Широкий
 
18.10.11
15:14
(83) разве?
85 Широкий
 
18.10.11
15:16
АБ - 300
БВ - 300
-----------
АВ - 300
86 PVV65
 
18.10.11
15:21
(85) В (82) написано, что "В" должен "А" - 500.

Ты что то путаешь. Требуется погасить долги (деньгами или документами), а не убрать "посредников".
87 PVV65
 
18.10.11
15:23
+(86) Я понял задачу так. Хотя можно и "посредников" убирать.
88 PR
 
18.10.11
15:28
(86) И что по-твоему означает "оптимальный путь погашения долга организациями"?
89 Axel2009
 
18.10.11
15:28
(83)
какие посредники??
БВ - 100
ВБ - 100
встретились и дали друг дружке по 100 рублей. зато в кафе посидели.
90 Широкий
 
18.10.11
15:29
(87) Тогда из 4 итераций ты сделал 5
91 PVV65
 
18.10.11
15:32
(88)(89)(90) Как должно быть на основании (82)?
92 PVV65
 
18.10.11
15:35
(90) Можно добавить в запросе СГРУППИРОВАТЬ.
93 Широкий
 
18.10.11
15:38
(91) Должна быть одна запись
ВА - 200
94 PR
 
18.10.11
15:38
(91) В должна А 200 :))
95 PVV65
 
18.10.11
15:47
(93)(94) А "Б" "В" ничего не должно. Было должно - 400.
96 PR
 
18.10.11
16:03
(95) Не 400, а 300 с учетом последнего объединения. И что?
97 PVV65
 
18.10.11
16:19
Н совсем понимаю - что означает запись из (93) "В должна А 200 :))" - это остаток всех долгов между организациями или это значит, что "В" должна перечислить "А" 200? А что с остальными?
98 PR
 
18.10.11
16:20
(97) Это означает, что все остальные долги можно закрыть взаимозачетами.
99 PVV65
 
18.10.11
16:24
(98) Понятно. Говорили о разном. Все о остатках взаиморасчетов, а я о суммах зачетов.
100 PVV65
 
18.10.11
16:26
+(99) Т.е. мой запрос решает задаче - какие платежи надо произвести между организациями (или оформить документы), что бы все остались "при своих" (имею ввиду деньгах) - это распространенная задача.
101 PR
 
18.10.11
16:31
(100) Для ограниченного числа организаций не интересно :))
102 PVV65
 
18.10.11
16:38
(101) Цепочки дружественных организаций всегда ограничены.
103 PR
 
18.10.11
16:39
(102) Ну да, например 50 штук.
И какой будет запрос? :))
Глупец, лишенный способности посмеяться над собой вместе с другими, не сможет долго выносить программирование. Фредерик Брукс-младший