My Old LibTech Blog (2013-2016)

The simple joys

Author: John Durno
Date: 2014-02-21

In between going to meetings, tweaking our operational plan, writing performance reviews, budgeting for next years' computer replacements, and whatever else we managers do, I occasionally find the time to write a bit of code.

Of course, there are people in Library Systems who do that much better than I do, but there's always more coding to be done than there are folks to do it so I like to pitch in when I can. And it has its rewards, over and above the obvious utility of whatever script or web app that results from my efforts.

Now, pretty much all the code I write is pretty basic and would not win any awards for ... well, anything. The data goes into the database, the data comes out again, all mediated by a web interface. Your standard CRUD webapp, to use the parlance (CRUD being an acronym for Create, Read, Update and Delete. I try not to write the other kind).

But even given the unambitious nature of my coding projects I occasionally run into a problem I haven't solved before requiring a solution that isn't immediately obvious. And it is then I most keenly regret not actually having a formal computer science education, since it is almost certain whatever solution I come up with will be significantly worse than the elegant algorithm someone else came up with back in 1957, or whenever it was. Which I would know, if I had taken Comp. Sci. 101.

I encountered such a moment yesterday, when I had the need to implement (in PHP) an algorithm that would distribute a set of tasks among a group of individuals in a more or less equitable way. The catch was that individuals within the group might already have an unequal number of tasks assigned to them, so the new tasks needed to be assigned in a way that evened things out. I didn't want to add to the workload of those who were already busy unless the number of tasks to be assigned caused the totals of everyone in the group to exceed the amount of tasks currently assigned to the busiest ones. Another catch was that I couldn't simply reassign the existing tasks to make things equitable before assigning new ones.

For example, let's say we have 3 people: Bob with zero tasks assigned, Carol, with 3, and Francis, with 6. We have eight new tasks to distribute among them. To make it fair, Bob should get five new tasks, Carol should get three, and Francis should get none. End result is Bob now has five, Carol has five, and Francis has the six she started with.

I've deliberately made the above wordy and opaque to accurately mirror my first pass at describing the problem to myself. Phrased that way, I thought I might be looking at some ugly and convoluted code. But eventually I figured out that there was a much simpler way of framing the problem, which was: I need to assign each new task to the individual with the least amount of tasks assigned to them at that moment. And that's pretty easy to implement.



$tasks = array(1,2,3,4,5,6,7,8);
$people = array('Bob' => 0, 'Carol' => 3, 'Francis' => 6);
$assignments = array();
foreach ($tasks as $task) {
   //sort the people array on the values, lowest to highest
   asort($people);
   //get the first key in the sorted array
   $firstPerson = current(array_keys($people));
   //assign the task to the first Person in the sorted array
   $assignments[$firstPerson][] = $task;
   //increment the number of tasks associated with the person
   $people[$firstPerson]++;
}


So what I thought was going to be a convoluted mess turned out to be a very short foreach loop. There's something highly satisfying about reducing complexity in this way, even if it doesn't completely allay the suspicion that someone a lot smarter than I am probably came up with an even better way of solving the same problem back before I was born.