Imports System.Text

Module Module1
    Sub Main()
        Dim a As New BalancedTernary("+-0++0+")
        Console.WriteLine("a: {0} = {1}", a, a.ToLong)
        Dim b As New BalancedTernary(-436)
        Console.WriteLine("b: {0} = {1}", b, b.ToLong)
        Dim c As New BalancedTernary("+-++-")
        Console.WriteLine("c: {0} = {1}", c, c.ToLong)
        Dim d = a * (b - c)
        Console.WriteLine("a * (b - c): {0} = {1}", d, d.ToLong)
    End Sub

    Class BalancedTernary
        Private Enum BalancedTernaryDigit
            MINUS = -1
            ZERO = 0
            PLUS = 1
        End Enum

        Private ReadOnly value() As BalancedTernaryDigit

        ' empty = 0
        Public Sub New()
            ReDim value(-1)
        End Sub

        ' create from string
        Public Sub New(str As String)
            ReDim value(str.Length - 1)
            For i = 1 To str.Length
                If str(i - 1) = "-" Then
                    value(i - 1) = BalancedTernaryDigit.MINUS
                ElseIf str(i - 1) = "0" Then
                    value(i - 1) = BalancedTernaryDigit.ZERO
                ElseIf str(i - 1) = "+" Then
                    value(i - 1) = BalancedTernaryDigit.PLUS
                Else
                    Throw New ArgumentException("Unknown Digit: " + str(i - 1))
                End If
            Next
            Array.Reverse(value)
        End Sub

        ' convert integer
        Public Sub New(l As Long)
            Dim value As New List(Of BalancedTernaryDigit)
            Dim sign = Math.Sign(l)
            l = Math.Abs(l)

            While l <> 0
                Dim remainder = CType(l Mod 3, Byte)
                If remainder = 0 OrElse remainder = 1 Then
                    value.Add(remainder)
                    l /= 3
                ElseIf remainder = 2 Then
                    value.Add(BalancedTernaryDigit.MINUS)
                    l = (l + 1) / 3
                End If
            End While

            Me.value = value.ToArray
            If sign < 0 Then
                Invert()
            End If
        End Sub

        ' copy constructor
        Public Sub New(origin As BalancedTernary)
            ReDim value(origin.value.Length - 1)
            Array.Copy(origin.value, value, origin.value.Length)
        End Sub

        ' only for internal use
        Private Sub New(value() As BalancedTernaryDigit)
            Dim endi = value.Length - 1
            While endi > 0 AndAlso value(endi) = BalancedTernaryDigit.ZERO
                endi -= 1
            End While
            ReDim Me.value(endi)
            Array.Copy(value, Me.value, endi + 1)
        End Sub

        ' invert the values
        Private Sub Invert()
            For i = 1 To value.Length
                value(i - 1) = CType(-CType(value(i - 1), Integer), BalancedTernaryDigit)
            Next
        End Sub

        ' convert to string
        Public Overrides Function ToString() As String
            Dim result As New StringBuilder
            Dim i = value.Length - 1
            While i >= 0
                If value(i) = BalancedTernaryDigit.MINUS Then
                    result.Append("-")
                ElseIf value(i) = BalancedTernaryDigit.ZERO Then
                    result.Append("0")
                ElseIf value(i) = BalancedTernaryDigit.PLUS Then
                    result.Append("+")
                End If

                i -= 1
            End While
            Return result.ToString
        End Function

        ' convert to long
        Public Function ToLong() As Long
            Dim result = 0L
            For i = 1 To value.Length
                result += value(i - 1) * Math.Pow(3.0, i - 1)
            Next
            Return result
        End Function

        ' unary minus
        Public Shared Operator -(origin As BalancedTernary) As BalancedTernary
            Dim result As New BalancedTernary(origin)
            result.Invert()
            Return result
        End Operator

        ' addition of digits
        Private Shared carry = BalancedTernaryDigit.ZERO
        Private Shared Function Add(a As BalancedTernaryDigit, b As BalancedTernaryDigit) As BalancedTernaryDigit
            If a <> b Then
                carry = BalancedTernaryDigit.ZERO
                Return a + b
            Else
                carry = a
                Return -CType(b, Integer)
            End If
        End Function

        ' addition of balanced ternary numbers
        Public Shared Operator +(a As BalancedTernary, b As BalancedTernary) As BalancedTernary
            Dim maxLength = Math.Max(a.value.Length, b.value.Length)
            Dim resultValue(maxLength) As BalancedTernaryDigit
            For i = 1 To maxLength
                If i - 1 < a.value.Length Then
                    resultValue(i - 1) = Add(resultValue(i - 1), a.value(i - 1))
                    resultValue(i) = carry
                Else
                    carry = BalancedTernaryDigit.ZERO
                End If

                If i - 1 < b.value.Length Then
                    resultValue(i - 1) = Add(resultValue(i - 1), b.value(i - 1))
                    resultValue(i) = Add(resultValue(i), carry)
                End If
            Next
            Return New BalancedTernary(resultValue)
        End Operator

        ' subtraction of balanced ternary numbers
        Public Shared Operator -(a As BalancedTernary, b As BalancedTernary) As BalancedTernary
            Return a + (-b)
        End Operator

        ' multiplication of balanced ternary numbers
        Public Shared Operator *(a As BalancedTernary, b As BalancedTernary) As BalancedTernary
            Dim longValue = a.value
            Dim shortValue = b.value
            Dim result As New BalancedTernary

            If a.value.Length < b.value.Length Then
                longValue = b.value
                shortValue = a.value
            End If

            For i = 1 To shortValue.Length
                If shortValue(i - 1) <> BalancedTernaryDigit.ZERO Then
                    Dim temp(i + longValue.Length - 2) As BalancedTernaryDigit
                    For j = 1 To longValue.Length
                        temp(i + j - 2) = CType(shortValue(i - 1) * longValue(j - 1), BalancedTernaryDigit)
                    Next
                    result += New BalancedTernary(temp)
                End If
            Next

            Return result
        End Operator
    End Class

End Module


import "/big" for BigInt
import "/trait" for Comparable

class BTernary is Comparable {
    toBT_(v) {
        if (v < BigInt.zero) return flip_(toBT_(-v))
        if (v == BigInt.zero) return ""
        var rem = mod3_(v)
        return (rem == BigInt.zero) ? toBT_(v/BigInt.three) + "0" :
               (rem == BigInt.one)  ? toBT_(v/BigInt.three) + "+" :
                       toBT_((v + BigInt.one)/BigInt.three) + "-"
    }

    flip_(s) {
        var sb = ""
        for (c in s) {
            sb = sb + ((c == "+") ? "-" : (c == "-") ? "+" : "0")
        }
        return sb
    }

    mod3_(v) {
        if (v > BigInt.zero) return v % BigInt.three
        return ((v % BigInt.three) + BigInt.three) % BigInt.three
    }

    addDigits2_(a, b) {
        return (a == "0") ? b :
               (b == "0") ? a :
               (a == "+") ? ((b == "+") ? "+-" : "0") :
                             (b == "+") ? "0" : "-+"
    }

    addDigits3_(a, b, carry) {
        var sum1 = addDigits2_(a, b)
        var sum2 = addDigits2_(sum1[-1], carry)
        return (sum1.count == 1) ? sum2 : (sum2.count == 1) ? sum1[0] + sum2 : sum1[0]
    }

    construct new(value) {
        if (value is String && value.all { |c| "0+-".contains(c) }) {
            _value = value.trimStart("0")
        } else if (value is BigInt) {
            _value = toBT_(value)
        } else if (value is Num && value.isInteger) {
            _value = toBT_(BigInt.new(value))
        } else {
            Fiber.abort("Invalid argument.")
        }
    }

    value { _value }

    +(other) {
        var a = _value
        var b = other.value
        var longer = (a.count > b.count) ? a : b
        var shorter = (a.count > b.count) ? b : a
        while (shorter.count < longer.count) shorter = "0" + shorter
        a = longer
        b = shorter
        var carry = "0"
        var sum = ""
        for (i in 0...a.count) {
            var place = a.count - i - 1
            var digisum = addDigits3_(a[place], b[place], carry)
            carry = (digisum.count != 1) ? digisum[0] : "0"
            sum = digisum[-1] + sum
        }
        sum = carry + sum
        return BTernary.new(sum)
    }

    - { BTernary.new(flip_(_value)) }

    -(other) { this + (-other) }

    *(other) {
        var that = other.clone()
        var one = BTernary.new(1)
        var zero = BTernary.new(0)
        var mul = zero
        var flipFlag = false
        if (that < zero) {
            that = -that
            flipFlag = true
        }
        var i = one
        while (i <= that) {
            mul = mul + this
            i = i + one
        }
        if (flipFlag) mul = -mul
        return mul
    }

    toBigInt {
        var len = _value.count
        var sum = BigInt.zero
        var pow = BigInt.one
        for (i in 0...len) {
            var c = _value[len-i-1]
            var dig = (c == "+") ? BigInt.one : (c == "-") ? BigInt.minusOne : BigInt.zero
            if (dig != BigInt.zero) sum = sum + dig*pow
            pow = pow * BigInt.three
        }
        return sum
    }

    compare(other) { this.toBigInt.compare(other.toBigInt) }

    clone() { BTernary.new(_value) }

    toString { _value }
}

var a = BTernary.new("+-0++0+")
var b = BTernary.new(-436)
var c = BTernary.new("+-++-")
System.print("a = %(a.toBigInt)")
System.print("b = %(b.toBigInt)")
System.print("c = %(c.toBigInt)")
var bResult = a * (b - c)
var iResult = bResult.toBigInt
System.print("a * (b - c) = %(bResult) = %(iResult)")


F gen(n)
   V txt = [‘[’, ‘]’] * n
   random:shuffle(&txt)
   R txt.join(‘’)

F is_balanced(s)
   V nesting_level = 0
   L(c) s
      S c
         ‘[’
            nesting_level++
         ‘]’
            I --nesting_level < 0
               R 0B
   R 1B

L(n) 0..9
   V s = gen(n)
   print(s‘’(‘ ’ * (20 - s.len))‘is ’(I is_balanced(s) {‘balanced’} E ‘not balanced’))


*        Balanced brackets         28/04/2016
BALANCE  CSECT
         USING  BALANCE,R13        base register and savearea pointer
SAVEAREA B      STM-SAVEAREA(R15)
         DC     17F'0'
STM      STM    R14,R12,12(R13)
         ST     R13,4(R15)
         ST     R15,8(R13)
         LR     R13,R15            establish addressability
         LA     R8,1               i=1
LOOPI    C      R8,=F'20'          do i=1 to 20
         BH     ELOOPI
         MVC    C(20),=CL20' '     c=' '
         LA     R1,1
         LA     R2,10
         BAL    R14,RANDOMX
         LR     R11,R0             l=randomx(1,10)
         SLA    R11,1              l=l*2
         LA     R10,1              j=1
LOOPJ    CR     R10,R11            do j=1 to 2*l
         BH     ELOOPJ
         LA     R1,0
         LA     R2,1
         BAL    R14,RANDOMX
         LR     R12,R0             m=randomx(0,1)
         LTR    R12,R12            if m=0
         BNZ    ELSEM
         MVI    Q,C'['             q='['
         B      EIFM
ELSEM    MVI    Q,C']'             q=']'
EIFM     LA     R14,C-1(R10)       @c(j)
         MVC    0(1,R14),Q         c(j)=q
         LA     R10,1(R10)         j=j+1
         B      LOOPJ
ELOOPJ   BAL    R14,CHECKBAL
         LR     R2,R0
         C      R2,=F'1'           if checkbal=1
         BNE    ELSEC
         MVC    PG+24(2),=C'ok'    rep='ok'
         B      EIFC
ELSEC    MVC    PG+24(2),=C'? '    rep='? '
EIFC     XDECO  R8,XDEC            i
         MVC    PG+0(2),XDEC+10
         MVC    PG+3(20),C
         XPRNT  PG,26
         LA     R8,1(R8)           i=i+1
         B      LOOPI
ELOOPI   L      R13,4(0,R13)
         LM     R14,R12,12(R13)
         XR     R15,R15            set return code to 0
         BR     R14 -------------- end
CHECKBAL CNOP   0,4 -------------- checkbal
         SR     R6,R6              n=0
         LA     R7,1               k=1
LOOPK    C      R7,=F'20'          do k=1 to 20
         BH     ELOOPK
         LR     R1,R7              k
         LA     R4,C-1(R1)         @c(k)
         MVC    CI(1),0(R4)        ci=c(k)
         CLI    CI,C'['            if ci='['
         BNE    NOT1
         LA     R6,1(R6)           n=n+1
NOT1     CLI    CI,C']'            if ci=']'
         BNE    NOT2
         BCTR   R6,0               n=n-1
NOT2     LTR    R6,R6              if n<0
         BNM    NSUP0
         SR     R0,R0              return(0)
         B      RETCHECK
NSUP0    LA     R7,1(R7)           k=k+1
         B      LOOPK
ELOOPK   LTR    R6,R6              if n=0
         BNZ    ELSEN
         LA     R0,1               return(1)
         B      RETCHECK
