powered by simpleCommunicator - 2.0.30     © 2024 Programmizd 02
Map
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Пятничная задача: работнички.
25 сообщений из 61, страница 1 из 3
Пятничная задача: работнички.
    #40122078
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всем привет! Предлагаю отвлечься от годовой отчетности и финальных релизов и немного размять мозги.

Задача

Работники обрабатывают коробки на складе, при это работники имеют следующие характеристики
speed - время обработки одной коробки в минутах
capacity - число коробок, которые работник в состоянии обработать без перерыва
delay - длительность перерыва в минутах

За какое минимальное время работники смогут обработать N коробок (задаётся биндом или константой, не суть)?

Пример данных

Код: plsql
1.
2.
3.
4.
create table w(speed, capacity, delay) as 
(select 1, 2, 3 from dual
union all select 3, 10, 3 from dual
union all select 2, 4, 3 from dual);


Если число коробок 10, то работники их смогут обработать за 8 минут.
Двое обработали по 4-ре коробки и один две (по три минуты каждую).

Как обычно, объявляется конкурс на SQL решение. Если кто захочет решить на PL/SQL - это тоже не возбраняется, но лучше засунуть под спойлер.

Тесты
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
SQL> var n number
SQL>
SQL> create table w(speed, capacity, delay) as
  2  (select 1, 2, 3 from dual
  3  union all select 3, 10, 3 from dual
  4  union all select 2, 4, 3 from dual);

Table created.

SQL>
SQL> exec :n := 10;

PL/SQL procedure successfully completed.

SQL>
...
 12  /

    RESULT
----------
         8

SQL>
SQL> insert into w select 3.5, 100, 100 from dual;

1 row created.

SQL>
SQL> exec :n := 20;

PL/SQL procedure successfully completed.

SQL>
...
 12  /

    RESULT
----------
        15


PS. Не дождался пятницы. Праздники и всё такое.
...
Рейтинг: 0 / 0
Пятничная задача: работнички.
    #40122088
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dbms_photoshop,

Добавте id работника, будет интереснее (легче) анализировать

1-й 4 коробки
2-й 2 коробки
3-й 4 коробки


зы
авторвремя обработки одной коробки в минутах

10 коробок, на таких данных время не может быть меньше 10

ззы
к слову, время может быть дробным (напр 1.5 полтора минуты)

.....
stax
...
Рейтинг: 0 / 0
Пятничная задача: работнички.
    #40122098
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax
Добавте id работника, будет интереснее (легче) анализировать
Да, с айдишником на них было бы лушче ссылаться, но я надеюсь всё достаточно тривиально и глубокого анализа не потребуется.
Данных предоставлено ровно столько сколько требуется для нахождения решения.
Stax
10 коробок, на таких данных время не может быть меньше 10
Параллельная обработка творит чудеса.
Stax
к слову, время может быть дробным (напр 1.5 полтора минуты)
Да, это так.
...
Рейтинг: 0 / 0
Пятничная задача: работнички.
    #40122107
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dbms_photoshop

всё достаточно тривиально и глубокого анализа не потребуется.

с тривиальностью у меня как-раз проблема

подожду решений (без модельки), и гляну где я ступил

.....
stax
...
Рейтинг: 0 / 0
Пятничная задача: работнички.
    #40122164
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dbms_photoshop
...всё достаточно тривиально и глубокого анализа не потребуется.
...

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

Пока я не вполне ясно понимаю, как это красиво сделать на sql (вероятно, рекурсивный запрос должен в итоге как надо подкрутиться)
а для pl/sql это правда не сильно сложная задача.
...
Рейтинг: 0 / 0
Пятничная задача: работнички.
    #40122190
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
booby,

dbms_photoshop решил без Ид (11строк кода)

как-то он хитро раздает коробки

зы
правда почему-то создал таблицу, мож ровид заюзал
чувствую что неправильно мыслю, зациклился я на ид работника

старею, утро-вечера мудренее

.....
stax
...
Рейтинг: 0 / 0
Пятничная задача: работнички.
    #40122197
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax
booby,

