-2

I want to generate a random String from 9 always separating 3 String with "-"

It must give this at the end: XXX-XXX-XXX

So far I have managed to create a Random of 9 but I don't know how to do the rest

map.put("referCode", getRandomCode(9));
public static String getRandomCode(int i) {
    final String characters = "ABCDEFGHIJKLMONPQRSTUVWXYZ0123456789";
    StringBuilder result = new StringBuilder();
    while (i > 0) {
        Random random = new Random(); 
        result.append(characters.charAt(random.nextInt(characters.length())));
        i++;
    }
    return result.toString();
}
Omar Shawky
  • 1,242
  • 1
  • 12
  • 25
arma
  • 71
  • 5

6 Answers6

2

In addition to the given answers it may be possible to use regular expressions to insert a separator/delimiter between each N characters:

  • using String::replaceAll:
System.out.println(random.replaceAll("(.{3})(?!$)", "$1-"));

Here negative lookahead is used to detect the end of the string (?!$).

System.out.println(String.join("-", random.split("(?<=\\G.{3})")));

For the given "random" string:

for (String random : Arrays.asList("12345678", "ABCDEF123456")) {
    System.out.println(random.replaceAll("(.{3})(?!$)", "$1-"));
  
    System.out.println(String.join("-", random.split("(?<=\\G.{3})")));
}

The output is as follows:

123-456-78
123-456-78
ABC-DEF-123-456
ABC-DEF-123-456
Nowhere Man
  • 19,170
  • 9
  • 17
  • 42
1

You can do something like this:

private static final String CHARACTERS = "ABCDEFGHIJKLMONPQRSTUVWXYZ0123456789";
public static String getRandomCode() {
    StringBuilder result = new StringBuilder();
    Random random = new Random(); 
    for (int i = 0; i < 9; i++) {
        result.append(CHARACTERS.charAt(random.nextInt(CHARACTERS.length())));
        if (i == 2 || i == 5)
            resault.append('-');
    }
    return result.toString();
}

Another option will be to use what you already wrote and do this:

String code = getRandomCode(9);
code = code.substring(0,3) + '-' + code.substring(3,6) + '-' + code.substring(6,9);

for more general case, you can use this:

private static final String CHARACTERS = "ABCDEFGHIJKLMONPQRSTUVWXYZ0123456789";
public static String getRandomCode(int segmentLength, int segmentAmount) {
    StringBuilder result = new StringBuilder();
    Random random = new Random(); 
    for (int i = 0; i < segmentAmount; i++) {
        if (i != 0)
            resault.append('-');
        for (int j = 0; j < segmentLength; j++)
            result.append(CHARACTERS.charAt(random.nextInt(CHARACTERS.length())));
    }
    return result.toString();
}
Ofek
  • 1,065
  • 6
  • 19
  • 1
    Placing the `new Random()` outside the loop it's a good practice, it can even be outside the function itself (final variable) – Roger Miranda Perez Oct 04 '21 at 21:25
  • Algorithm is good when it works for different values, not only one set of them. What if random code should be 12 or more length (this should be decided outside of method)? – MrFisherman Oct 04 '21 at 21:28
1
String randomString = result.toString();
String firstSegment = randomString.substring(0, 3);
String secondSegment = randomString.substring(3, 6);
String thirdSegment = randomString.substring(6, 10);

String finalResult = firstSegment + "-" + secondSegment + "-" + thirdSegment;

return finalResult;
JonR85
  • 700
  • 4
  • 12
1

Here you are, this algorithm is universal. It will work for every value, not only for 9 characters.

public class Algorithm {

    private static final String CHARACTERS = "ABCDEFGHIJKLMONPQRSTUVWXYZ0123456789";
    
    public static void main(String[] args) {
        System.out.println(getRandomCode(9));
        System.out.println(getRandomCode(12));
        System.out.println(getRandomCode(15));
        System.out.println(getRandomCode(50));
    }
 
    public static String getRandomCode(int numberOfCharacters) {
        StringBuilder result = new StringBuilder();
        Random random = new Random();
        for (int index = 1; index <= numberOfCharacters; index++) {
            result.append(CHARACTERS.charAt(random.nextInt(CHARACTERS.length())));
            if (index % 3 == 0 && index != numberOfCharacters) {
                result.append("-");
            }
        }
        return result.toString();
    }
} 

It will print:

