9

I have just started out on the regex part of python and I thought I understood this concept but when I started out the programming I wasn't able to get it. The problem statement which was given is to design a regex which

  1. It must contain at least 2 uppercase English alphabet characters
  2. It must contain at least 3 digits (0-9)
  3. it should only contain alphanumeric characters
  4. No characters should repeat
  5. There must be exactly 10 characters

The code which I wrote is

import re
n=int(input())
patt=r'^(?=.*[A-Z]).{2,}(?=.*[0-9]).{3,}(?=.*[\w]?){10}$'
for x in range(n):
    match=re.findall(patt,str(input()))
    #print(match)
    if match:
        print("Valid")
    else:
        print("Invalid")

I first started out with the 1st part i.e should contain "It must contain at least 2 uppercase English alphabet characters" for which I wrote (?=.*[A-Z]).{2,} as it will search for more than two characters and will use lookahead assertions For the second part I applied the same and for the third part i.e it should only contain alphanumeric characters I applied (?=.*[\w]?) these three seems to work but when the fourth and fifth condition comes i.e No characters should repeat and There must be exactly 10 characters I tried to use {10} at last but it didn't work and the whole thing seems to be broken now. Can anyone guide me how to use regex and what exactly is a positive lookahead.

Salman S
  • 47
  • 1
  • 15
Anidh Singh
  • 302
  • 2
  • 7
  • 19
  • No character should repeat means the no character anywhere in the string should match for example "B1CD102354" is an invalid string according to the above criteria because here 1 is repeating two times. – Anidh Singh Jul 16 '18 at 09:57
  • 1
    Did you ask the question from the HackerRank [Validating UID](https://www.hackerrank.com/challenges/validating-uid/problem) problem? – Ritam Chakraborty Aug 01 '20 at 10:39

4 Answers4

14

You may use this regex with 3 lookahead assertions, satisfying all your conditions:

^(?=(?:[a-z\d]*[A-Z]){2})(?=(?:\D*\d){3})(?:([a-zA-Z\d])(?!.*\1)){10}$

RegEx Demo

RegEx Description:

  • ^: Start
  • (?=(?:[a-z\d]*[A-Z]){2}): Lookahead to assert that we have at least 2 uppercase alphabets
  • (?=(?:\D*\d){3}): Lookahead to assert that we have at least 3 digits
  • (?:([a-zA-Z\d])(?!.*\1)){10}: Match exact 10 alphanumeric characters. Negative lookahead is to assert that we don't have anything repeating anywhere.
  • $: End

Read more about look aheads and look behinds

Code:

reg = re.compile(r'^(?=(?:[a-z\d]*[A-Z]){2})(?=(?:.*\d){3})(?:([a-zA-Z\d])(?!.*\1)){10}$')
arr = ['A1b2c3d4eF', 'B1CDEF2354', 'aBcDdef122', 'B1CD102354', 'a1bcf2coqb', 'a1bcf2oo3b', '1234567890']

for i in arr:
      print i, reg.match(i)
anubhava
  • 761,203
  • 64
  • 569
  • 643
2

no characters should repeat condition: regex to match a word with unique (non-repeating) characters

match exact number of characters condition: Regular expression to match exact number of characters?

the must contain condition: Regex must contain specific letters in any order

should contain only condition: it seems from the question you have already figured that out on your own.

The remaining job is to combine them all which you should do on your own if its part of an exercise given to you.

Ishan Srivastava
  • 1,129
  • 1
  • 11
  • 29
2
import re
n = int(input())
patt = r'^(?=(?:[a-z\d]*[A-Z]){2})(?=(?:\D*\d){3})(?:([a-zA-Z\d])(?!.*\1)){10}$'
for x in range(n):
    match=re.match(patt,str(input()))
    if match:
        print("Valid")
    else:
        print("Invalid")
Clemsang
  • 5,053
  • 3
  • 23
  • 41
Prasanth
  • 21
  • 1
  • While this code may answer the question, providing additional context regarding why and/or how this code answers the question improves its long-term value. – Donald Duck Dec 18 '20 at 11:11
0

Here is my solution to this question:

import re

for _ in range(int(input())):
    UID = input()
    try:
        assert re.fullmatch(r'[A-Za-z0-9]{10}',UID)
        assert re.fullmatch(r'([a-z0-9]*[A-Z]+[a-z0-9]*){2,}',UID)
        assert re.fullmatch(r'([a-zA-Z]*[0-9]+[a-zA-Z]*){3,}',UID)
        assert not(re.search(r'(.).*?\1',UID))
            
    except AssertionError:
        print('Invalid')
    else:
        print('Valid')
Meysiolio
  • 71
  • 1
  • 1
  • 7