dbms_photoshop решил без Ид (11строк кода)

как-то он хитро раздает коробки

зы
правда почему-то создал таблицу, мож ровид заюзал
чувствую что неправильно мыслю, зациклился я на ид работника

старею, утро-вечера мудренее

.....
stax
Никаких завязок на rowid у меня в решении нет.
Если не удаётся решить без ID работника - не понимаю в чём проблема проставить его с помощью rownum.

Написанное ниже вполне имеет смысл и не завязано на ID работника (это, впрочем, не значит что я решал так :)).
booby
надо первым выбирать для следующей работы того, у кого время обработки наименьшее

Если SQL вызывает трудности можно в конце концов написать на PL/SQL и прикинуть переписываемо ли оно на pure SQL.

На мой взгляд на SQL решается вполне изящно и гармонично.
...
Рейтинг: 0 / 0
Пятничная задача: работнички.
    #40122199
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax,

пронумеровать работников по их скорости в любом случае можно.
Это, так или иначе, почти наверно пригодится.
А 11 строк кода надо сначала посмотреть....
Мне такую задачу проще сначала записать в pl/sql решить.
И там (в pl/sql) ее нельзя решить правильно, если порядок по скорости работы не будет явно поддерживаться.

Я так как-то думаю..
попробую записать на pl/sql чуть позже.
Про sql потом яснее станет.

PS
в этой задаче два порядка - по времени следующей доступности работника и по быстродействию самих работников.
решение должно правильно их комбинировать.
...
Рейтинг: 0 / 0
Пятничная задача: работнички.
    #40122204
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dbms_photoshop
.
На мой взгляд на SQL решается вполне изящно и гармонично.


Скажем так, model я вряд ли был бы готов признать за гармонию, а в альтернативах надо аккуратно разбираться с порядком следования, что для sql исторически несколько чужеродно.

возможно и гармонично, я не отрицаю пока, но хочу сначала увидеть, как это должно выглядеть на pl/sql
позже положу
...
Рейтинг: 0 / 0
Пятничная задача: работнички.
    #40122206
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dbms_photoshop

Никаких завязок на rowid у меня в решении нет.


верю, просто я не в ту сторону думаю

залезло в голову, кто сколько коробок обработал, и мешает


ps
алгоритм придумал (без ид), завтра реализую
.....
stax
...
Рейтинг: 0 / 0
Пятничная задача: работнички.
    #40122254
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax
...
залезло в голову, кто сколько коробок обработал, и мешает
....
stax

это тоже не трудно получить, но в исходной постановке не требуется.
...
Рейтинг: 0 / 0
Пятничная задача: работнички.
    #40122264
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dbms_photoshop,

не причисывал

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
with w(id,speed, capacity, delay) as (
              select 1,1, 2, 3 from dual
union all select 2,3, 10, 3 from dual
union all select 3,2, 4, 3 from dual
union all select 4,3.5, 100, 100 from dual
)
, r (id,speed, capacity, delay,k2,l,s) as (
 select  w.*
  ,lag(0,1,1) over (order by speed)
  ,1
  ,speed
 from w
union all
 select  id,speed, capacity, delay
  ,k2+lag(0,1,1) over (order by speed*(k2+1)+floor(k2/capacity)*delay,id)
  ,l+1
  ,speed*(k2+1)+floor(k2/capacity)*delay
 from r where l<20
)
select min(s) m from r where l=20
--order by l,id
/
SQL> /

         M
----------
        15

ed
....
SQL> /

         M
----------
         8





.....
stax
...
Рейтинг: 0 / 0
Пятничная задача: работнички.
    #40122274
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
на pl/sql получилось так.
Строк вместе 271 на спецификацию и тело пакет, 237 на тело.
8 на первоначальных исходных данных получено
ну, и я, более-менее, без долгого тестирования верю, в то, что здесь написано.
Осталось быстро поверить в sql.

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
create or replace package sqlru_workers authid definer
is
 
