With some reasonable limitations, this can be done quite easily with regular expressions.
Assuming that \n is an illegal part of the password (VERY reasonable restriction), the following code will make the check readable enough (if you know how to read the regular expression):
static boolean legalChange(String before, String after) { String joined = String.format("%s\n%s", before, after); return !joined.matches(".*(.{4}).*\n.*\\1.*"); }
Here's the test harness ( see also at ideone.com ):
String[][] tests = { { "abcdef", "ghijklm" }, // true { "abcdef", "xbcdeyz" }, // false { "abcdef", "fedbcda" }, // true { "xyz", "" }, // true { "0123456789", "abc123def456ghi" }, // true { "0123456789", "abc123456ghi" }, // false }; for (String[] test : tests) { System.out.println(legalChange(test[0], test[1])); }
Note that this regular expression only checks the rule "there is no common substring of length 4". Additional regex rules should also be in place.
How it works
Essentially, we concatenate two lines into one, separated by the \n character (which is in any case an illegal character that has names in usernames).
This regular expression will match the ILLEGAL change:
before | after ie before = .* (.{4}) .* | after = .* \1 .* .*(.{4}).*\n.*\1.* \____/ 1
That is, we map and remove (.{4}) from before to group 1 and use the backlink \1 to see if it can be matched in after . We put .* Around the two so that the origin takes place anywhere. The regex engine will do all the necessary countdowns on .* To see if this pattern can fit.
Since this pattern corresponds to an unalloyed change, we deny the result of matches using the addition operator boolean ! .
This is not the most effective solution to the problem, but assuming the passwords are of a reasonable length, speed will not be a problem.
References