-1

Spec-

In the game the children sit in a circle and one person outside the ring (the leader) sings a song with a fixed number of words. Moving clockwise around the circle, the leader points to a new child in the ring for each word in the song. The child being pointed to on the last word of the song is out and must leave the circle. The leader then repeats the process with the smaller circle. The game continues until the last child is eliminated. This child is then the leader to start the next game.

I've almost got this logic figured out but there's a bug I can't find somewhere in the indexing of my array where I'm adding the current element to another array(to display the kids eliminated) and then removing them from the current array.

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Practice {

    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);
        System.out.println("Enter number of kids: ");
        int kidCount = sc.nextInt();
        List<Integer> kids = new ArrayList<Integer>();
        List<Integer> rejects = new ArrayList<Integer>();

        System.out.println("Enter number of words in the song: ");
        int words = sc.nextInt();

        int wordCount = 0;

        for (int i = 1; i <= kidCount; i++) {
            kids.add(i);
        }

        for (int i = 0; i < kids.size(); i++) {
            wordCount++;

            if (wordCount % words == 0) {
                rejects.add(kids.get(i));
                kids.remove(kids.get(i));

            }

            if (i == kids.size() - 1) {
                if (wordCount % words != 0) {
                    i = 0;
                } else {
                    rejects.add(kids.get(i));
                    kids.remove(kids.get(i));
                }
            }
        }
        System.out.println(rejects.toString());
    }
}

Expected output if there's 6 kids and 3 words: 3 6 4 2 5 1

Current output : [3, 2, 4, 6]

user3646508
  • 109
  • 5
  • 1
    Time to learn debugging as you already state in your question title. – m0skit0 Apr 04 '15 at 13:55
  • 1
    possible duplicate of [What is a debugger and how can it help me diagnose problems](http://stackoverflow.com/questions/25385173/what-is-a-debugger-and-how-can-it-help-me-diagnose-problems) – Raedwald Apr 04 '15 at 14:20

1 Answers1

4

Your way of looping through the kids is flawed. The way you "loop around" will always skip kid 1, since you set i=0 immediately before doing i++. Additionally, if you removed the kid before last, e.g. kid 5, you will instantly also remove the last kid, e.g. kid 6, because the size of the kids array has changed, and you have a second remove clause. Also, after removing the last kid, the loop will immediately exit, even if there are more kids left, simply because it doesn't set i=0 in the else for the end of the list.

In general, you should avoid using a for where you mess with the counter this much. A for is supposed to represent a single pass. What you're trying to accomplish is a round-robin, with in-place removals. In fact, your main mistake is the for's condition, since it's not iteration over the kids that you want, but rather looping until only one kid is left.

A cleaner implementation is hence:

int i = 0;
while (kids.size() > 1) { // Loop until we have a winner
    wordCount++; // Give the kid a word
    if (wordCount >= words) { // It's the last word, he's out
        rejects.add(kids.remove(i)); // Remove the kid at index i and place it into rejects
        // P.S. Small issue with ArrayList API: If your object type is Integer, then there's ambiguity between remove(T) and remove(int), which will prevent auto boxing from being used
        wordCount = 0; // And from the top
    }
    else {
        i++; // This kid is okay, move to the next
        // P.S. If we removed the kid, we're already pointing at the next one, hence the "else"
    }
    if (i >= kids.size()) { // Reached the end of the kids list
        i = 0; // Loop around
    }
}
SlugFiller
  • 1,596
  • 12
  • 12
  • 1
    You would need to reset `wordCount` at some point though, or check for `wordCount % words == 0` instead, otherwise after the first song has been completed, `wordCount >= words` is always true. – Siguza Apr 04 '15 at 14:08