-- booby 22.12.2021

 Type T_Worker_Spc Is Record( speed number -- время обработки одной коробки в минутах
                            , capacity number -- число коробок обрабатываемых без перерыва
                            , delay number -- перерыв в минутах после обработки capacity коробок
                            );

 --------------------                               
 TYPE T_WRK_CURSOR IS REF CURSOR RETURN T_Worker_Spc;
 -----
/*
  вернет отрицательный результат, если для заказанного положительного объема pN 
  не найдется работников в курсоре pcrs вообще
  пример вызова:
select sqlru_workers.get_min_wrk_time(pcrs => CURSOR(
                                                      select speed, capacity, delay 
                                                      From 
                                                      (select 1 as speed, 2 as capacity, 3 as delay from dual
                                                      union all select 3, 10, 3 from dual
                                                      union all select 2, 4, 3 from dual) w
                                                       )
                         , pN => 10        -- число коробок
                          )
from dual 
*/
 function get_min_wrk_time(pcrs in T_WRK_CURSOR -- курсор с работничками
                         , pN in Number        -- число коробок
                          ) Return Number; 

end sqlru_workers;
/
create or replace package body sqlru_workers is

 TYPE T_WORKERS_PLDICT is table of T_Worker_Spc index by pls_integer; 

 Type T_Worker_State Is Record( inum pls_integer -- номер работника в списке работников
                              , current_capacity Number -- текущее число обработанных коробок работником
                              , next_avalible Number -- следующее время доступности работника
                              );
 TYPE T_wrk_states is table of T_Worker_State Index by pls_integer;
 
 -- вернет отрицательный результат, если для заказанного положительного объема pN 
 -- не найдется работников в курсоре pcrs вообще
 function get_min_wrk_time(pcrs in T_WRK_CURSOR -- курсор с работничками
                         , pN in Number        -- число коробок
                          ) Return Number
 Is
   nstop_time Number := 0.0;
   N Number := Coalesce(pN, 0.0);
   a_workers T_WORKERS_PLDICT; -- работнички
   a_wrkstate T_wrk_states;     -- их рабочее состояние
   --
   ncur_time Number := 0.0; -- текущее время
   r_worker T_Worker_State;

  ------------------------------------------------------------------------------
  -- процедуры работы с очередью занятых работников
  -------------------------------------------
  Function Is_Empty(pa_wrk_states in T_wrk_states) return Boolean
    is
  Begin
    Return pa_wrk_states.COUNT = 0;
  End;
  -- получение индекса родителя
  function get_parent_idx(p_idx_in in Pls_integer) return Pls_integer Deterministic
    is
  begin
    return Floor(0.5*(p_idx_in));
  end;  
  -- копирование элемента 
  Procedure Copy_ItemTo(pa_array in out nocopy T_wrk_states
                      , pi_from in Pls_integer -- индекс с которого копируется элемент
                      , pi_to in Pls_Integer   -- индекс в который копируется элемент
                      )
  is
  Begin
    pa_array(pi_to) := pa_array(pi_from);
  End;   
  -- сравнение элементов по значению
  Function Less(pr_parent in T_Worker_State
              , pr_child in T_Worker_State
               ) Return Boolean
  Is
  Begin          
    Return Case 
             When  pr_child.next_avalible < pr_parent.next_avalible 
               Then True
             When pr_child.next_avalible = pr_parent.next_avalible       
               Then (a_workers(pr_child.inum).speed < a_workers(pr_parent.inum).speed)
           Else False
           End;
  End;  
  -- всплытие с указанной позиции
  Procedure Swim( pa_array in out nocopy T_wrk_states
                , pi_from in Pls_integer
                )
  is
    i_flow Pls_integer;
    i_parent Pls_integer;
    r_temp T_Worker_State;
  Begin
    i_flow := pi_from;
    i_parent :=  get_parent_idx(i_flow);
    r_temp := pa_array(pi_from);    
    
    While i_flow > 1
        And Less( pr_parent => pa_array(i_parent)
               ,  pr_child => r_temp 
                )   
    Loop
      pa_array(i_flow) := pa_array(i_parent); 
      i_flow := i_parent;
      i_parent := get_parent_idx(i_flow);
    End Loop;
    
    If i_flow != pi_from
      Then
      pa_array(i_flow) := r_temp; 
    End if;      
    
  End;    
  -- погружение с указанной позиции  
  Procedure Sink(pa_array in out nocopy T_wrk_states
                , pi_from in Pls_integer
                 )
  Is
    i_flow Pls_integer;
    i_child Pls_integer;
    i_lastPos Pls_integer;

    r_temp T_Worker_State;
  Begin
    i_lastPos := pa_array.COUNT;
    i_flow := pi_from;   
    If i_flow <= i_lastPos
      Then
      r_temp := pa_array(pi_from);
      While (i_flow + i_flow ) <= i_lastPos
      Loop
        i_child := (i_flow + i_flow); 

        If i_child < i_lastPos
            And Less( pr_parent => pa_array(i_child)
                    , pr_child =>  pa_array(i_child+1)
                    )
          Then
            i_Child := i_child + 1;
        End If;
        
        Exit When Not Less( pr_parent => r_temp
                         ,  pr_child => pa_array(i_Child)
                          ); 
                          
        Copy_ItemTo(pa_array => pa_array, pi_from => i_child, pi_to => i_flow);
        i_flow := i_child;

      End Loop;

      If i_flow != pi_from
        Then
        pa_array(i_flow) := r_temp; 
      End If;   
    End If; 
    --
  End;
  --------------------------------------------------  
  -- удаление и возврат максимального элемента
  Procedure delMax(pa_array in out nocopy T_wrk_states
                 , pr_Key_out OUT NOCOPY T_Worker_State
                   )
  Is
    i_rootPos Pls_integer := 1; --- индекс корня
    ilastPos Pls_integer; -- индекс последнего элемента
  Begin

    ilastPos := pa_array.COUNT;
    -- возвращаемое (снимаемое) значение
    pr_Key_out :=  pa_array(i_rootPos);

    Copy_ItemTo(pa_array => pa_array, pi_from => ilastPos, pi_to => i_rootPos); 
    pa_array.Delete(ilastPos);
    Sink(pa_array, i_rootPos); 
    Return;
  End;  

  -- постановка работы в очередь ожидания завершения
  Procedure Insert_Q(pa_array in out nocopy  T_wrk_states, pr_Key in T_Worker_State)
  Is
    ilastPos Pls_integer;
  Begin
    ilastpos := Coalesce(pa_array.Last + 1, 1 );
    pa_array(ilastpos) := pr_Key;
    Swim( pa_array => pa_array, pi_from => ilastpos);
    Return;
  End;

   -- получение следующего освободившегося работника
  Function get_Next_Event( pa_evt In OUT Nocopy T_wrk_states ) return T_Worker_State
    Is
    r_ret T_Worker_State; 
  Begin    
    If Not Is_Empty(pa_evt) Then
       delMax(pa_evt, r_ret);
    End If;
    Return r_ret;
  End;
 ---------------------------------------------------
   -- подготовка состояния работников 
   -- с одновременной загрузкой их начальной работой
   procedure prepare_workers
   Is
    r_worker T_Worker_State;
   Begin  
     nstop_time := -1.0;
     fetch pcrs Bulk Collect Into a_workers;
     If a_workers.count > 0 Then
       nstop_time := 0.0;       
       For i in 1..a_workers.count
       Loop
         r_worker.inum := i;
         r_worker.current_capacity := 1;
         r_worker.next_avalible := a_workers(i).speed;
         
         Insert_Q(pa_array => a_wrkstate, pr_Key => r_worker);       
         -- nstop_time := Greatest(nstop_time, r_worker.next_avalible);         
         N := N-1;         
         Exit When N <= 0;
       End Loop;  
     End If;       
   End;  
  
 Begin -- основное тело 
   If N > 0.0 Then
     prepare_workers;
     If a_workers.count > 0
       Then        
        Loop
          r_worker := get_Next_Event(a_wrkstate);
          ncur_time := r_worker.next_avalible;
          
          If r_worker.current_capacity < a_workers(r_worker.inum).capacity
            Then
              r_worker.current_capacity := r_worker.current_capacity + 1;
              r_worker.next_avalible := r_worker.next_avalible + a_workers(r_worker.inum).speed;
              N := N-1;
          Else
             r_worker.current_capacity := 0; 
             r_worker.next_avalible := r_worker.next_avalible + a_workers(r_worker.inum).delay;              
          End If;     
          -- поставить обратно в очередь ожидания выполнения работ
          Insert_Q(pa_array => a_wrkstate, pr_key => r_worker );
          Exit When N <=0;
        End Loop;
        -- цикл съема результата 
        While Not Is_Empty(a_wrkstate)
        Loop
          r_worker := get_Next_Event(a_wrkstate);
          If r_worker.current_capacity > 0
            Then
            nstop_time := Greatest(nstop_time, r_worker.next_avalible);         
          End If;
        End Loop;    
     End If;    
   End If;
   Return nstop_time;
 End;  

