Marc Schlossberg
Marc Schlossberg

Reputation: 13

Need optimized program logic. Word problems1 Sweet1

So I'm creating a roster app for my co-ed softball team. The league rules say that if two guys bat in a row, a girl has to follow. This leads to problems if the guy girl ratio is not balanced, eg if there are 4 girls and 14 guys, at least one of the girls will have to bat twice in the same run through the batting order in order to satisfy the 'guy guy girl' rule, and then she has to be placed at the back of the queue of girls, so the next time through the second girl moves up to the first girl spot, the third to the second, etc etc. So by the third or fourth inning we're frantically scribbling the modified batting order on the back of a receipt or something as we try to keep track of who's batting when.

The purpose, then, of the app I'm creating is to allow the user to enter in a batting order, press a button, and see that batting order extrapolated over, say, four times through the order (obv user can decide how many), moving the girls in the lineup accordingly.

So far, the app allows you to add players, set their gender, and put them in a desired order. This is all tracked in a database. Now I'm up to the 'press a button, see x amount of times through the order'. What I have works, assuming that the order is strictly 'guy guy girl'. But it can't handle any variation in that, eg the initial order is 'guy girl guy guy' or 'girl guy guy'. The logic I've coded just ignores that and changes it to 'guy guy girl'.

What logic could I use to correctly handle any initial batting order?

Here's my code:

//pos == numerical position in the roster
public void computeKickingOrder() {
    String TAG = "cKO";
    // instantiate dbhandler
    DatabaseHandler db = new DatabaseHandler(this);

    // get all tasks
    List<Player> players = db.getAllPlayers();
    List<Player> guys = new ArrayList<Player>();
    List<Player> girls = new ArrayList<Player>();
    List<Player> theRoster = new ArrayList<Player>();

    int pCount = players.size();
    int cycles = 4;
    Log.d(TAG, "Total Players: " + pCount);

    Log.d(TAG, "Generating " + cycles + " runs through the order.");

    //one cycle = guycount + guycount/2

    //Iterator<Player> itr = players.iterator();
    Iterator<Player> itr;

    // first cycle through the whole roster and separate out guys and girls
    // use cycles + 5 to ensure that there are plenty of players available in each list 
    for (int i = 0 ; i < cycles + 5 ; i++) {
        itr = players.iterator();
        while(itr.hasNext()) {
            Player p = itr.next();
            if(p.getGender().equals("M")) { guys.add(p); }
            else { girls.add(p); }
        }
    }

    Log.d(TAG, "guys.size(): " + guys.size());
    Log.d(TAG, "girls.size(): " + girls.size());




    //below code automatically creates guy guy girl order IGNORES that a girl might be first or second
    int girlSpot = 0;
    int guyKicks = 1;
    int pos = 1;
    for(int i=0; i<guys.size(); i++) {
        if(guyKicks<3) {
            Player p = guys.get(i);
            p.setPos(pos);
            theRoster.add(p);
            guyKicks++;
            Log.d(TAG, pos + " | " + p.getGender() + " | " + p.getName());

        }

        else {
            guyKicks = 1;
            Player p = girls.get(girlSpot);
            p.setPos(pos);
            theRoster.add(p);
            girlSpot++;
            Log.d(TAG, pos + " | " + p.getGender() + " | " + p.getName());
        }

        pos++;

    }

Upvotes: 0

Views: 149

Answers (2)

Jeffrey Blattman
Jeffrey Blattman

Reputation: 22637

keep two queues: guys and gals. generate your "rotation template" without specific names, with only gal or gal denotation. so you have say,

1: guy
2: guy
3: gal
4: guy
5: gal
6: guy
7: guy
8: gal
9: gal

or whatever, so as long as it satisfies the guy-guy-gal rule. you generate the initial rotation by processing the rotation template. for each position, you pull either a guy or gal from their respective queues.

every time someone is pulled from the queue and inserted into the rotations, they are inserted back into the queue. they will be at bat again when the entire queue of guys or gals in front of them is exhausted.

Queue<String> guys = new LinkedList<String>();
Queue<String> gals = new LinkedList<String>();

guys.add("John");
guys.add("Jeff");
guys.add("Bill");
guys.add("Frank");

gals.add("Mary");
gals.add("Tricia");

enum Gender { GUY, GAL };

Gender[] template = new Gender[] { GUY, GUY, GAL, GUY, GUY, GAL, GUY, GAL, GAL };

String[] getRotation() {
  String[] rotation = new String[9];
  for (int i = 0; i < template.length; i++) {
    String batter;
    if (template[i] == GUY) {
      batter = guys.poll();
      guys.offer(batter);
    } else {
      batter = gals.poll();
      gals.offer(batter);
    }
    rotation[i] = batter;
  }  
  return rotation;
}

Upvotes: 1

Jim Mischel
Jim Mischel

Reputation: 133995

You can create a simple state machine. Look at the first two items in the starting order, and you know what state you're in. That is, if you have three states:

state 1: guy
state 2: guy
state 3: girl

Program flow goes from state 1 to state 2, then 2 to 3, and from 3 back to 1.

Now, if you look at the first two items in your starting order, you know what state you're in to begin with:

[guy, guy]:  starting state 1
[guy, girl]: starting state 2
[girl, guy]: starting state 3

Upvotes: 1

Related Questions