oko1 has asked for the wisdom of the Perl Monks concerning the following question:

Greetings:

I'm trying to allocate a working schedule denoted by numerical ranges of 200 units apiece. What I need is a way to display that schedule split up into a number of "chunks" per volunteer, where each volunteer has given me the number of chunks they're willing to do, like so:

$a = 2192; # Starting number # Ben = 5, Scott = 4, Jim = 1, more to be added later for (0..98){ my $b=$a + 200; my $name = $_ % 10 < 5 ? "Ben" : $_ % 10 > 8 ? "Jim" : "Scott"; print "$a-$b\t\t$name", "\n"; $a+=201; }

So far, this does the right thing - but adding each volunteer is a pain, and I see myself hacking great big ugly *unreadable* logic trees into the script. Yuck!

What I'd really like is a hash where I can add, e.g., 'Joe => 3' and have the script allocate all the stuff properly. Doesn't sound too complex, right? Yeah, I do feel like an idiot for not being able to figure this out for myself...

Thanks for any help.


--
"Language shapes the way we think, and determines what we can think about."
-- B. L. Whorf

Replies are listed 'Best First'.
Re: Fair schedule allocation?
by zwon (Abbot) on Jan 04, 2010 at 20:18 UTC
    use strict; use warnings; my $aa = 2192; my @volunteers = (('Ben') x 5, ('Scott') x 4, 'Jim'); for (0..98){ my $bb = $aa + 200; my $name = $volunteers[ $_ % @volunteers ]; print "$aa-$bb\t\t$name", "\n"; $aa+=201; }

    As a side note -- $a and $b are special variables, don't assign these names to your variables.

      Oh, pretty! :) Thank you - very nice, exactly what I was looking for.


      --
      "Language shapes the way we think, and determines what we can think about."
      -- B. L. Whorf
Re: Fair schedule allocation?
by Tanktalus (Canon) on Jan 04, 2010 at 22:08 UTC

    Take your comment, and put it into data. Derive everything from it. I just happen to like AoH's, as it's easy to extend it out more.

    #/usr/bin/perl use strict; use warnings; use Readonly; my @volunteers = ( { name => "Ben", chunks => 5 }, { name => "Scott", chunks => 4 }, { name => "Jim", chunks => 1 }, ); my $current = 2192; Readonly my $CHUNKSIZE => 200; use List::Util qw(sum); my $total_volunteer_chunks = sum map { $_->{chunks} } @volunteers; sub volunteer_for { my $n = shift() % $total_volunteer_chunks; for my $v (@volunteers) { $n -= $v->{chunks}; if ($n < 0) { return $v; } } } for my $chunk (0..98) { my $end = $current + $CHUNKSIZE; my $victim = volunteer_for($chunk)->{name}; print "$current-$end\t\t$victim\n"; $current = $end + 1; }

    Update: Fixed the code. It works now.

      I'm afraid I couldn't get it to work: after fixing the 'Readonly my ...' line and adding the missing curly brace at the end of the sub, it only printed one iteration. :\ I do see the approach you're taking, though - thanks for the idea!


      --
      "Language shapes the way we think, and determines what we can think about."
      -- B. L. Whorf
Re: Fair schedule allocation?
by Anonymous Monk on Jan 04, 2010 at 20:04 UTC
    If you assign a number to each volunteer and then make an array of total size of chunks and allocate every hour the number of the volunteer that should be able to give you the name of volunteer.

    For example:

    $hash = { Ben = 5, scott => 4, jim => 1 }; @names = qw( Ben Scott Jim) @array = [ 0,0,0,0,0,1,1,1,1,2]; $name = $names[$array[$_]];
    You can create the @names and @array from the given data.
      @array = [ 0,0,0,0,0,1,1,1,1,2];

      That's exactly the kind of thing I'm trying to avoid having to do. But thanks for the suggestion, anyway. :)


      --
      "Language shapes the way we think, and determines what we can think about."
      -- B. L. Whorf
Re: Fair schedule allocation?
by JavaFan (Canon) on Jan 05, 2010 at 11:37 UTC
    my %vols = ( Ben => 5, Scott => 4, Jim => 1, ); my $batches = 98; OUTER: { while (my ($v, $c) = each %vols) { foreach (1 .. $c) { say $v; last OUTER unless $batches--; } } redo; }
    This may not be everyones definition of 'fair'. If you want Scott, Ben and Jim take one batch each if there are only 3 batches, the algorithm above won't work (but then, neither did yours).