Create a password generation program which will generate passwords containing random ASCII characters from the following groups:

         lower-case letters:  a ──► z
         upper-case letters:  A ──► Z
                     digits:  0 ──► 9
 other printable characters:  !"#$%&'()*+,-./:;<=>?@[]^_{|}~ 
 (the above character list excludes white-space, backslash and grave) 



The generated password(s) must include   at least one   (of each of the four groups):

   lower-case letter, 
   upper-case letter,
   digit  (numeral),   and 
   one  "other"  character. 



The user must be able to specify the password length and the number of passwords to generate.

The passwords should be displayed or written to a file, one per line.

The randomness should be from a system source or library.

The program should implement a help option or button which should describe the program and options when invoked.

You may also allow the user to specify a seed value, and give the option of excluding visually similar characters.

For example:            Il1     O0     5S     2Z            where the characters are:

   capital eye, lowercase ell, the digit one
   capital oh, the digit zero 
   the digit five, capital ess
   the digit two, capital zee


' Gambas module file
 
' INSTRUCTIONS
' I have not used a GUI as you could not run this in the 'Gambas Playground'
' Click on the link above to run this program
' The user can specify the password length and the number of passwords
' to generate by altering the values of the 2 lines below.
 
Public Sub Main()
Dim siPasswordLength As Short = 20                                      'Password length
Dim siPasswordQuantity As Short = 20                                    'Password quantity
Dim sLower As String = "abcdefghijklmnopqrstuvwxyz"                     'Lower case characters
Dim sUpper As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"                     'Upper case characters
Dim sNumber As String = "1234567890"                                    'Numbers
Dim sOther As String = "'!#$%&'()*+,-./:;<=>?@[]^_{|}~" & Chr(34)       'Other characters + quote
Dim sNoGo As String[] = ["I1", "1I", "l1", "1l", "Il", 
                        "lI", "O0", "0O", "S5", "5S", "Z2", "2Z"]       'Undesirable string combinations (can be added to if required)
Dim sData As String = sLower & sUpper & sNumber & sOther                'Create 1 string to pick the password characters from
Dim sToCheck, sPassword As String                                       'To hold a possible password for checking, to hold the passwords
Dim siCount, siLoop, siCounter As Short                                 'Various counters
Dim bPass As Boolean                                                    'To Pass or not to Pass!
 
For siCount = 1 To siPasswordQuantity                                   'Loop the amount of passwords required
  For siLoop = 1 To siPasswordLength                                    'Loop for each charater of the required length
    sToCheck &= Mid(sData, Rand(1, Len(sData)), 1)                      'Get a random character from sData
  Next
 
  bPass = False                                                         'Set bPass to False
  For siCounter = 1 To Len(sToCheck)                                    'Loop through each character in the generated password
    If InStr(sLower, Mid(sToCheck, siCounter, 1)) Then bPass = True     'If a LOWER CASE letter is included set bPass to True
  Next
 
  If bPass Then                                                         'If bPass is True then
    bPass = False                                                       'bPass is False
    For siCounter = 1 To Len(sToCheck)                                  'Loop through each character in the generated password
      If InStr(sUpper, Mid(sToCheck, siCounter, 1)) Then bPass = True   'If an UPPER CASE letter is included set bPass to True
    Next
  End If
 
  If bPass Then                                                         'If bPass is True then
    bPass = False                                                       'bPass is False
    For siCounter = 1 To Len(sToCheck)                                  'Loop through each character in the generated password
      If InStr(sNumber, Mid(sToCheck, siCounter, 1)) Then bPass = True  'If a NUMBER is included set bPass to True
    Next
  End If
 
  If bPass Then                                                         'If bPass is True then
    bPass = False                                                       'bPass is False
    For siCounter = 1 To Len(sToCheck)                                  'Loop through each character in the generated password
      If InStr(sOther, Mid(sToCheck, siCounter, 1)) Then bPass = True   'If an 'OTHER CHARACTER' is included set bPass to True
    Next
  End If
 
  If bPass Then
    For siCounter = 1 To sNoGo.Max                                      'Loop through each undesirable strings e.g. "0O"
      If InStr(sToCheck, sNoGo[siCounter]) Then bPass = False           'If an undesirable combination is located then set bPass to False
    Next
  Endif
 
  If bPass = True Then                                                  'If bPass is True (all checks have been passed) then
    sPassword &= sToCheck & gb.NewLine                                  'Add the new password to sPassword with a newline
  Else                                                                  'Else
    Dec siCount                                                         'Decrease the loop counter by one
  Endif
  sToCheck = ""                                                         'Clear sToCheck
Next
 
Print sPassword                                                         'Print the password list
 
End