0

I want to do the following, but am unsure of how to do it. I have read a number of solutions but they don't seem to fit what I want.

Please keep in mind I only have basic programming experience (some C and Pascal from 20+ years ago), and am trying to re-learn programming. A detailed explanation of some of the more advanced commands would be good.

So, say I have a list of items in a text file as follows:

1-5,foo
6-9,bar
10-12,snafu
13-14,blam
15,bingo

I need to roll randomly on a table three times, each time selecting an element from the table depending on the range it occurs in. Once that item is selected, it cannot be selected again during this process (i.e., each roll must result in a unique element being selected).

i.e., if a roll of four was made, then foo was selected. foo cannot be one of the next two rolls. The next roll results in an 11, that's snafu. snafu cannot be picked from the final roll.

etc etc.

The items picked should then be displayed.

I could do this by having each element on it's own line in the text file, reading the file into an array, find the total number of elements in the array and then randomly select three items from the array, using for loops and temporary arrays to remove the duplicate items of the element selected, but that could be messy.

I'd appreciate both a solution in Java and a solution in Perl but either/or is fine too.

I learn best form practical examples and doing than from reading theory books and websites.

I know I haven't posted any code, but that's because I'm not sure where to start or how to go about this. Any help will be appreciated.

SheetJS
  • 22,470
  • 12
  • 65
  • 75
Anestis
  • 3
  • 2
  • why don't you add them to a managed list and then when they are used removed them so they can not be used again. – Scary Wombat Aug 27 '13 at 04:20
  • 2
    I think you should narrow this down a bit, and write part of it. For some people, Perl is easier than Java and you can test it immediately without compilation. [This Perl question](http://stackoverflow.com/questions/1984320/how-can-i-get-weighted-random-selections-from-an-array-in-perl?rq=1) is a bit much for a beginner, but solves a random-sampling-without-replacement problem. Here's another [question/answer](http://stackoverflow.com/questions/8963228/how-can-i-take-n-elements-at-random-from-a-perl-array). Google "perl random sampling without replacement" has more. Now go write some code :) – Paul Aug 27 '13 at 04:37

1 Answers1

0

General steps to a (language-independent) solution:

First, reformat your list of items so that each one is associated with a weight (i.e., how many numbers will select it) instead of a specific range of numbers. e.g., For your sample data set, it would be:

foo,5
bar,4
snafu,3
blam,2
bingo,1

Next, add up all the weights and generate a random number from 1 to the total weight.

Now go through the list, subtracting the weight of each item as you go. When you reach an item whose weight is greater than the remaining weight, record it as your selection and remove it from the list, then go back to the "add up all the weights" step and repeat until you either have made the desired number of selections or you run out of items to choose from.

Example Perl implementation:

#!/usr/bin/env perl    

use strict;
use warnings;
use 5.010;

my %weight = (
  foo   => 5,
  bar   => 4,
  snafu => 3,
  blam  => 2,
  bingo => 1,
);

my $picks = 3;

while ($picks && %weight) {
  my $total_weight;
  $total_weight += $_ for values %weight;

  my $remaining_weight = rand($total_weight);
  for my $item (keys %weight) {
    if ($remaining_weight < $weight{$item}) {
      say $item;
      $picks--;
      delete $weight{$item};
      last;
    }
    $remaining_weight -= $weight{$item};
  }
}
Dave Sherohman
  • 45,363
  • 14
  • 64
  • 102
  • Thank you Dave, this works wonderfully. Now to try and adapt it to read in from a data file, and to output to a web page with the data selected. – Anestis Aug 30 '13 at 20:49