end sqlru_workers;
/

...
Рейтинг: 0 / 0
Пятничная задача: работнички.
    #40122275
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
booby,

текущее время в итоге не пригодилось, но забылось удалиться.
Так что, не без дефектов, но он и набросок.
...
Рейтинг: 0 / 0
Пятничная задача: работнички.
    #40122299
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax
не причисывал
Прикольно! Фактически прямолинейная реализация жадного алгоритма по раздаче коробок.
У меня несколько иной подход. Подождём может еще будут предложены решения. Потом чуть детальнее прокоментирую.
booby
ну, и я, более-менее, без долгого тестирования верю, в то, что здесь написано
Вера в себя это замечательно.
Код экстремально избычтоный и я не уверен что легче - переписать его сократив раз в десять или искать ошибку в том, что есть,
но на данных ниже для 31 коробки выдаёт 175 вместо 152 (у меня и Станислава результат одинаков).
Код: plsql
1.
2.
3.
4.
5.
6.
with w(id, speed, capacity, delay) as (
select 1 id, 10 speed, 12 capacity, 2 delay from dual
union all select 2, 30, 10, 5 from dual
union all select 3, 20, 4, 5 from dual
union all select 4, 35, 100, 100 from dual
)
...
Рейтинг: 0 / 0
Пятничная задача: работнички.
    #40122307
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ок, я посмотрю позже, где ошибка.
Но 152 тоже не похоже на правильный ответ.
его как-то надо лучше обосновать, чем указанием на одинаковость, возможно одинаково неправильных решений.


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