ELSEN    SR     R0,R0              return(0)
RETCHECK BR     R14 -------------- end checkbal
RANDOMX  CNOP   0,4 -------------- randomx
         LR     R3,R2              i2
         SR     R3,R1              ii=i2-i1
         L      R5,SEED
         M      R4,=F'1103515245'
         A      R5,=F'12345'
         SRDL   R4,1               shift to improve the algorithm
         ST     R5,SEED            seed=(seed*1103515245+12345)>>1
         LR     R6,R3              ii
         LA     R6,1(R6)           ii+1
         L      R5,SEED            seed
         LA     R4,0               clear
         DR     R4,R6              seed//(ii+1)
         AR     R4,R1              +i1
         LR     R0,R4              return(seed//(ii+1)+i1)
         BR     R14 -------------- end randomx
SEED     DC     F'903313037'
C        DS     20CL1
Q        DS     CL1
CI       DS     CL1
PG       DC     CL80' '
XDEC     DS     CL12
         REGS
         END    BALANCE


CLASS lcl_balanced_brackets DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS:
      class_constructor,

      are_brackets_balanced
        IMPORTING
          seq                            TYPE string
        RETURNING
          VALUE(r_are_brackets_balanced) TYPE abap_bool,

      get_random_brackets_seq
        IMPORTING
          n                    TYPE i
        RETURNING
          VALUE(r_bracket_seq) TYPE string.

  PRIVATE SECTION.
    CLASS-DATA: random_int TYPE REF TO cl_abap_random_int.

    CLASS-METHODS:
      _split_string
        IMPORTING
          i_text         TYPE string
        RETURNING
          VALUE(r_chars) TYPE stringtab,

      _rand_bool
        RETURNING
          VALUE(r_bool) TYPE i.
ENDCLASS.

CLASS lcl_balanced_brackets IMPLEMENTATION.
  METHOD class_constructor.
    random_int = cl_abap_random_int=>create( seed = CONV #( sy-uzeit )
                                             min  = 0
                                             max  = 1 ).
  ENDMETHOD.

  METHOD are_brackets_balanced.
    DATA: open_bracket_count TYPE i.

    DATA(chars) = _split_string( seq ).

    r_are_brackets_balanced = abap_false.

    LOOP AT chars ASSIGNING FIELD-SYMBOL(<c>).
      IF <c> = ']' AND open_bracket_count = 0.
        RETURN.
      ENDIF.

      IF <c> = ']'.
        open_bracket_count = open_bracket_count - 1.
      ENDIF.

      IF <c> = '['.
        open_bracket_count = open_bracket_count + 1.
      ENDIF.
    ENDLOOP.

    IF open_bracket_count > 0.
      RETURN.
    ENDIF.

    r_are_brackets_balanced = abap_true.
  ENDMETHOD.

  METHOD get_random_brackets_seq.
    DATA(itab) = VALUE stringtab( FOR i = 1 THEN i + 1 WHILE i <= n
                                     ( COND #( WHEN _rand_bool( ) = 0 THEN '['
                                               ELSE ']' ) ) ).
    r_bracket_seq = concat_lines_of( itab ).
  ENDMETHOD.

  METHOD _rand_bool.
    r_bool = random_int->get_next( ).
  ENDMETHOD.

  METHOD _split_string.
    DATA: off TYPE i VALUE 0.

    DO strlen( i_text ) TIMES.
      INSERT i_text+off(1) INTO TABLE r_chars.
      off = off + 1.
    ENDDO.
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
  DO 10 TIMES.
    DATA(seq) = lcl_balanced_brackets=>get_random_brackets_seq( 10 ).
    cl_demo_output=>write( |{ seq } => { COND string( WHEN lcl_balanced_brackets=>are_brackets_balanced( seq ) = abap_true THEN 'OK'
                                                      ELSE 'NOT OK' ) }| ).
  ENDDO.
  cl_demo_output=>display( ).


PROC Generate(BYTE size CHAR ARRAY s)
  BYTE i,half

  s(0)=size
  half=size RSH 1

  FOR i=1 TO half
  DO s(i)='[ OD

  FOR i=half+1 TO size
  DO s(i)='] OD
RETURN

PROC Shuffle(CHAR ARRAY s)
  BYTE i,j,k,n,len,tmp

  len=s(0)
  n=Rand(len+1)
  FOR k=1 TO n
  DO
    i=Rand(len)+1
    j=Rand(len)+1
    tmp=s(i)
    s(i)=s(j)
    s(j)=tmp
  OD
RETURN

BYTE FUNC Balanced(CHAR ARRAY s)
  INT i,lev

  lev=0
  FOR i=1 TO s(0)
  DO
    IF s(i)='[ THEN
      lev==+1
    ELSE
      lev==-1
    FI

    IF lev<0 THEN
      RETURN (0)
    FI
  OD

  IF lev#0 THEN
    RETURN (0)
  FI
RETURN (1)

PROC Main()
  CHAR ARRAY s(20)
  BYTE i,b

  FOR i=0 TO 20 STEP 2
  DO
    Generate(i,s)
    Shuffle(s)
    b=Balanced(s)

    IF s(0)=0 THEN
      Print("(empty)")
    ELSE
      Print(s)
    FI
    Print(" is ")
    IF b=0 THEN
      Print("not ")
    FI
    PrintE("balanced")
  OD
RETURN


with Ada.Numerics.Discrete_Random;
with Ada.Text_IO;
with Ada.Strings.Fixed;
procedure Brackets is
   package Random_Positive is new Ada.Numerics.Discrete_Random (Positive);
   Positive_Generator : Random_Positive.Generator;
   procedure Swap (Left, Right : in out Character) is
      Temp : constant Character := Left;
   begin
      Left := Right;
      Right := Temp;
   end Swap;
   function Generate_Brackets (Bracket_Count : Natural;
                               Opening_Bracket : Character := '[';
                               Closing_Bracket : Character := ']')
            return String is
      use Ada.Strings.Fixed;
      All_Brackets : String := Bracket_Count * Opening_Bracket & Bracket_Count * Closing_Bracket;
   begin
      for I in All_Brackets'Range loop
         Swap (All_Brackets (I), All_Brackets (Random_Positive.Random (Positive_Generator) mod (Bracket_Count * 2) + 1));
      end loop;
      return All_Brackets;
   end Generate_Brackets;

   function Check_Brackets (Test : String;
                            Opening_Bracket : Character := '[';
                            Closing_Bracket : Character := ']')
            return Boolean is
      Open : Natural := 0;
   begin
      for I in Test'Range loop
         if Test (I) = Opening_Bracket then
            Open := Open + 1;
         elsif Test (I) = Closing_Bracket then
            if Open = 0 then
               return False;
            else
               Open := Open - 1;
            end if;
         end if;
      end loop;
      return True;
   end Check_Brackets;
begin
   Random_Positive.Reset (Positive_Generator);
   Ada.Text_IO.Put_Line ("Brackets");
   for I in 0 .. 4 loop
      for J in 0 .. I loop
         declare
            My_String : constant String := Generate_Brackets (I);
         begin
            Ada.Text_IO.Put_Line (My_String & ": " & Boolean'Image (Check_Brackets (My_String)));
         end;
      end loop;
   end loop;
end Brackets;


unbalanced(data s)
{
    integer b, i;

    b = i = 0;
    while (i + ~s && -1 < b) {
        b += s[i -= 1] == '[' ? -1 : 1;
    }

    b;
}

generate(data b, integer d)
{
    if (d) {
        d.times(l_bill, list(), -1, '[', ']').l_rand().ucall(b_append, 1, b);
    }
}

main(void)
{
    integer i;

    i = 0;
    while (i < 10) {
        data s;

        generate(s, i);
        o_(s, " is ", unbalanced(s) ? "un" : "", "balanced\n");

        i += 1;
    }

    0;
}


# generates a string of random opening and closing brackets. The number of    #
# each type of brackets is speccified in length                               #
PROC get brackets = ( INT length ) STRING:
    BEGIN
        INT   result length = length * 2;
        [ 1 : result length ]CHAR result;
        # initialise the brackets to all open brackets                        #
        FOR char pos TO result length DO result[ char pos ] := "[" OD;
        # set half of the brackets to close brackets                          #
        INT   close count := 0;
        WHILE close count < length
        DO
            INT   random pos = 1 + ENTIER ( next random * result length );
            IF result[ random pos ] = "["
            THEN
                close count          +:= 1;
                result[ random pos ]  := "]"
            FI
        OD;
        result
    END # get brackets # ;

# returns TRUE if the brackets string contains a correctly nested sequence    #
# of brackets, FALSE otherwise                                                #
PROC check brackets = ( STRING brackets ) BOOL:
    BEGIN
        INT depth := 0;
        FOR char pos FROM LWB brackets TO UPB brackets
        WHILE
            IF brackets[ char pos ] = "["
            THEN
                depth +:= 1
            ELSE
                depth -:= 1
            FI;
            depth >= 0
        DO
            SKIP
        OD;
        # depth will be 0 if we reached the end of the string and it was     #
        # correct, non-0 otherwise                                           #
        depth = 0
    END # check brackets # ;

# procedure to test check brackets                                           #
PROC test check brackets = ( STRING brackets ) VOID:
    print( ( ( brackets
             + ": "
             + IF check brackets( brackets ) THEN "ok" ELSE "not ok" FI
             )
           , newline
           )
         ) ;

# test the bracket generation and checking PROCs                             #
test check brackets( get brackets( 0 ) );
FOR length TO 12
DO
    TO 2
    DO
        test check brackets( get brackets( length ) )
    OD
OD


grammar balancedBrackets ;

options {
	language = Java;
}

bb	:	{System.out.print("input is: ");} (balancedBrackets {System.out.print($balancedBrackets.text);})* NEWLINE {System.out.println();}
	;
balancedBrackets
	:	OpenBracket balancedBrackets* CloseBracket
	;
OpenBracket
	:	'['
	;
CloseBracket
	:	']'
	;
NEWLINE	:	'\r'? '\n'
	;


-- CHECK NESTING OF SQUARE BRACKET SEQUENCES ---------------------------------

-- Zero-based index of the first problem (-1 if none found):

-- imbalance :: String -> Integer
on imbalance(strBrackets)
    script
        on errorIndex(xs, iDepth, iIndex)
            set lngChars to length of xs
            if lngChars > 0 then
                set iNext to iDepth + cond(item 1 of xs = "[", 1, -1)

                if iNext < 0 then -- closing bracket unmatched
                    iIndex
                else
                    if lngChars > 1 then -- continue recursively
                        errorIndex(items 2 thru -1 of xs, iNext, iIndex + 1)
                    else -- end of string
                        cond(iNext = 0, -1, iIndex)
                    end if
                end if
            else
                cond(iDepth = 0, -1, iIndex)
            end if
        end errorIndex
    end script

    result's errorIndex(characters of strBrackets, 0, 0)
end imbalance

-- TEST ----------------------------------------------------------------------

-- Random bracket sequences for testing
-- brackets :: Int -> String
on randomBrackets(n)
    -- bracket :: () -> String
    script bracket
        on |λ|(_)
            cond((random number) < 0.5, "[", "]")
        end |λ|
    end script
    intercalate("", map(bracket, enumFromTo(1, n)))
end randomBrackets

on run
    set nPairs to 6

    -- report :: Int -> String
    script report
        property strPad : concat(replicate(nPairs * 2 + 4, space))

        on |λ|(n)
            set w to n * 2
            set s to randomBrackets(w)
            set i to imbalance(s)
            set blnOK to (i = -1)

            set strStatus to cond(blnOK, "OK", "problem")

            set strLine to "'" & s & "'" & ¬
                (items (w + 2) thru -1 of strPad) & strStatus

            set strPointer to cond(blnOK, ¬
                "", linefeed & concat(replicate(i + 1, space)) & "^")

            intercalate("", {strLine, strPointer})
        end |λ|
    end script

    linefeed & ¬
        intercalate(linefeed, ¬
            map(report, enumFromTo(1, nPairs))) & linefeed
end run

-- GENERIC FUNCTIONS ---------------------------------------------------------

-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
    tell mReturn(f)
        set lng to length of xs
        set lst to {}
        repeat with i from 1 to lng
            set end of lst to |λ|(item i of xs, i, xs)
        end repeat
        return lst
    end tell
end map

-- foldl :: (a -> b -> a) -> a -> [b] -> a
on foldl(f, startValue, xs)
    tell mReturn(f)
        set v to startValue
        set lng to length of xs
        repeat with i from 1 to lng
            set v to |λ|(v, item i of xs, i, xs)
        end repeat
        return v
    end tell
end foldl

-- Text -> [Text] -> Text
on intercalate(strText, lstText)
    set {dlm, my text item delimiters} to {my text item delimiters, strText}
    set strJoined to lstText as text
    set my text item delimiters to dlm
    return strJoined
end intercalate

-- concat :: [[a]] -> [a] | [String] -> String
on concat(xs)
    script append
        on |λ|(a, b)
            a & b
        end |λ|
    end script

    if length of xs > 0 and class of (item 1 of xs) is string then
        set empty to ""
    else
        set empty to {}
    end if
    foldl(append, empty, xs)
end concat

-- Egyptian multiplication - progressively doubling a list, appending
-- stages of doubling to an accumulator where needed for binary
-- assembly of a target length

-- replicate :: Int -> a -> [a]
on replicate(n, a)
    set out to {}
    if n < 1 then return out
    set dbl to {a}

    repeat while (n > 1)
        if (n mod 2) > 0 then set out to out & dbl
        set n to (n div 2)
        set dbl to (dbl & dbl)
    end repeat
    return out & dbl
end replicate

-- Value of one of two expressions
-- cond ::  Bool -> a -> b -> c
on cond(bln, f, g)
    if bln then
        set e to f
    else
        set e to g
    end if
    if class of e is handler then
        mReturn(e)'s |λ|()
    else
        e
    end if
end cond

-- enumFromTo :: Int -> Int -> [Int]
on enumFromTo(m, n)
    if m > n then
        set d to -1
    else
        set d to 1
    end if
    set lst to {}
    repeat with i from m to n by d
        set end of lst to i
    end repeat
    return lst
end enumFromTo

-- Lift 2nd class handler function into 1st class script wrapper
-- mReturn :: Handler -> Script
on mReturn(f)
    if class of f is script then
        f
    else
        script
            property |λ| : f
        end script
    end if
end mReturn


.data

balanced_message:
  .ascii "OK\n"

unbalanced_message:
  .ascii "NOT OK\n"

.text

.equ balanced_msg_len, 3
.equ unbalanced_msg_len, 7

BalancedBrackets:

  mov r1, #0
  mov r2, #0
  mov r3, #0

  process_bracket:
    ldrb r2, [r0, r1]

    cmp r2, #0
    beq evaluate_balance

    cmp r2, #'['
    addeq r3, r3, #1

    cmp r2, #']'
    subeq r3, r3, #1

    cmp r3, #0
    blt unbalanced

    add r1, r1, #1
    b process_bracket

  evaluate_balance:
    cmp r3, #0
    beq balanced

    unbalanced:
       ldr r1, =unbalanced_message
       mov r2, #unbalanced_msg_len
       b display_result

    balanced:
       ldr r1, =balanced_message
       mov r2, #balanced_msg_len

    display_result:
      mov r7, #4
      mov r0, #1
      svc #0

      mov pc, lr


isBalanced: function [s][
	cnt: 0

	loop split s [ch][
		if? ch="]" [
			cnt: cnt-1
			if cnt<0 -> return false
		]
		else [
			if ch="[" -> cnt: cnt+1
		]
    ]

    cnt=0
]

loop 1..10 'i [
	str: join map 0..(2*i)-1 [x][ sample ["[" "]"]]

	prints str

	if? isBalanced str  -> print " OK"
	else 				-> print " Not OK"
]


