<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: creating worker schedules in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/creating-worker-schedules/m-p/328194#M73264</link>
    <description>&lt;P&gt;Trying to generate all the possible schedules, here I used a frequentist approach. This code is basically a collection of answers that I received from other community members (or a modification) so all credit goes to them:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data permutations (drop=i);
array time{9} $ ("a" "a" "a" "b" "b" "b" "c" "c" "c") ; /*initialize the first possible schedule,
which assumes that employee a fills all 3 time slots of day 1, employee b all time slots of 
day 2 and employee c all time slots of day 3*/

do i = 1 to fact(9);
   call allperm(i, of time[*]);
   output;
end;
run;

/*select unique schedules because all possible permutations resulted in many repetitive schedules */
proc sql;
create table schedule as
select distinct * from permutations;
quit;

/*apply the constraint that the first hour of day 1 belongs to employee a*/

data schedule;
set schedule;
if time1 = "a";
n = _n_;
run;

/*apply the constraint that in any given day no more than 2 time slots are allocated
to the same employee. First create data constraint2 because the sortc function will 
sort the time slots of each day, therefore diminishing the possibilities. */
data constraint2;
  set schedule;
  array v1(*) $ time1-time3;
  array v2(*) $ time4-time6;
  array v3(*) $ time7-time9;

  call sortc(of v1(*));
  do i=1 to dim(v1);
    if not missing(v1(i)) then do;
      if i lt dim(v1) then do;
        if v1(i)ne v1(i+1) then day1=sum(day1,1);
      end;
      else day1=sum(day1,1);
    end;
  end;

call sortc(of v2(*));
  do i=1 to dim(v2);
    if not missing(v2(i)) then do;
      if i lt dim(v2) then do;
        if v2(i)ne v2(i+1) then day2=sum(day2,1);
      end;
      else day2=sum(day2,1);
    end;
  end;

  call sortc(of v3(*));
  do i=1 to dim(v3);
    if not missing(v3(i)) then do;
      if i lt dim(v3) then do;
        if v3(i)ne v3(i+1) then day3=sum(day3,1);
      end;
      else day3=sum(day3,1);
    end;
  end;
run;

data constraint2 (drop=i);
set constraint2;
if day1 ne 1 and day2 ne 1 and day3 ne 1;
drop time1-time9;
run;

data schedule;
merge schedule constraint2;
by n;
if day1 ne '.';
run;



/*apply the constraint that when an employee works 2 hours in a day these 2 hours must be consecutive*/
 data schedule;
set schedule;
array day(*) day1-day3;
array time(*) time1-time9;
array flag(3);

do j = 1 to 3;
   if day{j} = 3 then flag{j} = 1;
   else  
     do i=1 to 2;
       if time{3*(j-1)+i}=time{3*(j-1)+i+1} then flag{j}=1;
     end;
end;

  do k = 1 to dim(flag);
    if flag{k}=1;
  end;
drop i j;
run;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;In total I obtained 248 different schedules given the constraints. I will be very glad to have suggestions on how to make this code better!&lt;/P&gt;</description>
    <pubDate>Sat, 28 Jan 2017 05:11:02 GMT</pubDate>
    <dc:creator>ilikesas</dc:creator>
    <dc:date>2017-01-28T05:11:02Z</dc:date>
    <item>
      <title>creating worker schedules</title>
      <link>https://communities.sas.com/t5/SAS-Programming/creating-worker-schedules/m-p/325849#M72508</link>
      <description>&lt;P&gt;Hi,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;here is a puzzle (although it could have a real application) I am working on and will be glad for assistance! Its about creating random working schdules for employees subject to constraints.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;suppose that a company has a 3 day work week, and each day consists of 3 consecutive working hours - so there are 9 working hours in a work week. These 9 work hours have to be equally divided between 3 employees, so each employee works 3 hours in a work week.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;It should be noted that any employee can't work more than 2 hours in a day, and if an employee works 2 hours in a given day these hours have to be consecutive. Also, the first hour of the first day belongs to employee # 1.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Thanks!&lt;/P&gt;</description>
      <pubDate>Wed, 18 Jan 2017 23:59:16 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/creating-worker-schedules/m-p/325849#M72508</guid>
      <dc:creator>ilikesas</dc:creator>
      <dc:date>2017-01-18T23:59:16Z</dc:date>
    </item>
    <item>
      <title>Re: creating worker schedules</title>
      <link>https://communities.sas.com/t5/SAS-Programming/creating-worker-schedules/m-p/325852#M72509</link>
      <description>&lt;P&gt;Is the challenge creating any schedule or all schedules? Or did another constraint get lost?&lt;/P&gt;
