title: Distributing jobs fairly on accounts - distribution algorithm
body: <p>I'm working on a project that publish to a multiple websites using a multiple accounts. each account can publish to a specific website. as shown in the 'Dict' below. The problem is I'm trying to distribute the publishing jobs on accounts fairly and making a distance between accounts that has more than 1 job.</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq;
  
  public class Program
  {
      public struct Job
      {
          public string Site { get; set; }
          public string Account { get; set; }
      }
  
  
      private  static readonly Dictionary&lt;string, List&lt;string&gt;&gt; Dict = new Dictionary&lt;string, List&lt;string&gt;&gt;();
      private  static List&lt;string&gt; _accounts;
  
  
      public static void Main()
      {
          var sites = new List&lt;string&gt;{"Site-A", "Site-B", "Site-C", "Site-D", "Site-E"};
           _accounts = new List&lt;string&gt;{"Account-A", "Account-B", "Account-C", "Account-D", "Account-E"};
  
          // Permissions dictionary. specify accounts that has a permessions to  publish on a particular Site
          Dict.Add("Site-A", new List&lt;string&gt;{"Account-A", "Account-C"});
          Dict.Add("Site-B", new List&lt;string&gt;{"Account-A", "Account-E"});
          Dict.Add("Site-C", new List&lt;string&gt;{"Account-C", "Account-D"});
          Dict.Add("Site-D", new List&lt;string&gt;{"Account-A"});
          Dict.Add("Site-E", new List&lt;string&gt;{"Account-A"});
  
              var jobs = new List&lt;Job&gt;();
              foreach (var site in sites)
              {
                  var job = new Job();
  
                  // Get an account that has a permissions to publish on 'site'
                  // checking against the permissions dictionary Dict
                  var account = GetAccountCanPost(Dict, site, _accounts);
  
                  job.Site = site;
                  job.Account = account;
  
                  jobs.Add(job);
              }
  
  
              var jobsCountForEachAccountDict = CalculateJobsCountForEachAccounts(jobs);
  
              //////#### Now.. We need to re Order Jobs and swipe it here before send it to processing ####.....//////
  
              foreach (var job in jobs)
              {
                  Console.WriteLine(job.Account + " publish on " + job.Site);
              }
  
      }
  
       public static Dictionary&lt;string, int&gt; CalculateJobsCountForEachAccounts(List&lt;Job&gt; jobs)
          {
              var dict = new Dictionary&lt;string, int&gt;();
  
              foreach (var job in jobs)
              {
                  if (dict.ContainsKey(job.Account))
                      dict[job.Account]++;
                  else
                      dict.Add(job.Account, 1);
              }
  
              return dict;
          }
  
  
       public static string GetAccountCanPost(Dictionary&lt;string, List&lt;string&gt;&gt; dict, string targetSite, List&lt;string&gt; accounts)
          {
              var accountIdsAssoc = GetAccountsIdsAssociatedWithCommunity(dict, targetSite);
  
              var selectedId = PickRandom(accountIdsAssoc, new Random());
              var account = accounts.FirstOrDefault(s =&gt; s == selectedId);
  
              return account;
          }
  
       private static List&lt;string&gt; GetAccountsIdsAssociatedWithCommunity(Dictionary&lt;string, List&lt;string&gt;&gt; communitiesAccountsAssociationsDict, string communityId)
          {
              if (communitiesAccountsAssociationsDict.ContainsKey(communityId))
                  return communitiesAccountsAssociationsDict[communityId];
  
              return null;
          }
  
           private static T PickRandom&lt;T&gt;(IList&lt;T&gt; list, Random random)
          {
              var index = random.Next(0, list.Count);
              return list[(int) index];
          }
  
  }
  </code></pre>
  
  <p>when the jobs are created it is something similar to this: (Before re-adjusting the jobs distribution)</p>
  
  <pre><code>&gt; Account-A Publish on Site-A 
  &gt; Account-E Publish on Site-B
  &gt; Account-D Publish on Site-C
  &gt; Account-A Publish on Site-D
  &gt; Account-A Publish on Site-E
  </code></pre>
  
  <p>The publishing jobs created above are not fairly distributed to accounts, as you can see 'Account-A' has 3 jobs assigned while there's an other accounts can publish to the 'sites' as defined in 'Dict' so it should look something like:</p>
  
  <pre><code>&gt; Account-C Publish on Site-A
  &gt; Account-E Publish on Site-B
  &gt; Account-A Publish on Site-D
  &gt; Account-D Publish on Site-C
  &gt; Account-A Publish on Site-E
  </code></pre>
  
  <p>In the output above the jobs are distributed fairly on accounts and also there's a distance between accounts that has more than 1 job</p>
  
  <p>An example on distance between jobs:</p>
  
  <pre><code>    &gt; Account-A Publish on Site-A 
      &gt; Account-E Publish on Site-B
      &gt; Account-D Publish on Site-C
      &gt; Account-A Publish on Site-D
      &gt; Account-A Publish on Site-E
  </code></pre>
  
  <p>Job 4 and 5 are being processed by Account-A. An account should not process two jobs sequentially, so it could be swapped with another job.</p>
  
  <p>It will be highly appreciated if you could help. I need an algorithm that do the job distribution to get similar output. Performance is not important.</p>
  
  <p>Thank you..</p>