A word made up of 4 different letters using regular expressions?

For example, revaluations will match. It contains exactly 4 different characters: 'r', 'e', ​​'a' and 's'.

My attempt: /^([az])([az])([az])([az])(\1|\2|\3|\4)(\1|\2|\3|\4)(\1|\2|\3|\4)$/ (add as many (\1|\2|\3|\4) as needed to match the word length)

However, this will only correspond to 4 different letters, and only if they are the first 4 characters.

Is there a better solution?

+6
source share
4 answers

Something like that:

 ^([az])\1*+([az])(?:\1|\2)*+([az])(?:\1|\2|\3)*+([az])(?:\1|\2|\3|\4)*$ 

The use of possessive quantifiers is important in this pattern because it prohibits backtracking and avoids the fact that the next capture group matches the letter that was found.

An attractive quantifier function is available in Java (don’t forget to double backlinks), but if you need to use a template in a language that does not have this function, you can find several options to “translate” the template in my comment.

The above template is built to validate an entire line, but if you want to find words in a larger line, you can use this (over time case-insensitive option):

 (?<![az])([az])\1*+([az])(?:\1|\2)*+([az])(?:\1|\2|\3)*+([az])(?:\1|\2|\3|\4)*(?![az]) 
+1
source

Try

 ^([az])\1*([az])(\1*\2*)*([az])(\1*\2*\4*)*([az])(\1*\2*\4*\6*)*$ 

Change so that there are no less than 4 unique ones (for example, aaaa):

 ^([az])\1*(?!\1)([az])(\1*\2*)*(?!\1)(?!\2)([az])(\1*\2*\4*)*(?!\1)(?!\2)(?!\4)([az])(\1*\2*\4*\6*)*$ 
+1
source

Specific work -
This should result in an alignment that consists of only 4 different char of string> = 4 in length.

  # ^(?=.*(.).*(?!\1)(.).*(?!\1|\2)(.).*(?!\1|\2|\3)(.))(?:\1|\2|\3|\4)+$ ^ (?= .* ( . ) .* (?! \1 ) ( . ) .* (?! \1 | \2 ) ( . ) .* (?! \1 | \2 | \3 ) ( . ) ) (?: \1 | \2 | \3 | \4 )+ $ 

Perl Test:

 if ("upepipipeu" =~ /^(?=.*(.).*(?!\1)(.).*(?!\1|\2)(.).*(?!\1|\2|\3)(.))(?:\1|\2|\3|\4)+$/) { print "unique chars: '$1' '$2' '$3' '$4'\n"; print "matched: '$&'\n"; } 

Exit →

 unique chars: 'i' 'p' 'e' 'u' matched: 'upepipipeu' 

Test code for @aliteralmind:

 @Ary = ("aabbccdd", "dictionary", "reassess", "aaaa"); for( @Ary ) { if ("$_" =~ /^(?=.*(.).*(?!\1)(.).*(?!\1|\2)(.).*(?!\1|\2|\3)(.))(?:\1|\2|\3|\4)+$/) { print "unique chars: '$1' '$2' '$3' '$4'\n"; print "matched: '$&'\n\n"; } else { print "Failed-> '$_'\n\n"; } } 

Exit →

 unique chars: 'a' 'b' 'c' 'd' matched: 'aabbccdd' Failed-> 'dictionary' unique chars: 'r' 'a' 'e' 's' matched: 'reassess' Failed-> 'aaaa' 
+1
source

Regarding regular expression, it's a brain buster. Below is a solution without regular expressions. A function that uses a map to track unique characters and returns true when the maximum number of unique characters is reached.

 import java.util.Map; import java.util.TreeMap; /** <P>{@code java ExactlyFourDiffChars}</P> **/ public class ExactlyFourDiffChars { public static final void main(String[] ignored) { System.out.println("aabbccdd: " + hasMoreThanXUniqueChars(4, "aabbccdd")); System.out.println("dictionary: " + hasMoreThanXUniqueChars(4, "dictionary")); System.out.println("reassesses: " + hasMoreThanXUniqueChars(4, "reassesses")); } public static final boolean hasMoreThanXUniqueChars(int maxAllowedChars, String str) { Map<Character,Object> charMap = new TreeMap<Character,Object>(); for(int i = 0; i < str.length(); i++) { Character C = str.charAt(i); if(!charMap.containsKey(C)) { charMap.put(C, null); if(maxAllowedChars-- == 0) { return false; } } } return true; } } 

Output:

 [C:\java_code\]java ExactlyFourDiffChars aabbccdd: true dictionary: false reassesses : true 
0
source

All Articles