I have a very ugly way to do this using regex.
It uses named capture groups (?<name>)
, back references \k<name>
, and negative lookahead assertions (?!)
.
@Test
public void testForNonRepeatedCharactersUsingRegex() {
Pattern p = Pattern.compile("^(?<c1>[a-zA-Z])(?!.*\\k<c1>)" +
"(?<c3>[a-zA-Z])(?!.*\\k<c3>)" +
"(?<c2>[a-zA-Z])(?!.*\\k<c2>)" +
"(?<c4>[a-zA-Z])(?!.*\\k<c4>)" +
"(?<c5>[a-zA-Z])(?!.*\\k<c5>)" +
"(?<c6>[a-zA-Z])(?!.*\\k<c6>)" +
"(?<c7>[a-zA-Z])(?!.*\\k<c7>)" +
".$");
Assertions.assertTrue(p.matcher("abcdefgh").matches());
Assertions.assertTrue(p.matcher("ABCDEFGH").matches());
Assertions.assertFalse(p.matcher("12345678").matches());
Assertions.assertFalse(p.matcher("abefgh").matches());
Assertions.assertFalse(p.matcher("").matches());
Assertions.assertFalse(p.matcher("abcdefga").matches());
Assertions.assertFalse(p.matcher("aaaabbbb").matches());
}
If you are able to not use regex, then a much cleaner, more legible solution is:
@Test
public void testForNonRepeatedCharactersUsingStreams() {
Assertions.assertTrue(uniqueCharacterSequence("abcdefgh", 8));
Assertions.assertTrue(uniqueCharacterSequence("ABCDEFGH", 8));
Assertions.assertFalse(uniqueCharacterSequence("12345678", 8));
Assertions.assertFalse(uniqueCharacterSequence("abefgh", 8));
Assertions.assertFalse(uniqueCharacterSequence("", 8));
Assertions.assertFalse(uniqueCharacterSequence("abcdefga", 8));
Assertions.assertFalse(uniqueCharacterSequence("aaaabbbb", 8));
}
private static boolean uniqueCharacterSequence(String s, int length) {
return s.length() == length &&
s.codePoints().allMatch(Character::isLetter) &&
s.codePoints().distinct().count() == length;
}