Sunnicus Sunnicus - 1 month ago 12
Java Question

How to randomly combine elements of 2 arrays while making sure to not reuse an element until all have been used at least once?

Essentially I'm writing a program that produces random poems out of an array of nouns and an array of adjectives.

This is accomplished basically using this line

String poem = adjectives[rand.nextInt(3)]+" "+ nouns[rand.nextInt(3)];


Simple enough, but I'm supposed to make sure that it doesn't reuse the same noun or adjective for the next poems until all of them have been used at least once already. I'm not sure how to do that.

Answer

Convert the arrays to list, so you can use Collections.shuffle to shuffle them. Once shuffled, you can then simply iterate over them. The values will be random order, and all words will be used exactly once. When you reach the end of an array of words, sort it again, and start from the beginning.

If a poem consists of 1 adjective + 1 noun as in your example, then the program could go something like this:

List<String> adjectives = new ArrayList<>(Arrays.asList(adjectivesArr));
List<String> nouns = new ArrayList<>(Arrays.asList(nounsArr));
Collections.shuffle(adjectives);
Collections.shuffle(nouns);

int aindex = 0;
int nindex = 0;

for (int i = 0; i < 100; ++i) {
    String poem = adjectives.get(aindex++) + " " + nouns.get(nindex++);
    System.out.println(poem);

    if (aindex == adjectives.size()) {
        aindex = 0;
        Collections.shuffle(adjectives);
    }
    if (nindex == nouns.size()) {
        nindex = 0;
        Collections.shuffle(nouns);
    }
}

The program will work with other number of adjectives and nouns per poem too.

If you must use an array, you can implement your own shuffle method, for example using the Fisher-Yates shuffle algorithm:

private void shuffle(String[] strings) {
    Random random = new Random();
    for (int i = strings.length - 1; i > 0; i--) {
        int index = random.nextInt(i + 1);
        String temp = strings[i];
        strings[i] = strings[index];
        strings[index] = temp;
    }
}

And then rewrite with arrays in terms of this helper shuffle function:

shuffle(adjectives);
shuffle(nouns);

int aindex = 0;
int nindex = 0;

for (int i = 0; i < 100; ++i) {
    String poem = adjectives[aindex++] + " " + nouns[nindex++];
    System.out.println(poem);

    if (aindex == adjectives.length) {
        aindex = 0;
        shuffle(adjectives);
    }
    if (nindex == nouns.length) {
        nindex = 0;
        shuffle(nouns);
    }
}