&lt;P&gt;1 hour per person per work day looks like a minimal solution&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Day employee hour&lt;/P&gt;
&lt;P&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1&lt;/P&gt;
&lt;P&gt;2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1&lt;/P&gt;
&lt;P&gt;3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1&lt;/P&gt;
&lt;P&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2&lt;/P&gt;
&lt;P&gt;2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2&lt;/P&gt;
&lt;P&gt;3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2&lt;/P&gt;
&lt;P&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3&lt;/P&gt;
&lt;P&gt;2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3&lt;/P&gt;
&lt;P&gt;3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3&lt;/P&gt;</description>
      <pubDate>Wed, 18 Jan 2017 23:46:05 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/creating-worker-schedules/m-p/325852#M72509</guid>
      <dc:creator>ballardw</dc:creator>
      <dc:date>2017-01-18T23:46:05Z</dc:date>
    </item>
    <item>
      <title>Re: creating worker schedules</title>
      <link>https://communities.sas.com/t5/SAS-Programming/creating-worker-schedules/m-p/325854#M72510</link>
      <description>&lt;P&gt;that would be a trivial solution, the spirit of the question (and I guess that I should have mentioned it) is to create a random schedule, given the constraints. But now that you mentioned it, creating all possible schedules could also be very interesting!&lt;/P&gt;</description>
      <pubDate>Wed, 18 Jan 2017 23:58:30 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/creating-worker-schedules/m-p/325854#M72510</guid>
      <dc:creator>ilikesas</dc:creator>
      <dc:date>2017-01-18T23:58:30Z</dc:date>
    </item>
    <item>
      <title>Re: creating worker schedules</title>
      <link>https://communities.sas.com/t5/SAS-Programming/creating-worker-schedules/m-p/326219#M72617</link>
      <description>&lt;P&gt;Hi.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Interesting puzzle, here a greedy approach (will try to allocate maximum hours first) to solve it:&lt;CODE class=" language-sas"&gt;&lt;BR /&gt;&lt;/CODE&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;
%macro rand_schedule(TOTAL,SPLIT,FIRST,MAXUNIT);

%let EACH=%eval(&amp;amp;TOTAL/&amp;amp;SPLIT);

data _SCHEDULE;
     length HOUR 8;
     array _TOTAL[&amp;amp;SPLIT]; * totals;
     array SCHED[&amp;amp;SPLIT]; * schedule;
     drop _:;
     _I_=0;
     do HOUR=1 to &amp;amp;TOTAL; 
        do until (_TOTAL[_I] lt &amp;amp;EACH and _I ne _I_);
           if HOUR eq 1 then _I=&amp;amp;FIRST; * force first allocation;
           else _I=ceil(rand("Uniform")*&amp;amp;SPLIT);
        end; * randomly select;
        _I_=_I; * keep last allocated;
        if sum(_TOTAL[_I],&amp;amp;MAXUNIT) gt &amp;amp;EACH then _NEXT=sum(&amp;amp;EACH,-_TOTAL[_I]);
        else _NEXT=&amp;amp;MAXUNIT; * try max allocation;
        _TOTAL[_I]=sum(_TOTAL[_I],_NEXT);
        * schedule;
        do _J=1 to _NEXT;
           do _K=1 to &amp;amp;SPLIT; 
              SCHED[_K]=0;
           end; 
           SCHED[_I]=1;
           output;
           HOUR+1;
        end;
        HOUR+-1;
     end;
run;

%mend rand_schedule;

%rand_schedule(9,3,1,2); * total hours, num. of workers, first allocated, max consecutive hours;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Hope it helps.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Daniel Santos&amp;nbsp;@ &lt;A href="http://www.cgd.pt" target="_blank"&gt;www.cgd.pt&lt;/A&gt;&lt;/P&gt;</description>
      <pubDate>Fri, 20 Jan 2017 10:29:13 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/creating-worker-schedules/m-p/326219#M72617</guid>
      <dc:creator>DanielSantos</dc:creator>
      <dc:date>2017-01-20T10:29:13Z</dc:date>
    </item>
    <item>
      <title>Re: creating worker schedules</title>
      <link>https://communities.sas.com/t5/SAS-Programming/creating-worker-schedules/m-p/326325#M72653</link>
      <description>&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/12982"&gt;@ilikesas&lt;/a&gt; wrote:&lt;BR /&gt;