исполнители
id speed capacity delay1 10 12 22 30 12 53 20 4 54 35 100 100


трейс работы исполнителей во времени
время Коробка работник всего обработано готовность коробки прим0 1 1 1 10 0 2 3 1 20 0 3 2 1 30 0 4 4 1 35 10 5 1 2 20 20 6 1 3 30 20 7 3 2 40 30 8 1 4 40 30 9 2 2 60 35 10 4 2 70 40 11 1 5 50 40 12 3 3 60 50 13 1 6 60 60 14 1 7 70 60 15 3 4 80 next stop60 16 2 3 90 70 17 1 8 80 70 18 4 3 105 80 19 1 9 90 80 20 3 4 85 отдых85 21 3 5 105 90 22 1 10 100 90 23 2 4 120 100 24 1 11 110 105 25 3 6 125 105 26 4 4 140 110 27 1 12 120 next stop120 28 1 12 122 отдых122 29 1 13 132 125 30 3 7 145 132 31 1 14 142

руками вот так 145 получается
я посмотрю, где у меня ошибка.
...
Рейтинг: 0 / 0
Пятничная задача: работнички.
    #40122333
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
booby,

проверил, правильный ответ именно 175
при One off получится 150
чтобы получить 152 надо две ошибки совершить 1) one off 2) присобачить где-то к нему время отдыха 1го работника,
или ошибиться каким-то иным способом.