; Generate 10 strings with equal left and right brackets
Loop, 5
{
	B = %A_Index%
	loop 2
	{
		String =
		Loop % B
			String .= "[`n"
		Loop % B
			String .= "]`n"
		Sort, String, Random
		StringReplace, String, String,`n,,All
		Example .= String " - " IsBalanced(String) "`n"
	}
}
	MsgBox % Example
return

IsBalanced(Str)
{
	Loop, PARSE, Str
	{
		If A_LoopField = [
			i++
		Else if A_LoopField = ]
			i--
		If i < 0
			return "NOT OK"
	}
	Return "OK"
}


#include <Array.au3>
Local $Array[1]
_ArrayAdd($Array, "[]")
_ArrayAdd($Array, "[][]")
_ArrayAdd($Array, "[[][]]")
_ArrayAdd($Array, "][")
_ArrayAdd($Array, "][][")
_ArrayAdd($Array, "[]][[]")

For $i = 0 To UBound($Array) -1
	Balanced_Brackets($Array[$i])
	If @error Then
		ConsoleWrite($Array[$i] &" = NOT OK"&@CRLF)
	Else
		ConsoleWrite($Array[$i] &" = OK"&@CRLF)
	EndIf
Next

Func Balanced_Brackets($String)
	Local $cnt = 0
	$Split = Stringsplit($String, "")
	For $i = 1 To $Split[0]
		If $split[$i] = "[" Then $cnt += 1
		If $split[$i] = "]" Then $cnt -= 1
		If $cnt < 0 Then Return SetError(1,0,0)
	Next
	Return 1
EndFunc


#!/usr/bin/awk -f
BEGIN {
   print isbb("[]")
   print isbb("][")
   print isbb("][][")
   print isbb("[][]")
   print isbb("[][][]")
   print isbb("[]][[]")
}

function isbb(x) {
   s = 0
   for (k=1; k<=length(x); k++) {
	c = substr(x,k,1)
	if (c=="[") {s++}
	else { if (c=="]") s--	}

        if (s<0) {return 0}
   }
   return (s==0)
}


FOR len = 0 TO 18 STEP 2

    str$ = ""
    DOTIMES len
        str$ = str$ & CHR$(IIF(RANDOM(2) = 0, 91, 93))
    DONE

    status = 0
    FOR x = 1 TO LEN(str$)
        IF MID$(str$, x, 1) = "[" THEN
            INCR status
        ELSE
            DECR status
        FI
        IF status < 0 THEN BREAK
    NEXT

    IF status = 0 THEN
        PRINT "OK: ", str$
    ELSE
        PRINT "BAD: ", str$
    ENDIF
NEXT


DECLARE FUNCTION checkBrackets% (brackets AS STRING)
DECLARE FUNCTION generator$ (length AS INTEGER)

RANDOMIZE TIMER

DO
    x$ = generator$ (10)
    PRINT x$,
    IF checkBrackets(x$) THEN
        PRINT "OK"
    ELSE
        PRINT "NOT OK"
    END IF
LOOP WHILE LEN(x$)

FUNCTION checkBrackets% (brackets AS STRING)
    'returns -1 (TRUE) if everything's ok, 0 (FALSE) if not
    DIM L0 AS INTEGER, sum AS INTEGER

    FOR L0 = 1 TO LEN(brackets)
        SELECT CASE MID$(brackets, L0, 1)
            CASE "["
                sum = sum + 1
            CASE "]"
                sum = sum - 1
        END SELECT
        IF sum < 0 THEN
            checkBrackets% = 0
            EXIT FUNCTION
        END IF
    NEXT

    IF 0 = sum THEN
        checkBrackets% = -1
    ELSE
        checkBrackets% = 0
    END IF
END FUNCTION

FUNCTION generator$ (length AS INTEGER)
    z = INT(RND * length)
    IF z < 1 THEN generator$ = "": EXIT FUNCTION
    REDIM x(z * 2) AS STRING
    FOR i = 0 TO z STEP 2
        x(i) = "["
        x(i + 1) = "]"
    NEXT
    FOR i = 1 TO UBOUND(x)
        z = INT(RND * 2)
        IF z THEN SWAP x(i), x(i - 1)
    NEXT
    xx$ = ""
    FOR i = 0 TO UBOUND(x)
        xx$ = xx$ + x(i)
    NEXT
    generator$ = xx$
END FUNCTION


s$ = "[[]][]"
print s$; " = ";

if not check_brackets(s$) then print "not ";
print "ok"
end

function check_brackets(s$)
  level = 0
  for i = 1 to length(s$)
    c$ = mid(s$, i, 1)
    begin case
      case c$ = "["
        level = level + 1
      case c$ = "]"
        level = level - 1
        if level < 0 then exit for
    end case
  next i
  return level = 0
end function


:: Balanced Brackets Task from Rosetta Code
:: Batch File Implementation

@echo off
setlocal enabledelayedexpansion

set "num_pairs=10"
set "num_strings=10"