&lt;P&gt;that would be a trivial solution, the spirit of the question (and I guess that I should have mentioned it) is to create a random schedule, given the constraints. But now that you mentioned it, creating all possible schedules could also be very interesting!&lt;/P&gt;
&lt;HR /&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I'm a mathematician by (some)&amp;nbsp;training. Unless a non-trivial solution is specifically requested I'm going to generate the simplest and often trivial solution.&lt;/P&gt;</description>
      <pubDate>Fri, 20 Jan 2017 16:09:38 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/creating-worker-schedules/m-p/326325#M72653</guid>
      <dc:creator>ballardw</dc:creator>
      <dc:date>2017-01-20T16:09:38Z</dc:date>
    </item>
    <item>
      <title>Re: creating worker schedules</title>
      <link>https://communities.sas.com/t5/SAS-Programming/creating-worker-schedules/m-p/326477#M72700</link>
      <description>&lt;P&gt;Hi DanielSantos,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;thanks for the code, it is pretty complex and I am trying to understand it.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If HOUR = 1 , then _I = 1, but what is _TOTAL[1] if it was never allocated ?&lt;/P&gt;</description>
      <pubDate>Sat, 21 Jan 2017 04:13:58 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/creating-worker-schedules/m-p/326477#M72700</guid>
      <dc:creator>ilikesas</dc:creator>
      <dc:date>2017-01-21T04:13:58Z</dc:date>
    </item>
    <item>
      <title>Re: creating worker schedules</title>
      <link>https://communities.sas.com/t5/SAS-Programming/creating-worker-schedules/m-p/326635#M72783</link>
      <description>&lt;P&gt;Hi.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I've commented the code a little more to help you understanding it.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;So, as you can see the code works on 3 separate phases.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%let EACH=%eval(&amp;amp;TOTAL/&amp;amp;SPLIT); * calculate the amount of hours per worker;

data _SCHEDULE;
     length HOUR 8

     array _TOTAL[&amp;amp;SPLIT]; * this is used to track the current hours allocated to each worker;
     array SCHED[&amp;amp;SPLIT]; * this is the schedule for each worker, SCHED1 ... SCHEDn;

     drop _:; * auxiliary vars prefixed with _ so than can be easily dropped;

     _I_=0; 
     do HOUR=1 to &amp;amp;TOTAL; * cycle for each hour;

        * 1. find one worker with available time and that is not working in the previous hour;
        do until (_TOTAL[_I] lt &amp;amp;EACH and _I ne _I_); 
           if HOUR eq 1 then _I=&amp;amp;FIRST; * force first allocation to be worker 1;
           else _I=ceil(rand("Uniform")*&amp;amp;SPLIT); * pick one worker randomly;
        end;
        _I_=_I; * keep track of last allocated worker for next hour;

        * 2. greedly try to allocate maximum hours;
        if sum(_TOTAL[_I],&amp;amp;MAXUNIT) gt &amp;amp;EACH then _NEXT=sum(&amp;amp;EACH,-_TOTAL[_I]);
        else _NEXT=&amp;amp;MAXUNIT; * try max allocation;
        * _NEXT holds the allocated hours;
        _TOTAL[_I]=sum(_TOTAL[_I],_NEXT); * update total hours allocated for selected worker;

        * 3. update the schedule;
        do _J=1 to _NEXT; * cycle throught allocated hours;
           do _K=1 to &amp;amp;SPLIT; 
              SCHED[_K]=0; * set 0 for workers not selected;
           end; 
           SCHED[_I]=1; * set 1 for selected worker;
           output;
           HOUR+1; * adjust next;
        end;
        HOUR+-1; * adjust back;
     end;
run;

%mend rand_schedule;

