There are two clear requirements in your problem:
- Randomness: Generate random account number with a specific pattern
- Uniqueness: Ensure new account number is unique (not yet used)
While a real life application will certainly delegate part of the job to a database, here is a simple solution in pure python with minimal complexity:
import random
class Bank:
def __init__(self):
self.accounts = set()
@staticmethod
def get_random_account():
prefix = random.randint(10, 99)
number = random.randint(1e9, 1e10 - 1)
check = int((prefix * 1e10) + number) % 97
return f"{prefix:0>2d}-{number:0>10d}-{check:0>2d}"
def create_account(self):
while True:
account = self.get_random_account()
if account not in self.accounts:
self.accounts.add(account)
return account
I fix the random seed to a known value in order to make the MCVE reproducible:
random.seed(123) # Comment this line for more randomness
We create a Bank object that will be in charge for both operations: random account generation (static method) and unique account number creation (created account storage).
my_bank = Bank()
You can always create a random account without checking it is unique (not already issued):
my_bank.get_random_account() # '16-2149664691-72'
Then we can issue 10 account numbers that are guaranteed to be unique among this bank instance:
for _ in range(10):
account = my_bank.create_account()
print(account)
# 62-2144839923-10
# 14-7710107789-37
# 53-4659684175-93
# 30-5875034668-84
# 81-2052968588-52
# 10-9185802068-43
# 21-2621757232-66
# 10-2925527091-15
# 15-9988355352-16
# 28-4893851635-83
If we check the accounts
attribute of the instance we can confirm those issued account are stored in the set to allow uniqueness assessment:
my_bank.accounts
# {'10-2925527091-15',
# '10-9185802068-43',
# '14-7710107789-37',
# '15-9988355352-16',
# '21-2621757232-66',
# '28-4893851635-83',
# '30-5875034668-84',
# '53-4659684175-93',
# '62-2144839923-10',
# '81-2052968588-52'}
When using a set
the order of issued accounts is not preserved. Insertion order was ignored as it was not part of the requirements. Anyway changing set
for a dict
is easy an can both be used to preserve creation order (since 3.7+) and store a randomly generated PIN number as well. Let's do it:
class Bank:
def __init__(self):
self.accounts = dict()
@staticmethod
def get_random_account():
prefix = random.randint(10, 99)
number = random.randint(1e9, 1e10 - 1)
check = int((prefix * 1e10) + number) % 97
return f"{prefix:0>2d}-{number:0>10d}-{check:0>2d}"
def create_account(self):
while True:
account = self.get_random_account()
if account not in self.accounts:
self.accounts[account] = {"pin": "{:0>4}".format(random.randint(0, 9999))}
return account
Then our ten accounts would look like:
# {'62-2144839923-10': {'pin': '0625'},
# '58-6721745545-12': {'pin': '0850'},
# '30-5875034668-84': {'pin': '9190'},
# '52-4013734705-55': {'pin': '2683'},
# '10-9185802068-43': {'pin': '1435'},
# '86-2621757232-50': {'pin': '0108'},
# '50-8439051955-85': {'pin': '1671'},
# '15-9988355352-16': {'pin': '2329'},
# '26-5386175109-56': {'pin': '7055'},
# '83-7343337636-62': {'pin': '7688'}}