Регулярное выражение для соответствия всем перестановкам {1,2,3,4} без повторения

Я реализую следующую задачу в рубине.

Вот шаблон, который мне нужен:

1234, 1324, 1432, 1423, 2341 и т. Д.

т.е. цифры в четырехзначном номере должны быть между [1–4] и также не должны повторяться.

чтобы вы поняли простым способом, я беру двузначный образец, и решение должно быть: 12, 21

т.е. цифры должны быть 1 или 2 и не должны повторяться.

Чтобы убедиться, что они не повторяются, я хочу использовать 1 доллар в качестве условия для моей второй цифры, но это не работает.

Пожалуйста, помогите мне и заранее спасибо.


person Apoorv Saxena    schedule 23.06.2010    source источник
comment
Без регулярных выражений: str.chars.sort.join == 1234   -  person Lars Haugseth    schedule 23.06.2010


Ответы (4)


Вы можете использовать это (см. На rubular.com):

^(?=[1-4]{4}$)(?!.*(.).*\1).*$

Первое утверждение гарантирует, что это ^[1-4]{4}$, второе утверждение - это отрицательный прогноз, который гарантирует, что вы не можете сопоставить .*(.).*\1, то есть повторяющийся символ. Первое утверждение «дешевле», поэтому вам нужно сделать это в первую очередь.

использованная литература

Связанные вопросы

person polygenelubricants    schedule 23.06.2010
comment
+1 ** Первое утверждение дешевле, поэтому сделайте это первым. ** - person Sławomir Lenart; 20.11.2013

Вот еще один вариант:

^(?:1()|2()|3()|4()){4}\1\2\3\4$

По мере использования каждого уникального символа следующая за ним группа захвата захватывает пустую строку. Обратные ссылки также пытаются сопоставить пустые строки, поэтому, если одна из них не удалась, это может означать только, что связанная группа не участвовала в сопоставлении. И это произойдет только в том случае, если строка содержит хотя бы один дубликат.

Такое поведение пустых групп захвата и обратных ссылок официально не поддерживается ни в одном варианте регулярных выражений, поэтому caveat emptor. Но это работает в большинстве из них, включая Ruby.

person Alan Moore    schedule 23.06.2010
comment
Я скопировал и вставил это выражение в gskinner.com/RegExr и попробовал текст 1244, и он совпал. Это не предотвращает дублирование. - person gsingh2011; 22.06.2012
comment
@ gsingh2011: RegExr - это приложение Flash, что означает, что оно использует разновидность ActionScript. А ActionScript реализует стандарт ECMAScript, который устанавливает, что обратная ссылка на группу, которая еще не участвовала в сопоставлении, всегда успешна, независимо от того, какой группе должна соответствовать группа. См. здесь для обсуждения. Этот трюк также не работает в JavaScript или VBScript, и он не работает в .NET, если вы укажете параметр ECMAScript, хотя он работает в противном случае. - person Alan Moore; 22.06.2012
comment
Спасибо за разъяснения. Это интересно. - person gsingh2011; 22.06.2012

Я думаю, что это решение немного проще

^(?:([1-4])(?!.*\1)){4}$

См. здесь, на Rubular

^                  # matches the start of the string
    (?:            # open a non capturing group 
        ([1-4])    # The characters that are allowed the found char is captured in group 1
        (?!.*\1)   # That character is matched only if it does not occur once more
    ){4}           # Defines the amount of characters
$

(?!.*\1) - это утверждение просмотра вперед, чтобы гарантировать, что символ не повторяется.

^ и $ - якоря, соответствующие началу и концу строки.

person stema    schedule 25.01.2013

Хотя предыдущие ответы решают проблему, они не такие общие, как могли бы, и не допускают повторений в исходной строке. Например, {a,a,b,b,c,c}. Задав аналогичный вопрос на Perl Monks, следующее решение предоставил Эйли:

^(?:(?!\1)a()|(?!\2)a()|(?!\3)b()|(?!\4)b()|(?!\5)c()|(?!\6)c()){6}$

Точно так же это работает для более длинных «символов» в строке, а также для символов переменной длины.

person Quantum Mechanic    schedule 22.11.2018