%rand_schedule(9,3,1,2); * total hours, num. of workers, first allocated, max consecutive hours;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;First it tries to find an available worker that has not reached the total amount of hours for each and that is not working in the previous hour.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Then it tries to allocate the maximum consecutive hours, if it is not possible, then it will allocate the difference (maximum - current total).&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Finally it will build the schedule by cycling through the number of hours allocated and setting 0 and 1 to the corresponding workers.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Hope it helps.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Daniel Santos @ &lt;A href="http://www.cgd.pt" target="_blank"&gt;www.cgd.pt&amp;nbsp;&lt;/A&gt;&lt;/P&gt;</description>
      <pubDate>Mon, 23 Jan 2017 08:50:48 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/creating-worker-schedules/m-p/326635#M72783</guid>
      <dc:creator>DanielSantos</dc:creator>
      <dc:date>2017-01-23T08:50:48Z</dc:date>
    </item>
    <item>
      <title>Re: creating worker schedules</title>
      <link>https://communities.sas.com/t5/SAS-Programming/creating-worker-schedules/m-p/327638#M73103</link>
      <description>&lt;P&gt;Thanks for the explanation, now I understand the code much better and learned a lot from it!&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;After running the code several times, I noticed that the schedules are not "truly random" in the sense that each employee necessarily has 2 consecutive hours and his single hour is always preceded by the 2 consecutive hours. Trying to make the schedules more "random" I added a code that if the hour is the last hour of the day, then the next hour can be either consecutive to it or not.&lt;/P&gt;
&lt;P&gt;Here is the new code:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data _SCHEDULE;
     length HOUR 8;
     array _TOTAL[3]; * this is used to track the current hours allocated to each worker;
     array SCHED[3]; * this is the schedule for each worker, SCHED1 ... SCHEDn;
     drop _:; * auxiliary vars prefixed with _ so than can be easily dropped;
     _I_=0;

     do HOUR=1 to 9; 

	 * 1. find one worker with available time and that is not working in the previous hour;
        do until (_TOTAL[_I] lt 3 and _I ne _I_);
           if HOUR eq 1 then _I=1; * force first allocation to be worker 1;
           else _I=ceil(rand("Uniform")*3); * pick one worker randomly;
        end; ;
        _I_=_I; * keep track of last allocated worker for next hour;


if (hour/3) ne int(hour/3) then do; 
		* 2. greedly try to allocate maximum hours;
        if sum(_TOTAL[_I],2) gt 3 then _NEXT=sum(3,-_TOTAL[_I]);
        else _NEXT=2; * try max allocation;
        _TOTAL[_I]=sum(_TOTAL[_I],_NEXT); * update total hours allocated for selected worker;
      
		* 3. update the schedule;
        do _J=1 to _NEXT; * cycle throught allocated hours;
           do _K=1 to 3; 
              SCHED[_K]=0; * set 0 for workers not selected;
           end; 
           SCHED[_I]=1; * set 1 for selected worker;
           output;
           HOUR+1; * adjust next;
        end;
        HOUR+-1; * adjust back;
     end ;

else if (hour/3) = int(hour/3) then do;
_NEXT = 1 + rand("Bernoulli",0.5);
_TOTAL[_I]=sum(_TOTAL[_I],_NEXT);
do _J=1 to _NEXT; * cycle throught allocated hours;
           do _K=1 to 3; 
              SCHED[_K]=0; * set 0 for workers not selected;
           end; 
           SCHED[_I]=1; * set 1 for selected worker;
           output;
           HOUR+1; * adjust next;
        end;
        HOUR+-1; * adjust back;
    end;
end;
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;That is, the Bernoulli random number generator decided whether the next hour will be consecutive or not. At first I ran the code several times and it seemd that the schedules appeared more random, but then saw weired things: sometimes an employee would get 4 hours whereas another enployee would get only 2, and sometimes an additional 10th hour was created to accomodate a consecutive hour to the 9th hour. Please help!&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 26 Jan 2017 04:53:12 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/creating-worker-schedules/m-p/327638#M73103</guid>
      <dc:creator>ilikesas</dc:creator>
      <dc:date>2017-01-26T04:53:12Z</dc:date>
    </item>
    <item>
      <title>Re: creating worker schedules</title>
      <link>https://communities.sas.com/t5/SAS-Programming/creating-worker-schedules/m-p/328194#M73264</link>
      <description>&lt;P&gt;Trying to generate all the possible schedules, here I used a frequentist approach. This code is basically a collection of answers that I received from other community members (or a modification) so all credit goes to them:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data permutations (drop=i);
array time{9} $ ("a" "a" "a" "b" "b" "b" "c" "c" "c") ; /*initialize the first possible schedule,
which assumes that employee a fills all 3 time slots of day 1, employee b all time slots of 
day 2 and employee c all time slots of day 3*/