в предыдущих ручных выкладках я сам ошибся на строках отдыха, засчитав им живые коробки.
правильный финиш, начиная с 20й коробки, такой:
время коробка работник обработал всего готовность прим80 19 1 9 90 последняя правильная в пред. посте80 0 3 4 85 отдых85 20 3 5 105 90 21 1 10 100 90 22 2 4 120 100 23 1 11 110 105 24 3 6 125 105 25 4 4 140 110 26 1 12 120 next stop120 0 1 12 122 отдых120 27 2 5 150 122 28 1 13 132 125 29 3 7 145 132 30 1 14 142 140 31 4 5 175

PS
надеюсь, у нас не найдется повода обсуждать экстремальную избыточность кода,
чтобы не превращать топик совсем уж в посмешище.
...
Рейтинг: 0 / 0
Пятничная задача: работнички.
    #40122336
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
booby,

впрочем, 152 действительно получается, если на последней коробке сменить стратегию, и назначать следующую коробку не первому
освободившемуся, а перейти к ожиданию освобождения работника с минимальным суммарным временем
следующая готовность + обработка.
...
Рейтинг: 0 / 0
Пятничная задача: работнички.
    #40122354
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
booby,

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

.....
stax
...
Рейтинг: 0 / 0
Пятничная задача: работнички.
    #40122392
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dbms_photoshop

У меня несколько иной подход.

я сначала тоже пошел по другому пути(возможно неправильному), потом бросил

1) считаем минимальное время когда работает один человек, получаем стартовое
2) Параллельная обработка творит чудеса (c dbms_photoshop ).
далее время уменьшием (пополам, золотое сечение, ...)
3) считаем скоко за ето время коробок откроют при максимальном паралелизме (работают все)
4) далее если полученное к-во коробок меньше то - увеличиваем время, если больше уменьшаем, если равно то п6
5) п3
6) накручиваем точность
.....
stax
...
Рейтинг: 0 / 0
Пятничная задача: работнички.
    #40122511
Никанор Кузьмич
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я пока не вникал в предложенные выше решения. Писать код пока не пробовал, только думал над решением. Надумал вот что:
Подход 1: раскидывание коробок по сотрудникам пачками. В этом случае у каждого работника есть две характеристики: скорость работы S (заданная в условии) и средняя скорость работы с учетом перерывов, равная C * S / (C + D * S) (если я в формулах не напутал). Соответственно, если коробок мало, и все сотрудники успеют обработать коробки до ухода на перерыв, надо учитывать пиковую скорость работы, а если коробок много - то учитывать среднюю. Есть еще промежуточный вариант, когда часть работников успела сделать перерыв, а часть - нет. Дальше мне показалось, что этот путь тупиковый, и я перешел к
подходу 2: обрабатывать коробки по одной. Берем коробку, смотрим свободных сотрудников. Выбираем самого быстрого (с максимальной скоростью). Даем коробку ему. Берем следующую коробку. Выбираем самого быстрого из оставшихся, и т. д. Если сотрудников больше нет - ждем. Отдельно нужно вести учет времени - когда кто-то освободился, выдавать коробку ему. Чем-то это начинает напоминать недавно проскакивавшую задачу про поезда, где надо было перегружать грузы из одного в другой, и на входе были вагоны с номерами и грузоподьемностью, а на выходе - из какого вагона в какой сколько груза грузить. Только тут у нас поезд 1 - это коробки, а поезд 2 - это минуты. "Грузоподъемность" имеет разные единицы измерения, поэтому нужен "коэффициент пересчета". И это - табличка с работниками.
Это пока все, что надумал.
...
Рейтинг: 0 / 0
Пятничная задача: работнички.
    #40122535
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Никанор Кузьмич,

Осталась самая малость, перевести на буржуинский select from where

часть перевода (speed, capacity, delay) Александр уже засветил

