I tested this Java program and it works:
import java.util.Random;
/** @author Daniel Trebbien */
// License: Public Domain
public class SO2965185 {
public static String randomFormat(final String templ) {
int i = templ.indexOf('{');
if (i < 0) {
return templ;
}
else {
Random r = new Random();
int prevI = 0;
StringBuilder sb = new StringBuilder();
do {
sb.append(templ, prevI, i);
int j = templ.indexOf('}', i + 1);
if (j < 0)
throw new java.util.MissingFormatArgumentException(templ.substring(i));
int pipeCount = 0;
for (int k = templ.indexOf('|', i + 1); i < k && k < j; k = templ.indexOf('|', k + 1))
++pipeCount;
if (pipeCount == 0) {
sb.append(templ, i + 1, j);
}
else {
String m0Selection;
final int m0 = r.nextInt(pipeCount + 1); // must pick one from each set
if (m0 >= pipeCount) {
m0Selection = templ.substring(templ.lastIndexOf('|', j - 1) + 1, j);
}
else {
int k = i + 1;
int m = m0;
for(; m > 0; --m)
k = templ.indexOf('|', k) + 1;
m0Selection = templ.substring(k, templ.indexOf('|', k + 1));
}
int selectionCount = 0;
for (int n = 0; n <= pipeCount; ++n) {
if (n == m0) {
if (selectionCount != 0)
sb.append(", ");
sb.append(m0Selection);
++selectionCount;
}
else if (r.nextBoolean()) {
int m = n;
if (selectionCount != 0)
sb.append(", ");
if (m >= pipeCount) {
sb.append(templ, templ.lastIndexOf('|', j - 1) + 1, j);
}
else {
int k = i + 1;
for(; m > 0; --m)
k = templ.indexOf('|', k) + 1;
sb.append(templ, k, templ.indexOf('|', k + 1));
}
++selectionCount;
}
}
}
prevI = j + 1;
i = templ.indexOf('{', j + 1);
} while(i >= 0);
return sb.toString();
}
}
public static void main(String[] args) {
System.out.println(randomFormat("test"));
System.out.println(randomFormat("{oneOption}"));
System.out.println(randomFormat("{first|second}"));
String s1 = "planets {Sun|Mercury|Venus|Earth|Mars|Jupiter|Saturn|Uranus|Neptune}{?|!|.}";
System.out.println(randomFormat(s1));
//System.out.println(randomFormat("jjj{test"));
}
}
This program prints something like:
test
oneOption
first, second
planets Sun, Mercury, Jupiter, Neptune?, !, .
and
test
oneOption
second
planets Sun, Jupiter, Saturn!, .
and
test
oneOption
first
planets Venus, Earth, Jupiter, Saturn, Uranus, Neptune.
You'll have to forgive the mess a little because I originally wrote code for a slightly different problem :)
The code picks random combinations of entries having at least one entry from each set. So, for a set with N entries, there are 2N - 1 combinations that can be generated. Also, keep in mind the probability that there are exactly M entries in the random combination:
P(exactly M entries in generated combination) = (N choose M) divided by (2N - 1)
Example: N = 9 ("{Sun|Mercury|Venus|Earth|Mars|Jupiter|Saturn|Uranus|Neptune}"
).
P(exactly 2 entries in generated combination) = 0.0704