do i = 1 to fact(9);
   call allperm(i, of time[*]);
   output;
end;
run;

/*select unique schedules because all possible permutations resulted in many repetitive schedules */
proc sql;
create table schedule as
select distinct * from permutations;
quit;

/*apply the constraint that the first hour of day 1 belongs to employee a*/

data schedule;
set schedule;
if time1 = "a";
n = _n_;
run;

/*apply the constraint that in any given day no more than 2 time slots are allocated
to the same employee. First create data constraint2 because the sortc function will 
sort the time slots of each day, therefore diminishing the possibilities. */
data constraint2;
  set schedule;
  array v1(*) $ time1-time3;
  array v2(*) $ time4-time6;
  array v3(*) $ time7-time9;

  call sortc(of v1(*));
  do i=1 to dim(v1);
    if not missing(v1(i)) then do;
      if i lt dim(v1) then do;
        if v1(i)ne v1(i+1) then day1=sum(day1,1);
      end;
      else day1=sum(day1,1);
    end;
  end;

call sortc(of v2(*));
  do i=1 to dim(v2);
    if not missing(v2(i)) then do;
      if i lt dim(v2) then do;
        if v2(i)ne v2(i+1) then day2=sum(day2,1);
      end;
      else day2=sum(day2,1);
    end;
  end;

  call sortc(of v3(*));
  do i=1 to dim(v3);
    if not missing(v3(i)) then do;
      if i lt dim(v3) then do;
        if v3(i)ne v3(i+1) then day3=sum(day3,1);
      end;
      else day3=sum(day3,1);
    end;
  end;
run;

data constraint2 (drop=i);
set constraint2;
if day1 ne 1 and day2 ne 1 and day3 ne 1;
drop time1-time9;
run;

data schedule;
merge schedule constraint2;
by n;
if day1 ne '.';
run;



/*apply the constraint that when an employee works 2 hours in a day these 2 hours must be consecutive*/
 data schedule;
set schedule;
array day(*) day1-day3;
array time(*) time1-time9;
array flag(3);

do j = 1 to 3;
   if day{j} = 3 then flag{j} = 1;
   else  
     do i=1 to 2;
       if time{3*(j-1)+i}=time{3*(j-1)+i+1} then flag{j}=1;
     end;
end;

  do k = 1 to dim(flag);
    if flag{k}=1;
  end;
drop i j;
run;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;In total I obtained 248 different schedules given the constraints. I will be very glad to have suggestions on how to make this code better!&lt;/P&gt;</description>
      <pubDate>Sat, 28 Jan 2017 05:11:02 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/creating-worker-schedules/m-p/328194#M73264</guid>
      <dc:creator>ilikesas</dc:creator>
      <dc:date>2017-01-28T05:11:02Z</dc:date>
    </item>
    <item>
      <title>Re: creating worker schedules</title>
      <link>https://communities.sas.com/t5/SAS-Programming/creating-worker-schedules/m-p/328363#M73319</link>
      <description>&lt;P&gt;Hi.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Sorry for the late reply, I've been busy lately.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If you&amp;nbsp;need total randomess it's much simpler than that, you just have to modify the following piece of my code:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&lt;SPAN&gt;...&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;* 2. randomly allocate hours &amp;lt;= MAXUNIT;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt; _NEXT=ceil(rand("Uniform")*&amp;amp;MAXUNIT); * choose randomly up to MAXUNIT;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt; if sum(_TOTAL[_I],_NEXT) gt &amp;amp;EACH then _NEXT=sum(&amp;amp;EACH,-_TOTAL[_I]); * adjust if above total;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt; * _NEXT holds the allocated hours;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt; _TOTAL[_I]=sum(_TOTAL[_I],_NEXT); * update total hours allocated for selected worker;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;...&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="arial,helvetica,sans-serif"&gt;&lt;SPAN&gt;Hope it helps.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="arial,helvetica,sans-serif"&gt;&lt;SPAN&gt;Daniel Santos&amp;nbsp;@ &lt;A href="http://www.cgd.pt" target="_blank"&gt;www.cgd.pt&lt;/A&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;</description>
      <pubDate>Mon, 30 Jan 2017 11:32:10 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/creating-worker-schedules/m-p/328363#M73319</guid>
      <dc:creator>DanielSantos</dc:creator>
      <dc:date>2017-01-30T11:32:10Z</dc:date>
    </item>
  </channel>
</rss>