ps
в задачке с поездами, если камазы не разгружать, а выставить навпротив соответствующих вагонов, то придем к "красивому" решению
.....
stax
...
Рейтинг: 0 / 0
Пятничная задача: работнички.
    #40122568
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax
к-во итераций равно к-ву коробок
В моём случае число итераций чуть меньше потому что на каждой итерации я смотрю ближайший момент когда кто-то свободится (shift)
и считаю сколько коробок обработано (finished - может быть 1 или несколько).
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
SQL> with w(id, speed, capacity, delay) as (
  2  select 1 id, 10 speed, 12 capacity, 2 delay from dual
  3  union all select 2, 30, 10, 5 from dual
  4  union all select 3, 20, 4, 5 from dual
  5  union all select 4, 35, 100, 100 from dual
  6  )
  7  , r (time_next, n, time, lvl) as
  8  (select 0, 31, 0, 1 from dual
  9   union all
 10   select r.time_next + a.shift, n - a.finished, r.time_next, r.lvl + 1
 11   from r
 12  cross apply (select min(case when tmp < speed * capacity then (trunc(tmp / speed) + 1) * speed else speed * (capacity + 1) + delay end - tmp) shift,
 13                      sum(case when tmp > 0 and tmp <= speed * capacity and mod(tmp, speed) = 0 then 1 else 0 end) finished
 14                     from (select t.*, mod(time_next, speed * capacity + delay) tmp from w t) tt) a
 15  where n > 0)
 16  cycle lvl set cycle to 1 default 0
 17  select max(time) result from r
 18  /

    RESULT
----------
       152

Можно было бы обойтись по сути двумя столбцами time и n вместо четырёх.
lvl фигурирует в решении просто для нумерации проходов.
"cycle lvl set cycle to 1 default 0" указано потому что Ораклу всегда мерещаться циклы при наличии cross apply.

Если сделать "select * from r" то можно увидеть в какие моменты времени и сколько коробок убвало.

Очевидно, что на каждом проходе выполняется перебор всех работников.
Этого можно избежать если выстраивать их в очередь по близости освобождения, но тут уже потребуется PL/SQL.
...
Рейтинг: 0 / 0
Пятничная задача: работнички.
    #40122576
dba123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если правильно понял задачу
Дано:
1,2,3
3,10,3
2,4,3
Условия:
1) два человека не могут открывать одну коробку (разбирать содержимое)
2) минимальный шаг времени 1 минута
3) коробки идут без перерывов

Тогда получаем, что за 4 мин - втроем сделают 5 коробок и за 5 мин тоже только 5 коробок, а за 6 минут уже 8.
Т.е. 7 коробок все равно сделают за 6 мин и быстрей никак (плюс одна бонусная)
box Job1(mi) Job2(mi) Job3(mi)1 1 3 22 2 =+1 6 =+3 4 =+23 6 =+4 9 =+3 6 =+24 7 =+1 12 =+3 8 =+25 11 =+4 15 =+3 13 =+56 12 =+1 18 =+3 15 =+27 16 =+4 21 =+3 17 =+28 17 =+1 24 =+3 19 =+29 21 =+4 27 =+3 24 =+510 22 =+1 30 =+3 26 =+2

1.тогда на вопрос сколько коробок распакуют за Х минут 3 человека
mi1 2345678910111213141516171819202122box1345589101111121415151718202122222425
2. какое минимальное время потребуется троим рабочим, чтобы разобрать Х коробок
box1 2345678910111213141516171819202122232425mi122346667891112121315151617171819212122
...
Рейтинг: 0 / 0
Пятничная задача: работнички.
    #40122586
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dba123
минимальный шаг времени 1 минута
В частном случае когда speed & delay are integers.
dba123
сколько коробок распакуют за Х минут 3 человека
Для этого можно составить относительно простое выражение.
dba123
какое минимальное время потребуется троим рабочим, чтобы разобрать Х коробок
Интересный вопрос выводима ли эта функция аналитически, но я сомневаюсь.
...
Рейтинг: 0 / 0
25 сообщений из 61, страница 1 из 3
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Пятничная задача: работнички.
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]