Task:

 Generate a string with   N   opening brackets   [   and with   N   closing brackets   ],   in some arbitrary order. 
 Determine whether the generated string is balanced; that is, whether it consists entirely of pairs of opening/closing brackets (in that order), none of which mis-nest.


Examples

   (empty)      OK
   []           OK   
   [][]         OK   
   [[][]]       OK 
   ][         NOT OK
   ][][       NOT OK
   []][[]     NOT OK



' Balanced brackets
PROGRAM "balancedbrackets"
VERSION "0.001"
 
IMPORT "xst"
 
DECLARE FUNCTION Entry()
INTERNAL FUNCTION IsStringBalanced(str$)
INTERNAL FUNCTION Generate$(n%%)
 
' Pseudo-random number generator
' Based on the rand, srand functions from Kernighan & Ritchie's book
' 'The C Programming Language'
DECLARE FUNCTION Rand()
DECLARE FUNCTION SRand(seed%%)
 
FUNCTION Entry()
  PRINT "Supplied examples"
  DIM tests$[6]
  tests$[0] = ""
  tests$[1] = "[]"
  tests$[2] = "]["
  tests$[3] = "[][]"
  tests$[4] = "][]["
  tests$[5] = "[[][]]"
  tests$[6] = "[]][[]"
  FOR example@@ = 0 TO UBOUND(tests$[])
    test$ = tests$[example@@]
    PRINT "The string '"; test$; "' is ";
    IFT IsStringBalanced(test$) THEN
      PRINT "OK."
    ELSE
      PRINT "not OK."
    END IF
  NEXT example@@
  PRINT
  PRINT "Random generated examples"
  XstGetSystemTime (@msec)
  SRand(INT(msec) MOD 32768)
  FOR example@@ = 1 TO 10
    test$ = Generate$(INT(Rand() / 32768.0 * 10.0) + 1)
    PRINT "The string '"; test$; "' is ";
    IFT IsStringBalanced(test$) THEN
      PRINT "OK."
    ELSE
      PRINT "not OK."
    END IF
  NEXT example@@
END FUNCTION
 
FUNCTION IsStringBalanced(s$)
  paired& = 0
  i%% = 1
  DO WHILE i%% <= LEN(s$) && paired& >= 0
    c$ = MID$(s$, i%%, 1)
    SELECT CASE c$
      CASE "[":
        INC paired&
      CASE "]":
        DEC paired&
    END SELECT
    INC i%%
  LOOP
END FUNCTION (paired& = 0)
 
FUNCTION Generate$(n%%)
  opensCount%% = 0
  closesCount%% = 0
  ' Choose at random until n%% of one type generated
  generated$ = ""
  DO WHILE opensCount%% < n%% && closesCount%% < n%%
    SELECT CASE (INT(Rand() / 32768.0 * 2.0) + 1)
      CASE 1:
        INC opensCount%%
        generated$ = generated$ + "["
      CASE 2:
        INC closesCount%%
        generated$ = generated$ + "]"
    END SELECT
  LOOP
  ' Now pad with the remaining other brackets
  IF opensCount%% = n%% THEN
    generated$ = generated$ + CHR$(']', n%% - closesCount%%)
  ELSE
    generated$ = generated$ + CHR$('[', n%% - opensCount%%)
  END IF
END FUNCTION generated$
 
' Return pseudo-random integer on 0..32767
FUNCTION Rand()
  #next&& = #next&& * 1103515245 + 12345
END FUNCTION USHORT(#next&& / 65536) MOD 32768
 
' Set seed for Rand()
FUNCTION SRand(seed%%)
  #next&& = seed%%
END FUNCTION
 
END PROGRAM
 