8PJ-Y6T-4LV
FE7-WRY-64A-2L2
23H-A24-CBF-E8Z-NHD
DXA-8Z3-DB4-2ZS-U2O-SQS-CAR-Y5Z-UXT-AP9-3TI-9ZO-D7T-OMZ-RDN-K34-BB

Also if you want to try the same with while loop you can first split string by 3, add results to the list and then join them with String.join:

public static String getRandomCode(int numberOfCharacters) {

        List<String> results = new ArrayList<>();
        StringBuilder result = new StringBuilder();
        Random random = new Random();
        
        int index = 0;
        int prevIndex = 0;
       
        while (index < numberOfCharacters) {
            index++;
            result.append(CHARACTERS.charAt(random.nextInt(CHARACTERS.length())));
            if (index % 3 == 0) {
                results.add(result.substring(prevIndex, index));
                prevIndex = index;
            }
        }
        return String.join("-", results);
    }

And if you want to be super elastic you can also parametrize split point, so not only by 3, but also any other value:

private static final String CHARACTERS = "ABCDEFGHIJKLMONPQRSTUVWXYZ0123456789";

    public static void main(String[] args) {
        System.out.println(getRandomCode(9,3));
        System.out.println(getRandomCode(12,4));
        System.out.println(getRandomCode(15,5));
        System.out.println(getRandomCode(150,50));
    }

    public static String getRandomCode(int numberOfCharacters, int splitPointIndex) {

        List<String> results = new ArrayList<>();
        StringBuilder result = new StringBuilder();
        Random random = new Random();

        int index = 0;
        int prevIndex = 0;

        while (index < numberOfCharacters) {
            index++;
            result.append(CHARACTERS.charAt(random.nextInt(CHARACTERS.length())));
            if (index % splitPointIndex == 0) {
                results.add(result.substring(prevIndex, index));
                prevIndex = index;
            }
        }
        return String.join("-", results);
    }

It will print:

HBZ-BWT-MYI
7YSM-DD0K-HJYF
EUQ2P-NFJ4F-L4MRP
MG91WG9F9HF1GM0UH6I91VX7TLNIUDPQUCUK8SXDQ3T087JPAE-JJ6IZHKH2YBZBJKPPHJFR43112JKQDBJ9LSTAA7BTB6O3JXTYX-EGCJBGWJBZJOGBMVCH9TLCL9VSV3L15JR7QZIKIKOZGAOKR6GT

Cheers!

MrFisherman
  • 720
  • 1
  • 7
  • 27
0

Try this.

static final String CHARACTERS = "ABCDEFGHIJKLMONPQRSTUVWXYZ0123456789";

public static String getRandomCode(int i) {
    return new Random().ints(i, 0, CHARACTERS.length())
        .mapToObj(r -> String.valueOf(CHARACTERS.charAt(r)))
        .collect(Collectors.joining())
        .replaceAll(".{3}(?!$)", "$0-");
}

public static void main(String[] args) {
    System.out.println(getRandomCode(9));
    System.out.println(getRandomCode(10));
}

output:

MHC-ELK-44H
9X8-L2P-UMD-L
0

Strategy for generating a random char [A-Z] used in all these solutions:

private static char rnd() {
    return (char) ('A' + ThreadLocalRandom.current().nextInt('Z'-'A' + 1));
}

Anyway, if it's always going to have a length of nine, then I wouldn't overthink it:

public static String gen() {
    return String.format("%s-%s-%s", triplet(), triplet(), triplet());
}

private static String triplet() {
    return String.format("%c%c%c", rnd(), rnd(), rnd());
}

If it needs to scale depending on input, here's one of the many possible dynamic solutions:

public static String gen(int len) {
    if(len < 1)
        return "";  
    final char[] out = new char[len + ((len-1)/3)];
    fill(out, 0);
    return new String(out);
}

private static void fill(char[] chars, int idx) {
    if(idx > (chars.length - 1))
        return;
    chars[idx] = ((idx+1)%4==0) ? '-' : rnd();
    fill(chars, idx+1);
}

There's also this variant which is a bit less efficient because it creates a new String each time, but I like it because it's immutable:

public static String gen(final int len) {
    if(len < 1)
        return "";
    return gen("", 0, (len + ((len-1)/3)));
    
}

private static String gen(final String out, final int idx, final int max) {
    if(idx >= max)
        return out;
    return gen(out + (((idx+1)%4==0) ? '-' : rnd()), idx+1, max);
}
PPartisan
  • 8,173
  • 4
  • 29
  • 48