I am trying to make a regex to matches all the binations of a given string. For example of the string is "1234", answers would include:
- "1"
- "123"
- "4321"
- "4312"
Nonexamples would include:
- "11"
- "11234"
- "44132"
If it matters, the programming language I am using is javascript.
Thank you for any help.
I am trying to make a regex to matches all the binations of a given string. For example of the string is "1234", answers would include:
- "1"
- "123"
- "4321"
- "4312"
Nonexamples would include:
- "11"
- "11234"
- "44132"
If it matters, the programming language I am using is javascript.
Thank you for any help.
Share asked Apr 17, 2018 at 15:50 Vishnu MurthyVishnu Murthy 511 silver badge8 bronze badges 5- 1 Regex is likely the wrong way to acplish whatever you're trying to do with that. – Herohtar Commented Apr 17, 2018 at 15:53
- What is a good way to acplish this? – Vishnu Murthy Commented Apr 17, 2018 at 15:53
- 2 Sort your candidate and pare to the original (assuming that the original is already sorted like in your example). – PM 77-1 Commented Apr 17, 2018 at 15:55
-
I see you're doing a simple
[1-4]+
– revo Commented Apr 17, 2018 at 15:57 - 1 @VishnuMurthy Did any of the responses answer your question? – Jason Cust Commented Apr 24, 2018 at 19:14
3 Answers
Reset to default 4You may use this lookahead based assertions in your regex:
^(?!(?:[^1]*1){2})(?!(?:[^2]*2){2})(?!(?:[^3]*3){2})(?!(?:[^4]*4){2})[1234]+$
RegEx Demo
Here we have 4 lookahead assertions:
(?!(?:[^1]*1){2})
: Assert that we don't have more than one instance of1
(?!(?:[^2]*2){2})
: Assert that we don't have more than one instance of2
(?!(?:[^3]*3){2})
: Assert that we don't have more than one instance of3
(?!(?:[^4]*4){2})
: Assert that we don't have more than one instance of4
We use [1234]+
to match any string with these 4 characters.
A bination of group captures using character classes and negative look-ahead assertions using back-references would do the trick.
Let's begin with simply matching any bination of 1, 2, 3, and 4 using a character class,[1-4]
, and allowing any length from 1 to 4 characters. {1,4}
.
const regex = /^[1-4]{1,4}$/;
// Create set of inputs from 0 to 4322
const inputs = Array.from(new Array(4323), (v, i) => i.toString());
// Output only values that match criteria
console.log(inputs.filter((input) => regex.test(input)));
When that code is run, it's easy to see that although only numbers consisting of some bination of 1, 2, 3, and 4 are matched, it also is matching numbers with repeating binations (e.g. 11, 22, 33, 112, etc). Obviously, this was not what was desired.
To prevent repeating characters requires a reference to previously matched characters and then a negation of them from any following matched characters. Negative look-aheads, (?!...)
using a back-reference, \1-9
, can acplish this.
Building on the previous example with a subset of the inputs (limiting to a max length of two characters for the moment) would now incorporate a group match surrounding the first character, ([1-4])
, followed by a negative look-ahead with a back-reference to the first capture, (?!\1)
, and finally a second optional character class.
const regex = /^([1-4])(?!\1)[1-4]?$/;
// Create set of inputs from 0 to 44
const inputs = Array.from(new Array(45), (v, i) => i.toString());
// Output only values that match criteria
console.log(inputs.filter((input) => regex.test(input)));
This matches the desired characters with no repetition!
Expanding this pattern to include back-references for each of the previously matched characters up to the desired max length of 4 yields the following expression.
const regex = /^([1-4])((?!\1)[1-4])?((?!\1|\2)[1-4])?((?!\1|\2|\3)[1-4])?$/;
// Create set of inputs from 0 to 4322
const inputs = Array.from(new Array(4323), (v, i) => i.toString());
// Output only values that match criteria
console.log(inputs.filter((input) => regex.test(input)));
Hope this helps!
You don't need to use regex for this. The snippet below does the following:
- Loop over possible binations (
a => s
) (1
,123
,4321
, etc.) - Copy the current bination so as not to overwrite it (
s2 = s
) - Loop over the characters of test string (
x => ch
) (1234
=>1
,2
,3
,4
) - Replace mon characters in the bination string shared with the test string (
s2.replace
)- For example in the bination
1
, the1
will be replaced when the loop gets to the character1
in1234
resulting in an empty string
- For example in the bination
- If the bination string's length reaches
0
(s2.length == 0
) write the result to the console and break out of the loop (no point in continuing to attempt to replace on an empty string)
const x = "1234"
const a = ["1","123","4321","4312","11","11234","44132"]
a.forEach(function(s) {
var s2 = s
for(var ch of x) {
s2 = s2.replace(ch, '')
if(s2.length == 0) {
console.log(s);
break;
}
}
})
Results:
1
123
4321
4312