:: the main thing
for /l %%s in (1, 1, %num_strings%) do (
    call :generate
    call :check
)
echo(
pause
exit /b 0

:: generate strings of brackets
:generate
set "string="
rem put %num_pairs% number of "[" in string
for /l %%c in (1, 1, %num_pairs%) do set "string=!string!["
rem put %num_pairs% number of "]" in random spots of string
set "ctr=%num_pairs%"
for /l %%c in (1, 1, %num_pairs%) do (
    set /a "rnd=!random! %% (!ctr! + 1)"
    for %%x in (!rnd!) do (
        set "left=!string:~0,%%x!"
        set "right=!string:~%%x!"
    )
    set "string=!left!]!right!"
    set /a "ctr+=1"
)
goto :EOF

:: check for balance
:check
set "new=%string%"
:check_loop
if "%new%" equ "" (
    echo(
    echo(%string% is Balanced.
    goto :EOF
) else if "%old%" equ "%new%" (   %== unchangeable already? ==%
    echo(
    echo(%string% is NOT Balanced.
    goto :EOF
)
rem apply rewrite rule "[]" -> null
set "old=%new%"
set "new=%old:[]=%"
goto check_loop


FOR x%=1 TO 10
test$=FNgenerate(RND(10))
  PRINT "Bracket string ";test$;" is ";FNvalid(test$)
NEXT x%
END
:
DEFFNgenerate(n%)
LOCAL l%,r%,t%,output$
WHILE l%<n% AND r%<n%
  CASE RND(2) OF
    WHEN 1:
      l%+=1
      output$+="["
    WHEN 2:
      r%+=1
      output$+="]"
  ENDCASE
ENDWHILE
IF l%=n% THEN output$+=STRING$(n%-r%,"]") ELSE output$+=STRING$(n%-l%,"[")
=output$
:
DEFFNvalid(q$)
LOCAL x%,count%
IF LEN(q$)=0 THEN ="OK."
FOR x%=1 TO LEN(q$)
  IF MID$(q$,x%,1)="[" THEN count%+=1 ELSE count%-=1
  IF count%<0 THEN ="not OK."
NEXT x%
="OK."


( (bal=|"[" !bal "]" !bal)
& ( generate
  =   a j m n z N S someNumber
    .   !arg:<1&
      |   11^123+13^666+17^321:?someNumber
        & (!arg:?n)+1:?N
        & :?S
        &   whl
          ' (!n+-1:~<0:?n&"[" "]" !S:?S)
        &   whl
          ' ( !someNumber:>0
            & mod$(!someNumber.!N):?j
            & div$(!someNumber.!N):?someNumber
            & !S:?a [!j ?m [!N ?z
            & !z !m !a:?S
            )
        & !S
  )
& 0:?L
&   whl
  ' ( generate$!L:?S
    & put$(str$(!S ":"))
    &   out
      $ (!S:!bal&Balanced|"Not balanced")
    & !L+1:<11:?L
    )
);


string.prototype.balanced? = {
  brackets = []
  balanced = true

  my.dice.each_while { c |
    true? c == "["
      { brackets << c }
      { true? c == "]"
        { last = brackets.pop
          false? last == "["
          { balanced = false }
        }
      }

    balanced
  }

  true? brackets.empty?
    { balanced }
    { false }
}

generate_brackets = { n | (n.of("[") + n.of("]")).shuffle.join }

1.to 10 { n |
  test = generate_brackets n

  true? test.balanced?
    { p "#{test} is balanced" }
    { p "#{test} is not balanced" }
}


#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int isBal(const char*s,int l){
    signed c=0;
    while(l--)
	if(s[l]==']') ++c;
	else if(s[l]=='[') if(--c<0) break;
    return !c;
}

void shuffle(char*s,int h){
    int x,t,i=h;
    while(i--){
	t=s[x=rand()%h];
	s[x]=s[i];
	s[i]=t;
    }
}

void genSeq(char*s,int n){
    if(n){
	memset(s,'[',n);
	memset(s+n,']',n);
	shuffle(s,n*2);
    }
    s[n*2]=0;
}

void doSeq(int n){
    char s[64];
    const char *o="False";
    genSeq(s,n);
    if(isBal(s,n*2)) o="True";
    printf("'%s': %s\n",s,o);
}

int main(){
    int n=0;
    while(n<9) doSeq(n++);
    return 0;
}


using System;
using System.Linq;

class Program
{
    static bool IsBalanced(string text, char open = '[', char close = ']')
    {
        var level = 0;
        foreach (var character in text)
        {
            if (character == close)
            {
                if (level == 0)
                {
                    return false;
                }
                level--;
            }
            if (character == open)
            {
                level++;
            }
        }
        return level == 0;
    }

    static string RandomBrackets(int count, char open = '[', char close = ']')
    {
        var random = new Random();
        return string.Join(string.Empty,
                (new string(open, count) + new string(close, count)).OrderBy(c => random.Next()));
    }

    static void Main()
    {
        for (var count = 0; count < 9; count++)
        {
            var text = RandomBrackets(count);
            Console.WriteLine("\"{0}\" is {1}balanced.", text, IsBalanced(text) ? string.Empty : "not ");
        }
    }
}


#include <algorithm>
#include <iostream>
#include <string>

std::string generate(int n, char left = '[', char right = ']')
{
    std::string str(std::string(n, left) + std::string(n, right));
    std::random_shuffle(str.begin(), str.end());
    return str;
}

bool balanced(const std::string &str, char left = '[', char right = ']')
{
    int count = 0;
    for (std::string::const_iterator it = str.begin(); it != str.end(); ++it)
    {
        if (*it == left)
            count++;
        else if (*it == right)
            if (--count < 0) return false;
    }
    return count == 0;
}

int main()
{
    srand(time(NULL)); // seed rng
    for (int i = 0; i < 9; ++i)
    {
        std::string s(generate(i));
        std::cout << (balanced(s) ? " ok: " : "bad: ") << s << "\n";
    }
}


import com.vasileff.ceylon.random.api {
    platformRandom,
    Random
}
"""Run the example code for Rosetta Code ["Balanced brackets" task] (http://rosettacode.org/wiki/Balanced_brackets)."""
shared void run() {
    value rnd = platformRandom();
    for (len in (0..10)) {
        value c = generate(rnd, len);
        print("``c.padTrailing(20)`` - ``if (balanced(c)) then "OK" else "NOT OK" ``");
    }
}

String generate(Random rnd, Integer count)
        => if (count == 0) then ""
           else let(length = 2*count,
                    brackets = zipEntries(rnd.integers(length).take(length),
                                          "[]".repeat(count))
                            .sort((a,b) => a.key<=>b.key)
                            .map(Entry.item))
                String(brackets);

Boolean balanced(String input)
        => let (value ints = { for (c in input) if (c == '[') then 1 else -1 })
           ints.filter((i) => i != 0)
               .scan(0)(plus<Integer>)
               .every((i) => i >= 0);


(defn gen-brackets [n]
  (->> (concat (repeat n \[) (repeat n \]))
       shuffle
       (apply str ,)))

(defn balanced? [s]
  (loop [[first & coll] (seq s)
	 stack '()]
    (if first
      (if (= first \[)
	(recur coll (conj stack \[))
	(when (= (peek stack) \[)
	  (recur coll (pop stack))))
      (zero? (count stack)))))


% This program needs the random number generator from
% "misc.lib" that comes with PCLU.

shuffle = proc [T: type] (a: array[t])
    aT = array[t]
    for i: int in int$from_to_by(aT$size(a)-1,0,-1) do
        x: int := aT$low(a) + i
        y: int := aT$low(a) + random$next(i+1)
        temp: T := a[x]
        a[x] := a[y]
        a[y] := temp
    end
end shuffle

brackets = proc (n: int) returns (string)
    br: array[char] := array[char]$[]
    for i: int in int$from_to(1,2*n) do
        if i<=n then array[char]$addh(br, '[')
        else array[char]$addh(br, ']')
        end
    end
    shuffle[char](br)
    return(string$ac2s(br))
end brackets

balanced = proc (br: string) returns (bool)
    depth: int := 0
    for c: char in string$chars(br) do
        if     c='[' then depth := depth + 1
        elseif c=']' then depth := depth - 1
        end
        if depth<0 then return(false) end
    end
    return(depth = 0)
end balanced

start_up = proc ()
    po: stream := stream$primary_output()
    d: date := now()
    random$seed(d.second + 60*(d.minute + 60*d.hour))

    for size: int in int$from_to(0, 10) do
        b: string := brackets(size)
        stream$puts(po, "\"" || b || "\": ")
        if balanced(b) then
            stream$putl(po, "balanced")
        else
            stream$putl(po, "not balanced")
        end
    end
end start_up


       IDENTIFICATION DIVISION.
       PROGRAM-ID. test-balanced-brackets.

       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  True-Val  CONSTANT 0.
       01  False-Val CONSTANT 1.

       LOCAL-STORAGE SECTION.
       01  current-time        PIC 9(10).

       01  bracket-type        PIC 9.
           88 add-open-bracket VALUE 1.

       01  bracket-string-area.
           03  bracket-string  PIC X(10) OCCURS 10 TIMES.

       01  i                   PIC 999.
       01  j                   PIC 999.

       PROCEDURE DIVISION.
           *> Seed RANDOM().
           MOVE FUNCTION CURRENT-DATE (7:10) TO current-time
           MOVE FUNCTION RANDOM(current-time) TO current-time

           *> Generate random strings of brackets.
           PERFORM VARYING i FROM 1 BY 1 UNTIL 10 < i
               PERFORM VARYING j FROM 1 BY 1 UNTIL i < j
                   COMPUTE bracket-type =
                       FUNCTION REM(FUNCTION RANDOM * 1000, 2)

                   IF add-open-bracket
                       MOVE "[" TO bracket-string (i) (j:1)
                   ELSE
                       MOVE "]" TO bracket-string (i) (j:1)
                   END-IF
               END-PERFORM
           END-PERFORM

           *> Display if the strings are balanced or not.
           PERFORM VARYING i FROM 1 BY 1 UNTIL 10 < i
               CALL "check-if-balanced" USING bracket-string (i)
               IF RETURN-CODE = True-Val
                   DISPLAY FUNCTION TRIM(bracket-string (i))
                       " is balanced."
               ELSE
                   DISPLAY FUNCTION TRIM(bracket-string (i))
                       " is not balanced."
               END-IF
           END-PERFORM

           GOBACK
           .

       END PROGRAM test-balanced-brackets.

       IDENTIFICATION DIVISION.
       PROGRAM-ID. check-if-balanced.

       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  True-Val  CONSTANT 0.
       01  False-Val CONSTANT 1.

       LOCAL-STORAGE SECTION.
       01  nesting-level  PIC S999.
       01  i              PIC 999.

       LINKAGE SECTION.
       01  bracket-string PIC X(100).

       PROCEDURE DIVISION USING bracket-string.
           PERFORM VARYING i FROM 1 BY 1
                   UNTIL (100 < i)
                      OR (bracket-string (i:1) = SPACE)
                      OR (nesting-level < 0)
               IF bracket-string (i:1) = "["
                   ADD 1 TO nesting-level
               ELSE
                   SUBTRACT 1 FROM nesting-level
                   IF nesting-level < 0
                       MOVE False-Val TO RETURN-CODE
                       GOBACK
                   END-IF
               END-IF
           END-PERFORM

           IF nesting-level = 0
               MOVE True-Val TO RETURN-CODE
           ELSE
               MOVE False-Val TO RETURN-CODE
           END-IF

           GOBACK
           .

       END PROGRAM check-if-balanced.


isBalanced = (brackets) ->
  openCount = 0
  for bracket in brackets
    openCount += if bracket is '[' then 1 else -1
    return false if openCount < 0
  openCount is 0

bracketsCombinations = (n) ->
  for i in [0...Math.pow 2, n]
    str = i.toString 2
    str = '0' + str while str.length < n
    str.replace(/0/g, '[').replace(/1/g, ']')

for brackets in bracketsCombinations 4
  console.log brackets, isBalanced brackets


(defun string-of-brackets (n)
  (let* ((len (* 2 n))
         (res (make-string len))
         (opening (/ len 2))
         (closing (/ len 2)))
    (dotimes (i len res)
      (setf (aref res i)
            (cond ((zerop opening) #\])
                  ((zerop closing) #\[)
                  (t (if (= (random 2) 0)
                         (progn (decf opening) #\[)
                         (progn (decf closing) #\]))))))))

(defun balancedp (string)
  (zerop (reduce (lambda (nesting bracket)
                   (ecase bracket
                     (#\] (if (= nesting 0)
                              (return-from balancedp nil)
                              (1- nesting)))
                     (#\[ (1+ nesting))))
                 string
                 :initial-value 0)))

(defun show-balanced-brackets ()
  (dotimes (i 10)
    (let ((s (string-of-brackets i)))
      (format t "~3A: ~A~%" (balancedp s) s))))


MODULE Brackets;
IMPORT StdLog, Args, Stacks (* See Task Stacks *);
TYPE

	Character = POINTER TO RECORD (Stacks.Object)
		c: CHAR
	END;

PROCEDURE NewCharacter(c: CHAR): Character;
VAR
	n: Character;
BEGIN
	NEW(n);n.c:= c;RETURN n
END NewCharacter;

PROCEDURE (c: Character) Show*;
BEGIN
	StdLog.String("Character(");StdLog.Char(c.c);StdLog.String(");");StdLog.Ln
END Show;

PROCEDURE CheckBalance(str: ARRAY OF CHAR): BOOLEAN;
VAR
	s: Stacks.Stack;
	n,x: ANYPTR;
	i: INTEGER;
	c : CHAR;
BEGIN
	i := 0; s := Stacks.NewStack();
	WHILE (i < LEN(str$)) & (~Args.IsBlank(str[i])) & (str[i] # 0X) DO
		IF s.Empty() THEN
			s.Push(NewCharacter(str[i]));
		ELSE
			n := s.top.data;
			WITH
				n :  Character DO
				IF (str[i] = ']')& (n.c = '[') THEN
					x := s.Pop();
				ELSE
					s.Push(NewCharacter(str[i]))
				END;
			ELSE RETURN FALSE;
			END;
		END;
		INC(i)
	END;
	RETURN s.Empty();
END CheckBalance;

PROCEDURE Do*;
VAR
	p : Args.Params;
	i: INTEGER;
BEGIN
	Args.Get(p); (* Get Params *)
	FOR i := 0 TO p.argc - 1 DO
		StdLog.String(p.args[i] + ":>");StdLog.Bool(CheckBalance(p.args[i]));StdLog.Ln
	END
END Do;

END Brackets.


def generate(n : Int)
  (['[',']'] * n).shuffle.join # Implicit return
end

def is_balanced(str : String)
  count = 0
  str.each_char do |ch|
    case ch
    when '['
      count += 1
    when ']'
      count -= 1
      if count < 0
        return false
      end
    else
      return false
    end
  end
  count == 0
end

10.times do |i|
  str = generate(i)
  puts "#{str}: #{is_balanced(str)}"
end


import std.stdio, std.algorithm, std.random, std.range;

void main() {
    foreach (immutable i; 1 .. 9) {
        immutable s = iota(i * 2).map!(_ => "[]"[uniform(0, 2)]).array;
        writeln(s.balancedParens('[', ']') ? " OK: " : "bad: ", s);
    }
}


procedure Balanced_Brackets;

var   BracketsStr : string;
      TmpStr      : string;
      I,J         : integer;

begin
  Randomize;
  for I := 1 to 9 do
    begin
      { Create a random string of 2*N chars with N*"[" and N*"]" }
      TmpStr  := '';
      for J := 1 to I do
        TmpStr := '['+TmpStr+']';
      BracketsStr := '';
      while TmpStr > '' do
        begin
          J := Random(Length(TmpStr))+1;
          BracketsStr := BracketsStr+TmpStr[J];
          Delete(TmpStr,J,1);
        end;
      TmpStr := BracketsStr;
      { Test for balanced brackets }
      while Pos('[]',TmpStr) > 0 do
        Delete(TmpStr,Pos('[]',TmpStr),2);
      if TmpStr = '' then
        writeln(BracketsStr+': OK')
      else
        writeln(BracketsStr+': not OK');
    end;
end;


matching?:
	swap 0
	for c in chars:
		if = c "]":
			++
		elseif = c "[":
			if not dup:
				drop
				return false
			--
	not

!. matching? ""
!. matching? "[]"
!. matching? "[][]"
!. matching? "[[][]]"
!. matching? "]["
!. matching? "][]["
!. matching? "[]][[]"


(define (balance str)
	(for/fold (closed 0) ((par str))
	 #:break (< closed 0 ) => closed
	(+ closed
	(cond
		((string=? par "[")  1)
		((string=? par "]") -1)
		(else 0)))))

(define (task N)
(define str (list->string (append (make-list N "[") (make-list N "]"))))
	(for ((i 10))
	(set! str (list->string (shuffle (string->list str))))
	(writeln  (if (zero? (balance str)) '👍  '❌ ) str)))

(task 4)

❌     "[]]][[]["
❌     "]][][[[]"
❌     "][[[]]]["
👍     "[][[[]]]"
❌     "]][[][]["
❌     "][][[[]]"
👍     "[][][[]]"
❌     "]][[][[]"
❌     "[[]]][[]"
❌     "[[][]]]["


import system'routines;
import extensions;
import extensions'text;

randomBrackets(len)
{
    if (0 == len)
    {
        ^emptyString
    }
    else
    {
        var brackets :=
            Array.allocate(len).populate:(i => $91)
            +
            Array.allocate(len).populate:(i => $93);

        brackets := brackets.randomize(len * 2);

        ^ brackets.summarize(new StringWriter()).toString()
    }
}

extension op
{
    get isBalanced()
    {
        var counter := new Integer(0);

        self.seekEach:(ch => counter.append((ch==$91).iif(1,-1)) < 0);

        ^ (0 == counter)
    }
}

public program()
{
    for(int len := 0, len < 9, len += 1)
    {
        var str := randomBrackets(len);

        console.printLine("""",str,"""",str.isBalanced ? " is balanced" : " is not balanced")
    };

    console.readChar()
}


defmodule Balanced_brackets do
  def task do
    Enum.each(0..5, fn n ->
      brackets = generate(n)
      result = is_balanced(brackets) |> task_balanced
      IO.puts "#{brackets} is #{result}"
    end)
  end

  defp generate( 0 ), do: []
  defp generate( n ) do
    for _ <- 1..2*n, do: Enum.random ["[", "]"]
  end

  def is_balanced( brackets ), do: is_balanced_loop( brackets, 0 )

  defp is_balanced_loop( _, n ) when n < 0, do: false
  defp is_balanced_loop( [], 0 ), do: true
  defp is_balanced_loop( [], _n ), do: false
  defp is_balanced_loop( ["[" | t], n ), do: is_balanced_loop( t, n + 1 )
  defp is_balanced_loop( ["]" | t], n ), do: is_balanced_loop( t, n - 1 )

  defp task_balanced( true ), do: "OK"
  defp task_balanced( false ), do: "NOT OK"
end

Balanced_brackets.task


-module( balanced_brackets ).
-export( [generate/1, is_balanced/1, task/0] ).

generate( N ) ->
	[generate_bracket(random:uniform()) || _X <- lists:seq(1, 2*N)].

is_balanced( String ) -> is_balanced_loop( String, 0 ).

task() ->
	lists:foreach( fun (N) ->
			String = generate( N ),
			Result = is_balanced( String ),
			io:fwrite( "~s is ~s~n", [String, task_balanced(Result)] )
		end,
		lists:seq(0, 5) ).

is_balanced_loop( _String, N ) when N < 0 -> false;
is_balanced_loop( [], 0 ) -> true;
is_balanced_loop( [], _N ) -> false;
is_balanced_loop( [$[ | T], N ) -> is_balanced_loop( T, N + 1 );
is_balanced_loop( [$] | T], N ) -> is_balanced_loop( T, N - 1 ).

generate_bracket( N ) when N =< 0.5 -> $[;
generate_bracket( N ) when N > 0.5 -> $].

task_balanced( true ) -> "OK";
task_balanced( false ) -> "NOT OK".


function check_brackets(sequence s)
    integer level
    level = 0
    for i = 1 to length(s) do
        if s[i] = '[' then
            level += 1
        elsif s[i] = ']' then
            level -= 1
            if level < 0 then
                return 0
            end if
        end if
    end for
    return level = 0
end function

function generate_brackets(integer n)
    integer opened,closed,r
    sequence s
    opened = n
    closed = n
    s = ""
    for i = 1 to n*2 do
        r = rand(opened+closed)
        if r<=opened then
            s &= '['
            opened -= 1
        else
            s &= ']'
            closed -= 1
        end if
    end for
    return s
end function

sequence s
for i = 1 to 10 do
    s = generate_brackets(3)
    puts(1,s)
    if check_brackets(s) then
        puts(1," OK\n")
    else
        puts(1," NOT OK\n")
    end if
end for


bracketReport
=LAMBDA(bracketPair,
    LAMBDA(s,
        LET(
            depths, SCANLCOLS(
                LAMBDA(depth, charDelta,
                    depth + charDelta
                )
            )(0)(
                codesFromBrackets(bracketPair)(
                    MID(s,
                        SEQUENCE(1, LEN(s), 1, 1),
                        1
                    )
                )
            ),
            overClosePosn, IFNA(MATCH(-1, depths, 0), 0),

            IF(0 <> overClosePosn,
                "Overclosed at char " & (overClosePosn - 1),
                IF(0 <> LASTCOL(depths),
                    "Underclosed by end",
                    "OK"
                )
            )
        )
    )
)

testRandomBrackets
=LAMBDA(bracketPair,
    LAMBDA(n,
        LET(
            sample, CONCAT(
                bracketFromCode(bracketPair)(
                    RANDARRAY(1, n, -1, 1, TRUE)
                )
            ),

            APPENDCOLS(sample)(
                bracketReport(bracketPair)(sample)
            )
        )
    )
)

bracketFromCode
=LAMBDA(bracketPairString,
    LAMBDA(c,
        IF(0 <> c,
            IF(0 < c,
                MID(bracketPairString, 1, 1),
                MID(bracketPairString, 2, 1)
            ),
            "x"
        )
    )
)

codesFromBrackets
=LAMBDA(bracketPair,
    LAMBDA(s,
        LAMBDA(c,
            LET(
                posn, IFERROR(
                    FIND(c, bracketPair),
                    0
                ),

                rem, "0 for non-bracket chars, (1, -1) for (open, close)",
                IF(0 <> posn,
                    IF(1 < posn, -1, 1),
                    0
                )
            )
        )(
             MID(s,
                SEQUENCE(1, LEN(s), 1, 1),
                1
            )
        )
    )
)


let isBalanced str =
  let rec loop count = function
    | ']'::_  when count = 0 -> false
    | '['::xs                -> loop (count+1) xs
    | ']'::xs                -> loop (count-1) xs
    | []                     -> count = 0
    | _::_                   -> false

  str |> Seq.toList |> loop 0

let shuffle arr =
    let rnd = new System.Random()
    Array.sortBy (fun _ -> rnd.Next()) arr

let generate n =
  new string( String.replicate n "[]" |> Array.ofSeq |> shuffle )

for n in 1..10 do
  let s = generate n
  printfn "\"%s\" is balanced: %b" s (isBalanced s)


USING: io formatting locals kernel math sequences unicode.case ;
IN: balanced-brackets

:: balanced ( str -- )
   0 :> counter!
   1 :> ok!
   str
   [ dup length 0 > ]
   [ 1 cut swap
     "[" = [ counter 1 + counter! ] [ counter 1 - counter! ] if
     counter 0 < [ 0 ok! ] when
   ]
   while
   drop
   ok 0 =
   [ "NO" ]
   [ counter 0 > [ "NO" ] [ "YES" ] if ]
   if
   print ;

readln
balanced


class Main
{
  static Bool matchingBrackets (Str[] brackets)
  {
    Int opened := 0
    Int i := 0
    while (i < brackets.size)
    {
      if (brackets[i] == "[")
        opened += 1
      else
        opened -= 1
      if (opened < 0) return false
      i += 1
    }
    return true
  }

  public static Void main (Str[] args)
  {
    if (args.size == 1 && Int.fromStr(args[0], 10, false) != null)
    {
      n := Int.fromStr(args[0])
      Str[] brackets := [,]
      20.times
      {
        brackets = [,]
        // create a random set of brackets
        n.times { brackets.addAll (["[", "]"]) }
        n.times { brackets.swap(Int.random(0..<2*n), Int.random(0..<2*n)) }
        // report if matching or not
        if (matchingBrackets(brackets))
          echo (brackets.join(" ") + " Matching")
        else
          echo (brackets.join(" ") + " not matching")
      }
    }
  }
}


include lib/choose.4th                 ( n1 -- n2)
include lib/ctos.4th                   ( n -- a 1)

 10 constant /[]                       \ maximum number of brackets
/[] string    []                       \ string with brackets
                                       \ create string with brackets
: make[]                               ( --)
  0 dup [] place /[] choose 0 ?do 2 choose 2* [char] [ + c>s [] +place loop
;                                      \ empty string, fill with brackets
                                       \ evaluate string
: eval[]                               ( --)
  [] count 2dup over chars + >r swap type 0
  begin                                \ setup string and count
    over [email protected] <                          \ reached end of string?
  while                                \ if not ..
    dup 0< 0=                          \ unbalanced ]?
  while                                \ if not ..
    over [email protected] [char] \ - negate + swap char+ swap
  repeat                               \ evaluate, goto next character
  r> drop if ."  NOT" then ."  OK" cr drop
;                                      \ evaluate string and print result

make[] eval[]


! $ gfortran -g -O0 -std=f2008 -Wall f.f08 -o f.exe
! $ ./f
!  compiles             syntax error
! :
! :                     ][
! :                     ]][[
! :[[[]]]
! :                     ][[][]][
! :                     ][[]]][[[]
! :                     ]]]][]][[[[[
! :                     ]]]][][]][[[[[
! :                     ][[[]]]]][]][[[[
! :                     [[][]]][]]][[[][[]
! :                     ]]][[][[[[[[[[]]]]]]
! :[[][[[][]]][]]
! :[[[][]][][[[]][]][]]

program balanced_brackets
  implicit none
  integer :: N
  character(len=20) :: brackets, fmt
  write(6,*)'compiles             syntax error'
  call random_seed
  do N=0, 10
     call generate(N, brackets)
     if (balanced(brackets)) then
        fmt = '(a,a20)'
     else
        fmt = '(a,21x,a20)'
     end if
     write(6,fmt)':',brackets
  end do

  brackets = '[[][[[][]]][]]'
  if (balanced(brackets)) then
     fmt = '(a,a20)'
  else
     fmt = '(a,21x,a20)'
  end if
  write(6,fmt)':',brackets

  N = 10
  call generate(N, brackets)
  do while (.not. balanced(brackets)) ! show a balanced set
     call generate(N, brackets)
  end do
  fmt = '(a,a20)'
  write(6,fmt)':',brackets

contains

  logical function balanced(s)
    implicit none
    character(len=*), intent(in) :: s
    integer :: i, a, n
    n = len_trim(s)
    a = 0
    balanced = .true.
    do i=1, n
       if (s(i:i) == '[') then
          a = a+1
       else
          a = a-1
       end if
       balanced = balanced .and. (0 <= a)
    end do
  end function balanced

  subroutine generate(N, s)
    implicit none
    integer, intent(in) :: N
    character(len=*), intent(out) :: s
    integer :: L, R, i
    real, dimension(2*N) :: harvest
    character :: c
    i = 1
    L = 0
    R = 0
    s = ' '
    call random_number(harvest)
    do while ((L < N) .and. (R < N))
       if (harvest(i) < 0.5) then
          L = L+1
          s(i:i) = '['
       else
          R = R+1
          s(i:i) = ']'
       end if
       i = i+1
    end do
    c = merge('[', ']', L < N)
    do while (i <= 2*N)
       s(i:i) = c
       i = i+1
    end do
  end subroutine generate
end program balanced_brackets


' FB 1.05.0 Win64

Function isBalanced(s As String) As Boolean
  If s = "" Then Return True
  Dim countLeft As Integer = 0 '' counts number of left brackets so far unmatched
  Dim c As String
  For i As Integer = 1 To Len(s)
    c = Mid(s, i, 1)
    If  c = "[" Then
      countLeft += 1
    ElseIf countLeft > 0 Then
      countLeft -= 1
    Else
      Return False
    End If
  Next
  Return countLeft = 0
End Function

' checking examples in task description
Dim brackets(1 To 7) As String = {"", "[]", "][", "[][]", "][][", "[[][]]", "[]][[]"}
For i As Integer = 1 To 7
  Print IIf(brackets(i) <> "", brackets(i), "(empty)"); Tab(10); IIf(isBalanced(brackets(i)), "OK", "NOT OK")
Next

' checking 7 random strings of brackets of length 8 say
Randomize
Dim r As Integer '' 0 will signify "[" and 1 will signify "]"
Dim s As String
For i As Integer = 1 To 7
  s = Space(8)
  For j As Integer = 1 To 8
    r = Int(Rnd * 2)
    If r = 0 Then
      Mid(s, j) = "["
    Else
      Mid(s, j) = "]"
    End If
  Next j
  Print s; Tab(10); IIf(isBalanced(s), "OK", "NOT OK")
Next i

Print
Print "Press any key to quit"
Sleep


'Altered to prevent lines starting with ']' or ending with '[' being generated as they can't work

siNumberOfBrackets As Short = 20              'Maximum amount of brackets in a line
siNumberOfLines As Short = 20                 'Amount of lines to test

'----

Public Sub Main()
Dim sBrks As String[] = GenerateBrackets()    'Get random array to check
Dim sTemp, sHold, sWork As String             'Working variables
Dim siCount As Short                          'Counter

For Each sTemp In sBrks                       'For each line in the sBrk array (e.g. '[][][][[[[]][]]]')
  sWork = sTemp                               'Make sWork = sTemp
  Repeat                                      'Repeat
    sHold = sWork                             'Make sHold = sWork
    sWork = Replace(sWork, "[]", "")          'Remove all brackets that match '[]'
  Until sHold = sWork                         'If sHold = sWork then there are no more '[]' matches

  If sWork = "" Then                          'So if all the brackets 'Nested' correctly sWork will be empty
      Print "    OK ";                        'Print 'OK'
  Else                                        'Else they did not all match
    Print "NOT OK ";                          'So print 'NOT OK'
  Endif

  For siCount = 1 To Len(sTemp)               'Loop through the line of brackets
    Print Mid(sTemp, siCount, 1) & " ";       'Print each bracket + a space to make it easier to read
  Next
  Print                                       'Print a new line
Next

End

'----

Public Sub GenerateBrackets() As String[]     'Generates an array of random quantities of '[' and ']'
Dim siQty As New Short[]                      'To store the random number (of brackets) to put in a line
Dim sBrk As New String[]                      'To store the lines of brackets
Dim siNum, siEnd, siLoop As Short             'Various counters
Dim sTemp As String                           'Temp string

Repeat                                        'Repeat
  siNum = Rand(0, siNumberOfBrackets)         'Pick a number between 0 and the total number of brackets requested
  If Even(siNum) Then siQty.Add(siNum)        'If the number is even then add the number to siQty
Until siQty.Count = siNumberOfLines           'Keep going until we have the number of lines requested

For Each siNum In siQty                       'For each number in siQty..(e.g. 6)
  Do
    siEnd = Rand(0, 1)                        'Generate a 0 or a 1
    If siEnd = 0 Then sTemp &= "["            'If '0' then add a '[' bracket
    If siEnd = 1 Then sTemp &= "]"            'If '1' then add a ']' bracket

    If siNum = 0 Then                         'If siNum = 0 then..
      sBrk.Add("")                            'Add '0' to the array
        sTemp = ""                            'Clear sTemp
        Break                                 'Exit the Do Loop
    Endif

    If Len(sTemp) = siNum Then                'If the length of sTemp = the required amount then..
      If sTemp Not Begins "]" And sTemp Not Ends "[" Then  'Check to see that sTemp does not start with "]" and does not end with a "["
        sBrk.Add(sTemp)                       'Add it to the array
        sTemp = ""                            'Clear sTemp
        Break                                 'Exit the Do Loop
      Else                                    'Else
        sTemp = ""                            'Clear sTemp
      End If                                  'Try again!
    Endif
  Loop
Next

Return sBrk                                   'Return the sBrk array

End


Balanced := function(L)
    local c, r;
    r := 0;
    for c in L do
        if c = ']' then
            r := r - 1;
            if r < 0 then
                return false;
            fi;
        elif c = '[' then
            r := r + 1;
        fi;
    od;
    return r = 0;
end;

Balanced("");
# true

Balanced("[");
# false

Balanced("]");
# false

Balanced("[]");
# true

Balanced("][");
# false

Balanced("[[][]]");
# true

Balanced("[[[]][]]]");
# false


package main

import (
    "bytes"
    "fmt"
    "math/rand"
    "time"
)

func init() {
    rand.Seed(time.Now().UnixNano())
}

func generate(n uint) string {
    a := bytes.Repeat([]byte("[]"), int(n))
    for i := len(a) - 1; i >= 1; i-- {
        j := rand.Intn(i + 1)
        a[i], a[j] = a[j], a[i]
    }
    return string(a)
}

func testBalanced(s string) {
    fmt.Print(s + ": ")
    open := 0
    for _,c := range s {
        switch c {
        case '[':
            open++
        case ']':
            if open == 0 {
                fmt.Println("not ok")
                return
            }
            open--
        default:
            fmt.Println("not ok")
            return
        }
    }
    if open == 0 {
        fmt.Println("ok")
    } else {
        fmt.Println("not ok")
    }
}

func main() {
    rand.Seed(time.Now().UnixNano())
    for i := uint(0); i < 10; i++ {
        testBalanced(generate(i))
    }
    testBalanced("()")
}


def random = new Random()

def factorial = { (it > 1) ? (2..it).inject(1) { i, j -> i*j } : 1 }

def makePermutation;
makePermutation = { string, i ->
    def n = string.size()
    if (n < 2) return string
    def fact = factorial(n-1)
    assert i < fact*n

    def index = i.intdiv(fact)
    string[index] + makePermutation(string[0..<index] + string[(index+1)..<n], i % fact)
}

def randomBrackets = { n ->
    if (n == 0) return ''
    def base = '['*n + ']'*n
    def p = random.nextInt(factorial(n*2))
    makePermutation(base, p)
}


isMatching :: String -> Bool
isMatching = null . foldl aut []
  where
    aut ('[':s) ']' = s
    -- aut ('{':s) '}' = s -- automaton could be extended
    aut s x = x:s


procedure main(arglist)
every s := genbs(!arglist) do
   write(image(s), if isbalanced(s) then " is balanced." else " is unbalanced")
end

procedure isbalanced(s) # test if a string is balanced re: []
return (s || " ") ? (bal(,'[',']') = *s+1)
end

procedure genbs(i)  # generate strings of i pairs of []
s := ""
every 1 to i do s ||:= "[]"       # generate i pairs
every !s := ?s                    # shuffle
return s
end


bracketDepth    =:  '[]' -&(+/\)/@:(=/) ]
checkBalanced   =:  _1 [email protected] bracketDepth
genBracketPairs =:  ([email protected]# { ])@#"0 1&'[]'          NB. bracket pairs in arbitrary order


public class BalancedBrackets {

    public static boolean hasBalancedBrackets(String str) {
        int brackets = 0;
        for (char ch : str.toCharArray()) {
            if (ch == '[') {
                brackets++;
            } else if (ch == ']') {
                brackets--;
            } else {
                return false;   // non-bracket chars
            }
            if (brackets < 0) {   // closing bracket before opening bracket
                return false;
            }
        }
        return brackets == 0;
    }

    public static String generateBalancedBrackets(int n) {
        assert n % 2 == 0;   // if n is odd we can't match brackets
        char[] ans = new char[n];
        int openBracketsLeft = n / 2;
        int unclosed = 0;
        for (int i = 0; i < n; i++) {
            if (Math.random() >= 0.5 && openBracketsLeft > 0 || unclosed == 0) {
                ans[i] = '[';
                openBracketsLeft--;
                unclosed++;
            } else {
                ans[i] = ']';
                unclosed--;
            }
        }
        return String.valueOf(ans);
    }

    public static void main(String[] args) {
        for (int i = 0; i <= 16; i += 2) {
            String brackets = generateBalancedBrackets(i);
            System.out.println(brackets + ": " + hasBalancedBrackets(brackets));
        }

        String[] tests = {"", "[]", "][", "[][]", "][][", "[[][]]", "[]][[]"};
        for (String test : tests) {
            System.out.println(test + ": " + hasBalancedBrackets(test));
        }
    }
}


function shuffle(str) {
  var a = str.split(''), b, c = a.length, d
  while (c) b = Math.random() * c-- | 0, d = a[c], a[c] = a[b], a[b] = d
  return a.join('')
}

function isBalanced(str) {
  var a = str, b
  do { b = a, a = a.replace(/\[\]/g, '') } while (a != b)
  return !a
}

var M = 20
while (M-- > 0) {
  var N = Math.random() * 10 | 0, bs = shuffle('['.repeat(N) + ']'.repeat(N))
  console.log('"' + bs + '" is ' + (isBalanced(bs) ? '' : 'un') + 'balanced')
}


using Printf

function balancedbrackets(str::AbstractString)
    i = 0
    for c in str
        if c == '[' i += 1 elseif c == ']' i -=1 end
        if i < 0 return false end
    end
    return i == 0
end

brackets(n::Integer) = join(shuffle(collect(Char, "[]" ^ n)))

for (test, pass) in map(x -> (x, balancedbrackets(x)), collect(brackets(i) for i = 0:8))
    @printf("%22s%10s\n", test, pass ? "pass" : "fail")
end


"[[]][]]"

%acc 0 !acc
%flag false !flag

len [
    get tochar dup
    "[" == [$acc 1 + !acc] if
    "]" == [$acc 1 - !acc] if
    $acc 0 < [true !flag] if
    ] for

print

$acc 0 # $flag or ( [" is NOT ok"] [" is OK"] ) if
print

" " input


import java.util.Random

fun isBalanced(s: String): Boolean {
    if (s.isEmpty()) return true
    var countLeft = 0  // number of left brackets so far unmatched
    for (c in s) {
        if (c == '[') countLeft++
        else if (countLeft > 0) countLeft--
        else return false
    }
    return countLeft == 0
}

fun main(args: Array<String>) {
    println("Checking examples in task description:")
    val brackets = arrayOf("", "[]", "][", "[][]", "][][", "[[][]]", "[]][[]")
    for (b in brackets) {
        print(if (b != "") b else "(empty)")
        println("\t  " + if (isBalanced(b)) "OK" else "NOT OK")
    }
    println()

    println("Checking 7 random strings of brackets of length 8:")
    val r = Random()
    (1..7).forEach {
        var s = ""
        for (j in 1..8) {
            s += if (r.nextInt(2) == 0) '[' else ']'
        }
        println("$s  " + if (isBalanced(s)) "OK" else "NOT OK")
    }
}


(include "string")

(defn bool balanced (std::string s)
  (def bal 0)
  (foreach c s
    (if (== c #\[) (++ bal)
      (if (== c #\]) (-- bal)))
    (if (< bal 0) (return false)))
  (return (== bal 0)))

(main
  (decl std::string (at tests) |{"", "[]", "[][]", "[[][]]", "][", "][][", "[]][[]"}|)
  (pr std::boolalpha)
  (foreach x tests
    (prn x "\t" (balanced x))))


define randomparens(num::integer,open::string='[',close::string=']') => {
    local(out) = array

    with i in 1 to #num do {
        #out->insert(']', integer_random(1,#out->size || 1))
        #out->insert('[', integer_random(1,#out->size || 1))
    }
    return #out->join
}

define validateparens(input::string,open::string='[',close::string=']') => {
    local(i) = 0
    #input->foreachcharacter => {
        #1 == #open ? #i++
        #1 == #close && --#i < 0 ? return false
    }
    return #i == 0 ? true | false
}

with i in 1 to 10
let input = randomparens(#i)
select #input + ' = ' + validateparens(#input)


print "Supplied examples"
for i =1 to 7
    read test$
    print "The string '"; test$; "' is "; validString$( test$)
next i
print
data "", "[]", "][","[][]","][][","[[][]]","[]][[]"

print "Random generated examples"
for example =1 to 10
    test$ =generate$( int( 1 +10 *rnd(1)))
    print "The string '"; test$; "' is "; validString$( test$)
next example
end

function validString$( in$)
    if left$( in$, 1) <>"[" and len( test$) <>0 then
        validString$ ="not OK. Opens wrongly."
        exit function
    end if
    paired =0
    for i =1 to len( in$)
        c$ =mid$( in$, i, 1)
        if c$ ="[" then paired =paired +1
        if c$ ="]" then paired =paired -1
        if paired <0 then
            exit for
        end if
    next i
    if ( lBr =rBr) and ( paired >=0) then validString$ ="OK." else validString$ ="not OK. Unbalanced."
end function

function generate$( N)
    lBr =0
    rBr =0
    '   choose at random until N of one type generated
    while ( lBr <N) and ( rBr <N)
        select case int( 1.5 +rnd( 1))
            case 1
                lBr =lBr +1
                generate$ =generate$ +"["
            case 2
                rBr =rBr +1
                generate$ =generate$ +"]"
        end select
    wend
    '   now pad with the remaining other brackets
    if lBr =N then
        generate$ =generate$ +string$( N -rBr, "]")
    else
        generate$ =generate$ +string$( N -lBr, "[")
    end if
end function

function string$( n, c$)
    for i =1 to n
        op$ =op$ +c$
    next i
    string$ =op$
end function

end


function isBalanced(s)
  --Lua pattern matching has a 'balanced' pattern that matches sets of balanced characters.
  --Any two characters can be used.
  return s:gsub('%b[]','')=='' and true or false
end

function randomString()
  math.randomseed(os.time())
  math.random()math.random()math.random()math.random()
  local tokens={'[',']'}
  local result={}
  for i=1,8 do
    table.insert(result,tokens[math.random(1,2)])
  end
  return table.concat(result)
end

local RS=randomString()
print(RS)
print(isBalanced(RS))


(* Generate open/close events. *)
gen[n_] := RandomSample[Table[{1, -1}, {n}] // Flatten]

(* Check balance. *)
check[lst_] := And @@ (# >= 0 & /@ Accumulate[lst])

(* Do task for string with n opening and n closing brackets. *)
doString[n_] := (
  lst = gen[n];
  str = StringJoin[lst /. {1 -> "[", -1 -> "]"}];
  Print[str <> If[match[lst, 0],
     "  is balanced.",
     "  is not balanced."]])


brack(s) := block(
   [n: slength(s), r: 0, c],
   catch(
      for i thru n do (
         if cequal(c: charat(s, i), "]") then (if (r: r - 1) < 0 then throw(false))
         elseif cequal(c, "[") then r: r + 1
      ),
      is(r = 0)
   )
)$

brack("");
true

brack("[");
false

brack("]");
false

brack("[]");
true

brack("][");
false

brack("[[][]]");
true

brack("[[[]][]]]");
false


:- module balancedbrackets.
:- interface.

:- import_module io.

:- pred main(io::di, io::uo) is det.

:- import_module list, random, char.

:- pred brackets(int::in,list(char)::out,supply::mdi,supply::muo) is det.

:- pred imbalance(list(char)::in,int::out) is semidet.
:- pred balanced(list(char)::in) is semidet.

:- implementation.

:- import_module int.

imbalance([],0).
imbalance(['['|T],N) :- imbalance(T,N+1).
imbalance([']'|T],N) :- N > 0, imbalance(T,N-1).

balanced(S) :- imbalance(S,0).

brackets(N,S,!RS) :-
    (
	N < 1 -> S is []
    ;   random(0,2,R,!RS),
	( R is 0 -> S is ['['|T], brackets(N-1,T,!RS)
	; S is [']'|T], brackets(N-1,T,!RS))).

main(!IO) :-
    random.init(0,RS),
    brackets(4,S,RS,_),
    print(S,!IO),
    (
	balanced(S) -> print(" is balanced\n",!IO)
    ;   print(" is unbalanced\n", !IO)
    ).


isBalanced = function(str)
	level = 0
	for c in str
		if c == "[" then level = level + 1
		if c == "]" then level = level - 1
		if level < 0 then return false
	end for
	return level == 0
end function


MODULE Brackets;
IMPORT IO, Lib;

CONST MaxN = 4;

PROCEDURE DoTest( N : CARDINAL);
VAR
  brStr : ARRAY [0..2*MaxN] OF CHAR; (* string of brackets *)
  verdict : ARRAY [0..2] OF CHAR;
  br : CHAR;
  k, nL, nR, randNum : CARDINAL;
  count : INTEGER;
BEGIN
  k := 0; (* index into brStr *)
  nL := N; nR := N; (* number of left/right brackets remaining *)
  WHILE (nL > 0) AND (nR > 0) DO
    randNum := Lib.RANDOM( nL + nR);
    IF (randNum < nL) THEN brStr[k] := '['; DEC(nL);
                      ELSE brStr[k] := ']'; DEC(nR); END;
    INC(k);
  END;
  (* Here when only one kind of bracket is possible *)
  IF (nL = 0) THEN br := ']' ELSE br := '['; END;
  WHILE (k < 2*N) DO brStr[k] := br; INC(k); END;
  brStr[k] := 0C; (* null to mark end of string *)

  (* Test for balance *)
  count := 0;
  k := 0;
  REPEAT
    IF brStr[k] = '[' THEN INC( count) ELSE DEC( count) END;
    INC( k);
  UNTIL (count < 0) OR (k = 2*N);
  IF (count < 0) THEN verdict := 'no' ELSE verdict := 'yes' END;
  IO.WrStr( brStr); IO.WrStr(' '); IO.WrStr( verdict);
  IO.WrLn;
END DoTest;

(* Main routine *)
VAR
  j : CARDINAL;
BEGIN
  Lib.RANDOMIZE;
  FOR j := 1 TO 10 DO
    DoTest( Lib.RANDOM(MaxN) + 1);
  END;
END Brackets.


import Nanoquery.Util

def gen(N)
	txt = {"[", "]"} * N
	txt = new(Random).shuffle(txt)
	return "".join("", txt)
end

def balanced(txt)
	braced = 0
	for ch in txt
		if ch = "["
			braced += 1
		else if ch = "]"
			braced -= 1
		end

		if braced < 0
			return false
		end
	end
	return braced = 0
end

// unlike Python, the range function is inclusive in Nanoquery
for N in range(1, 10)
	txt = gen(N)
	if balanced(txt)
		println format("%-22s is balanced", txt)
	else
		println format("%-22s is not balanced", txt)
	end
end


from random import random, randomize, shuffle
from strutils import repeat

randomize()

proc gen(n: int): string =
  result = "[]".repeat(n)
  shuffle(result)

proc balanced(txt: string): bool =
  var b = 0
  for c in txt:
    case c
    of '[':
      inc(b)
    of ']':
      dec(b)
      if b < 0: return false
    else: discard
  b == 0

for n in 0..9:
  let s = gen(n)
  echo "'", s, "' is ", (if balanced(s): "balanced" else: "not balanced")


MODULE BalancedBrackets;
IMPORT
  Object,
  Object:Boxed,
  ADT:LinkedList,
  ADT:Storable,
  IO,
  Out := NPCT:Console;

TYPE
  (* CHAR is not boxed in the standard lib *)
  (* so make a boxed char *)
  Character* = POINTER TO CharacterDesc;
  CharacterDesc* = RECORD
    (Boxed.ObjectDesc)
    c: CHAR;
  END;

(* Method for a boxed char *)
PROCEDURE (c: Character) INIT*(x: CHAR);
BEGIN
  c.c := x;
END INIT;

PROCEDURE NewCharacter*(c: CHAR): Character;
VAR
  x: Character;
BEGIN
    NEW(x);x.INIT(c);RETURN x
END NewCharacter;

PROCEDURE (c: Character) ToString*(): STRING;
BEGIN
  RETURN Object.NewLatin1Char(c.c);
END ToString;

PROCEDURE (c: Character) Load*(r: Storable.Reader) RAISES IO.Error;
BEGIN
  r.ReadChar(c.c);
END Load;

PROCEDURE (c: Character) Store*(w: Storable.Writer) RAISES IO.Error;
BEGIN
  w.WriteChar(c.c);
END Store;

PROCEDURE (c: Character) Cmp*(o: Object.Object): LONGINT;
BEGIN
  IF c.c < o(Character).c THEN RETURN -1
  ELSIF c.c = o(Character).c THEN RETURN 0
  ELSE RETURN 1
  END
END Cmp;
(* end of methods for a boxed char *)

PROCEDURE CheckBalance(str: STRING): BOOLEAN;
VAR
  s: LinkedList.LinkedList(Character);
  chars: Object.CharsLatin1;
  n, x: Boxed.Object;
  i,len: LONGINT;
BEGIN
  i := 0;
  chars := str(Object.String8).CharsLatin1();
  len := str.length;
  s := NEW(LinkedList.LinkedList(Character));
  WHILE (i < len) & (chars[i] # 0X) DO
    IF s.IsEmpty() THEN
      s.Append(NewCharacter(chars[i]))  (* Push character *)
    ELSE
      n := s.GetLast(); (* top character *)
      WITH
        n: Character DO
          IF (chars[i] = ']') & (n.c = '[') THEN
            x := s.RemoveLast(); (* Pop character *)
            x := NIL
          ELSE
            s.Append(NewCharacter(chars[i]))
          END
        ELSE RETURN FALSE
      END (* WITH *)
    END;
    INC(i)
  END;
  RETURN s.IsEmpty()
END CheckBalance;

PROCEDURE Do;
VAR
  str: STRING;
BEGIN
  str := "[]";Out.String(str + ":> "); Out.Bool(CheckBalance(str));Out.Ln;
  str := "[][]";Out.String(str + ":> ");Out.Bool(CheckBalance(str));Out.Ln;
  str := "[[][]]";Out.String(str + ":> ");Out.Bool(CheckBalance(str));Out.Ln;
  str := "][";Out.String(str + ":> ");Out.Bool(CheckBalance(str));Out.Ln;
  str := "][][";Out.String(str + ":> ");Out.Bool(CheckBalance(str));Out.Ln;
  str := "[]][[]";Out.String(str + ":> ");Out.Bool(CheckBalance(str));Out.Ln;
END Do;

BEGIN
  Do
END BalancedBrackets.


bundle Default {
  class Balanced {
    function : IsBalanced(text : String) ~ Bool {
      level := 0;
      each(i : text) {
        character := text->Get(i);
        if(character = ']') {
          if(level = 0) {
            return false;
          };
          level -= 1;
        };

        if(character = '[') {
          level += 1;
        };
      };

      return level = 0;
    }

    function : Main(args : String[]) ~ Nil {
      ": "->Print(); IsBalanced("")->PrintLine();
      "[]: "->Print(); IsBalanced("[]")->PrintLine();
      "[][]: "->Print(); IsBalanced("[][]")->PrintLine();
      "[[][]]: "->Print(); IsBalanced("[[][]]")->PrintLine();
      "][: "->Print(); IsBalanced("][")->PrintLine();
      "][][: "->Print(); IsBalanced("][][")->PrintLine();
      "[]][[]: "->Print(); IsBalanced("[]][[]")->PrintLine();
    }
  }
}


let generate_brackets n =
  let rec aux i acc =
    if i <= 0 then acc else
      aux (pred i) ('['::']'::acc)
  in
  let brk = aux n [] in
  List.sort (fun _ _ -> (Random.int 3) - 1) brk

let is_balanced brk =
  let rec aux = function
    | [], 0 -> true
    | '['::brk, level -> aux (brk, succ level)
    | ']'::brk, 0 -> false
    | ']'::brk, level -> aux (brk, pred level)
    | _ -> assert false
  in
  aux (brk, 0)

let () =
  let n = int_of_string Sys.argv.(1) in
  Random.self_init();
  let brk = generate_brackets n in
  List.iter print_char brk;
  Printf.printf " %B\n" (is_balanced brk);
;;


String method: isBalanced
| c |
   0 self forEach: c [
      c '[' == ifTrue: [ 1+ continue ]
      c ']' <> ifTrue: [ continue ]
      1- dup 0 < ifTrue: [ drop false return ]
      ]
   0 == ;

: genBrackets(n)
   "" #[ "[" "]" 2 rand 2 == ifTrue: [ swap ] rot + swap + ] times(n) ;


tests = .array~of("", "[]", "][", "[][]", "][][", "[[][]]", "[]][[]")

-- add some randomly generated tests
loop i = 1 to 8
    tests~append(generateBrackets(i))
end

loop test over tests
    say test":" checkbrackets(test)
end

::routine checkBrackets
  use arg input
  -- counter of bracket groups.  Must be 0 at end to be valid
  groups = 0

  -- loop over all of the characters
  loop c over input~makearray("")
      if c == '[' then groups += 1
      else if c == ']' then groups -= 1
      else return .false  -- non-bracket char found
      -- check for a close occurring before an open
      if groups < 0 then return .false
  end
  -- should be zero at the end
  return groups == 0

-- generate a string with n pairs of brackets
::routine generateBrackets
  use arg n

  answer = .mutablebuffer~new(,2*n)

  openBracketsNeeded = n
  unclosedBrackets = 0
  loop while answer~length < 2 * n
      if random(0, 1) & openBracketsNeeded > 0 | unclosedBrackets == 0 then do
          answer~append('[')
          openBracketsNeeded -= 1
          unclosedBrackets += 1
      end
      else do
          answer~append(']')
          unclosedBrackets -= 1
      end
  end
  return answer~string


function CheckBrackets(string s) as bool
'=======================================
  sys co, le=len s
  byte b at strptr s
  indexbase 0
  for i=0 to <le
    select b(i)
    case "[" : co++
    case "]" : co--
    end select
    if co<0 then return 0
  next
  if co=0 then return 1
end function

'TEST
'====

print CheckBrackets ""    '1
print CheckBrackets "["   '0
print CheckBrackets "]"   '0
print CheckBrackets "[]"  '1
print CheckBrackets "[[]" '0
print CheckBrackets "[]]" '0
print CheckBrackets "[][]"'1
print CheckBrackets "]["  '0


balanced(s)={
  my(n=0,v=Vecsmall(s));
  for(i=1,#v,
    if(v[i]==91,
      n++
    ,
      if(v[i]==93 && n, n--, return(0))
    )
  );
  !n
};
rnd(n)=Strchr(vectorsmall(n,i,if(random(2),91,93)))
forstep(n=0,10,2,s=rnd(n);print(s"\t"if(balanced(s),"true","false")))


sub generate {
    my $n = shift;
    my $str = '[' x $n;
    substr($str, rand($n + $_), 0) = ']' for 1..$n;
    return $str;
}

sub balanced {
    shift =~ /^ (\[ (?1)* \])* $/x;
}

for (0..8) {
    my $input = generate($_);
    print balanced($input) ? " ok:" : "bad:", " '$input'\n";
}


with javascript_semantics
function check_brackets(sequence s)
integer level = 0
    for i=1 to length(s) do
        switch s[i]
            case '[': level += 1
            case ']': level -= 1
                      if level<0 then return false end if
        end switch
    end for
    return (level=0)
end function

sequence s
constant ok = {"not ok","ok"}

for i=1 to 10 do
    for j=1 to 2 do
        s = shuffle(join(repeat("[]",i-1),""))
        printf(1,"%s %s\n",{s,ok[check_brackets(s)+1]})
    end for
end for


"[[]][]"
0 var acc

len for
    get dup
    '[' == if acc 1 + var acc endif
    ']' == if acc 1 - var acc endif
    acc 0 < if exitfor endif
endfor

print
acc 0 < if
    " is NOT ok"
else
    " is OK"
endif
print


#!/usr/bin/php
<?php

# brackets generator
function bgenerate ($n) {
    if ($n==0) return '';
    $s = str_repeat('[', $n) . str_repeat(']', $n);
    return str_shuffle($s);
}

function printbool($b) {return ($b) ? 'OK' : 'NOT OK';}

function isbalanced($s) {
    $bal = 0;
    for ($i=0; $i < strlen($s); $i++) {
        $ch = substr($s, $i, 1);
        if ($ch == '[') {
            $bal++;
        } else {
            $bal--;
        }
        if ($bal < 0) return false;
    }
    return ($bal == 0);
}

# test parameters are N (see spec)
$tests = array(0, 2,2,2, 3,3,3, 4,4,4,4);

foreach ($tests as $v) {
    $s = bgenerate($v);
    printf("%s\t%s%s", $s, printbool(isbalanced($s)), PHP_EOL);
}


(load "@lib/simul.l")  # For 'shuffle'

(de generateBrackets (N)
   (shuffle (make (do N (link "[" "]")))) )

(de checkBrackets (S)
   (let N 0
      (for C S
         (if (= C "[")
            (inc 'N)
            (if2 (= C "]") (=0 N)
               (off N)
               (dec 'N) ) ) )
      (=0 N) ) )

(for N 10
   (prinl (if (checkBrackets (prin (generateBrackets N))) " OK" "not OK")) )


*process m or(!) s attributes source;
 cb: Proc Options(main);
 /* PL/I program to check for balanced brackets [] ********************
 * 07.12.2013 Walter Pachl translated from REXX Version 2
 *********************************************************************/
 Dcl v Char(20) Var;
 Dcl (i,j) Bin Fixed(31);
 Dcl r Bin Float(53);

 Call testbal('');                  /* first some user written tests */
 Call testbal('[][][][[]]');
 Call testbal('[][][][[]]][');
 Call testbal('[');
 Call testbal(']');
 Call testbal('[]');
 Call testbal('][');
 Call testbal('][][');
 Call testbal('[[]]');
 Call testbal('[[[[[[[]]]]]]]');
 Call testbal('[[[[[]]]][]');
 Call testbal('[][]');
 Call testbal('[]][[]');
 Call testbal(']]][[[[]');
 Call testbal('[[a]][b]');
 Put Edit(' ')(Skip,a);
 r=random(12345);                      /* then some generated ones   */
 Do i=1 To 10;
   v='';
   Do j=1 To 10;
     r=random();
     If r>0.5 Then v=v!!']';
              Else v=v!!'[';
     End;
   Call testbal(v);
   End;
 Return;

 testbal: Proc(s);          /* test the given string and show result */
 Dcl s Char(*);
 Dcl yesno(0:1) Char(20) Var Init('unbalanced','  balanced');
 Put Edit(yesno(checkbal(s)),''''!!s!!'''')(Skip,a,x(1),a);
 End;

 checkBal: proc(s) Returns(Bin Fixed(31));
                                    /*check for balanced brackets [] */
 Dcl s Char(*);
 Dcl nest Bin Fixed(31) Init(0);
 Dcl i Bin Fixed(31);
 Do i=1 To length(s);
   Select(substr(s,i,1));
     When('[') nest+=1;
     When(']') Do;
       If nest=0 Then return(0);
       nest-=1;
       End;
     Otherwise;
     End;
   End;
 Return(nest=0);
 End;

 End;


function Get-BalanceStatus ( $String )
    {
    $Open = 0
    ForEach ( $Character in [char[]]$String )
        {
        switch ( $Character )
            {
            "["     { $Open++ }
            "]"     { $Open-- }
            default { $Open = -1 }
            }
        #  If Open drops below zero (close before open or non-allowed character)
        #    Exit loop
        If ( $Open -lt 0 ) { Break }
        }
    $Status = ( "NOT OK", "OK" )[( $Open -eq 0 )]
    return $Status
    }


rosetta_brackets :-
	test_brackets([]),
	test_brackets(['[',']']),
	test_brackets(['[',']','[',']']),
	test_brackets(['[','[',']','[',']',']']),
	test_brackets([']','[']),
	test_brackets([']','[',']','[']),
	test_brackets(['[',']',']','[','[',']']).

balanced_brackets :-
	gen_bracket(2,  B1, []), test_brackets(B1),
	gen_bracket(4,  B2, []), test_brackets(B2),
	gen_bracket(4,  B3, []), test_brackets(B3),
	gen_bracket(6,  B4, []), test_brackets(B4),
	gen_bracket(6,  B5, []), test_brackets(B5),
	gen_bracket(8,  B6, []), test_brackets(B6),
	gen_bracket(8,  B7, []), test_brackets(B7),
	gen_bracket(10, B8, []), test_brackets(B8),
	gen_bracket(10, B9, []), test_brackets(B9).

test_brackets(Goal) :-
	(   Goal = [] -> write('(empty)'); maplist(write, Goal)),
	(   balanced_brackets(Goal, []) ->
	    writeln(' succeed')
	;
	    writeln(' failed')
	).

% grammar of balanced brackets
balanced_brackets --> [].

balanced_brackets -->
	['['],
	balanced_brackets,
	[']'].

balanced_brackets -->
	['[',']'],
	balanced_brackets.

% generator of random brackets
gen_bracket(0) --> [].

gen_bracket(N) -->
	{N1 is N - 1,
	 R is random(2)},
	bracket(R),
	gen_bracket(N1).

bracket(0) --> ['['].
bracket(1) --> [']'].


Procedure.s Generate(N)
  For i=1 To N
    sample$+"[]"
  Next
  For i=Len(sample$)-1 To 2 Step -1
    r=Random(i-1)+1
    If r<>i
      a.c=PeekC(@sample$+r*SizeOf(Character))
      b.c=PeekC(@sample$+i*SizeOf(Character))
      PokeC(@sample$+r*SizeOf(Character), b)
      PokeC(@sample$+i*SizeOf(Character), a)
    EndIf
  Next
  ProcedureReturn sample$
EndProcedure

Procedure Balanced(String$)
  Protected *p.Character, cnt
  *p=@String$
  While *p\c
    If *p\c='['
      cnt+1
    ElseIf *p\c=']'
      cnt-1
      If cnt<0: Break: EndIf
    EndIf
    *p+SizeOf(Character)
  Wend
  If cnt=0
    ProcedureReturn #True
  EndIf
EndProcedure

;- Test code
OpenConsole()
For i=1 To 5
  TestString$ = Generate(i)
  Print(TestString$)
  If Balanced(TestString$)
    PrintN(" is balanced.")
  Else
    PrintN(" is not balanced")
  EndIf
Next


>>> def gen(N):
...     txt = ['[', ']'] * N
...     random.shuffle( txt )
...     return ''.join(txt)
...
>>> def balanced(txt):
...     braced = 0
...     for ch in txt:
...         if ch == '[': braced += 1
...         if ch == ']':
...             braced -= 1
...             if braced < 0: return False
...     return braced == 0
...
>>> for txt in (gen(N) for N in range(10)):
...     print ("%-22r is%s balanced" % (txt, '' if balanced(txt) else ' not'))
...
''                     is balanced
'[]'                   is balanced
'[][]'                 is balanced
'][[[]]'               is not balanced
'[]][[][]'             is not balanced
'[][[][]]]['           is not balanced
'][]][][[]][['         is not balanced
'[[]]]]][]][[[['       is not balanced
'[[[[]][]]][[][]]'     is balanced
'][[][[]]][]]][[[[]'   is not balanced


(define balanced-brackets-0
  []      0   -> true
  []      _   -> false
  [#\[|R] Sum -> (balanced-brackets-0 R (+ Sum 1))
  _       0   -> false
  [_  |R] Sum -> (balanced-brackets-0 R (- Sum 1)))

(define balanced-brackets
  "" -> true
  S  -> (balanced-brackets-0 (explode (INTERN S)) 0))

(balanced-brackets "")

(balanced-brackets "[]")
(balanced-brackets "[][]")
(balanced-brackets "[[][]]")

(balanced-brackets "][")
(balanced-brackets "][][")
(balanced-brackets "[]][[]")


  [ char [ over of
    swap
    char ] swap of
    join shuffle ]      is bracket$ ( n --> $ )

  [ 0 swap witheach
      [ char [ =
        iff 1 else -1 +
        dup 0 < if
          conclude ]
    0 = ]               is balanced ( $ --> b )

  10 times
    [ 20 i 2 * - times sp
      i bracket$ dup echo$
      say " is "
      balanced not if
        [ say "un" ]
      say "balanced."
      cr ]


balanced <- function(str){
  str <- strsplit(str, "")[[1]]
  str <- ifelse(str=='[', 1, -1)
  all(cumsum(str) >= 0) && sum(str) == 0
}


#lang racket

(define (generate n)
  (list->string (shuffle (append* (make-list n '(#\[ #\]))))))

(define (balanced? str)
  (let loop ([l (string->list str)] [n 0])
    (or (null? l)
        (if (eq? #\[ (car l))
          (loop (cdr l) (add1 n))
          (and (> n 0) (loop (cdr l) (sub1 n)))))))

(define (try n)
  (define s (generate n))
  (printf "~a => ~a\n" s (if (balanced? s) "OK" "NOT OK")))

(for ([n 10]) (try n))


sub balanced($s) {
    my $l = 0;
    for $s.comb {
        when "]" {
            --$l;
            return False if $l < 0;
        }
        when "[" {
            ++$l;
        }
    }
    return $l == 0;
}

my $n = prompt "Number of brackets";
my $s = (<[ ]> xx $n).flat.pick(*).join;
say "$s {balanced($s) ?? "is" !! "is not"} well-balanced"


; Functional code
balanced-brackets: [#"[" any balanced-brackets #"]"]
rule: [any balanced-brackets end]
balanced?: func [str][parse str rule]

; Tests
tests: [
	good: ["" "[]" "[][]" "[[]]" "[[][]]" "[[[[[]]][][[]]]]"]
	bad:  ["[" "]" "][" "[[]" "[]]" "[]][[]" "[[[[[[]]]]]]]"]
]

foreach str tests/good [
	if not balanced? str [print [mold str "failed!"]]
]
foreach str tests/bad [
	if balanced? str [print [mold str "failed!"]]
]

repeat i 10 [
	str: random copy/part "[][][][][][][][][][]" i * 2
	print [mold str "is" either balanced? str ["balanced"]["unbalanced"]]
]


/*REXX program checks for balanced brackets     [  ]      ─── some fixed, others random.*/
parse arg seed .                                 /*obtain optional argument from the CL.*/
if datatype(seed,'W')  then call random ,,seed   /*if specified, then use as RANDOM seed*/
@.=0;          yesNo.0= right('not OK', 50)      /*for bad expressions, indent 50 spaces*/
               yesNo.1=           'OK'           /* [↓]  the 14 "fixed"  ][  expressions*/
q=                     ;          call checkBal  q;           say yesNo.result  '«null»'
q= '[][][][[]]'        ;          call checkBal  q;           say yesNo.result  q
q= '[][][][[]]]['      ;          call checkBal  q;           say yesNo.result  q
q= '['                 ;          call checkBal  q;           say yesNo.result  q
q= ']'                 ;          call checkBal  q;           say yesNo.result  q
q= '[]'                ;          call checkBal  q;           say yesNo.result  q
q= ']['                ;          call checkBal  q;           say yesNo.result  q
q= '][]['              ;          call checkBal  q;           say yesNo.result  q
q= '[[]]'              ;          call checkBal  q;           say yesNo.result  q
q= '[[[[[[[]]]]]]]'    ;          call checkBal  q;           say yesNo.result  q
q= '[[[[[]]]][]'       ;          call checkBal  q;           say yesNo.result  q
q= '[][]'              ;          call checkBal  q;           say yesNo.result  q
q= '[]][[]'            ;          call checkBal  q;           say yesNo.result  q
q= ']]][[[[]'          ;          call checkBal  q;           say yesNo.result  q
#=0                                                    /*# additional random expressions*/
          do j=1  until  #==26                         /*gen 26 unique bracket strings. */
          q=translate( rand( random(1,10) ), '][', 10) /*generate random bracket string.*/
          call checkBal q; if result==-1  then iterate /*skip if duplicated expression. */
          say yesNo.result  q                          /*display the result to console. */
          #=#+1                                        /*bump the  expression  counter. */
          end   /*j*/                            /* [↑]  generate 26 random "Q" strings.*/
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
?:        ?=random(0,1);                                     return ? || \?   /*REXX BIF*/
rand:     $=copies(?()?(),arg(1));  _=random(2,length($));   return left($,_-1)substr($,_)
/*──────────────────────────────────────────────────────────────────────────────────────*/
checkBal: procedure expose @.; parse arg y       /*obtain the   "bracket"   expression. */
          if @.y  then return -1                 /*Done this expression before?  Skip it*/
          @.y=1                                  /*indicate expression was processed.   */
          !=0;         do j=1  for length(y);      _=substr(y,j,1)    /*get a character.*/
                       if _=='[' then      !=!+1                      /*bump the nest #.*/
                                 else do;  !=!-1;  if !<0  then return 0;   end
                       end   /*j*/
          return !==0                            /* [↑]  "!" is the nested  ][  counter.*/


nr = 0
while nr < 10
      nr += 1
      test=generate(random(9)+1)
      see "bracket string " + test + " is " + valid(test) + nl
end

func generate n
l = 0 r = 0 output = ""
while l<n and r<n
      switch random(2)
      on 1 l+=1 output+="["
      on 2 r+=1 output+="]"
      off
end
if l=n output+=copy("]",n-r) else output+=copy("]",n-l) ok
return output

func valid q
count = 0
if len(q)=0 return "ok." ok
for x=1 to len(q)
    if substr(q,x,1)="[" count+=1 else count-=1 ok
    if count<0 return "not ok." ok
next
return "ok."


re = /\A     # beginning of string
  (?<bb>     # begin capture group <bb>
    \[       #   literal [
    \g<bb>*  #   zero or more <bb>
    \]       #   literal ]
  )*         # end group, zero or more such groups
\z/x         # end of string

10.times do |i|
  s = (%w{[ ]} * i).shuffle.join
  puts (s =~ re ? " OK: " : "bad: ") + s
end

["[[]", "[]]", "a[ letters[-1] ].xyz[0]"].each do |s|
  t = s.gsub(/[^\[\]]/, "")
  puts (t =~ re ? " OK: " : "bad: ") + s
end


extern crate rand;

trait Balanced {
    /// Returns true if the brackets are balanced
    fn is_balanced(&self) -> bool;
}

impl<'a> Balanced for str {
    fn is_balanced(&self) -> bool {
        let mut count = 0;

        for bracket in self.chars() {
            let change = match bracket {
                '[' => 1,
                ']' => -1,
                _ => panic!("Strings should only contain brackets")
            };

            count += change;
            if count < 0 { return false; }
        }

        count == 0
    }
}

/// Generates random brackets
fn generate_brackets(num: usize) -> String {
    use rand::random;

    (0..num).map(|_| if random() { '[' } else { ']' }).collect()
}

fn main() {
    for i in (0..10) {
        let brackets = generate_brackets(i);

        println!("{}    {}", brackets, brackets.is_balanced())
    }
}


import scala.collection.mutable.ListBuffer
import scala.util.Random

object BalancedBrackets extends App {

  val random = new Random()
  def generateRandom: List[String] = {
    import scala.util.Random._
    val shuffleIt: Int => String = i => shuffle(("["*i+"]"*i).toList).foldLeft("")(_+_)
    (1 to 20).map(i=>(random.nextDouble*100).toInt).filter(_>2).map(shuffleIt(_)).toList
  }

  def generate(n: Int): List[String] = {
    val base = "["*n+"]"*n
    var lb = ListBuffer[String]()
    base.permutations.foreach(s=>lb+=s)
    lb.toList.sorted
  }

  def checkBalance(brackets: String):Boolean = {
    def balI(brackets: String, depth: Int):Boolean = {
      if (brackets == "") depth == 0
      else brackets(0) match {
        case '[' => ((brackets.size > 1) && balI(brackets.substring(1), depth + 1))
        case ']' => (depth > 0) && ((brackets.size == 1) || balI(brackets.substring(1), depth -1))
        case _   => false
      }
    }
    balI(brackets, 0)
  }

  println("arbitrary random order:")
  generateRandom.map(s=>Pair(s,checkBalance(s))).foreach(p=>println((if(p._2) "balanced:   " else "unbalanced: ")+p._1))
  println("\n"+"check all permutations of given length:")
  (1 to 5).map(generate(_)).flatten.map(s=>Pair(s,checkBalance(s))).foreach(p=>println((if(p._2) "balanced:   " else "unbalanced: ")+p._1))
}


(define (balanced-brackets string)
  (define (b chars sum)
    (cond ((< sum 0)
           #f)
          ((and (null? chars) (= 0 sum))
           #t)
          ((null? chars)
           #f)
          ((char=? #\[ (car chars))
           (b (cdr chars) (+ sum 1)))
          ((char=? #\] (car chars))
           (b (cdr chars) (- sum 1)))
          (else
           (#f)))
  (b (string->list string) 0))

(balanced-brackets "")

(balanced-brackets "[]")
(balanced-brackets "[][]")
(balanced-brackets "[[][]]")

(balanced-brackets "][")
(balanced-brackets "][][")
(balanced-brackets "[]][[]")


function varargout=isbb(s)
    st=strsplit(s);
    t=cumsum((st=='[')-(st==']'));
    balanced=and(t>=0) & t(length(t))==0;
    varargout=list(balanced)
endfunction