$ include "seed7_05.s7i";

const func string: generateBrackets (in integer: count) is func
  result
    var string: stri is "";
  local
    var integer: index is 0;
    var integer: pos is 0;
    var char: ch is ' ';
  begin
    stri := "[" mult count & "]" mult count;
    for index range 1 to length(stri) do
      pos := rand(1, length(stri));
      ch := stri[index];
      stri @:= [index] stri[pos];
      stri @:= [pos] ch;
    end for;
  end func;

const func boolean: checkBrackets (in string: test) is func
  result
    var boolean: okay is TRUE;
  local
    var char: ch is ' ';
    var integer: open is 0;
  begin
    for ch range test do
      if ch = '[' then
        incr(open);
      elsif ch = ']' then
        if open = 0 then
          okay := FALSE;
        else
          decr(open);
        end if;
      end if;
    end for;
    okay := open = 0;
  end func;

const proc: main is func
  local
    var integer: n is 0;
    var integer: count is 0;
    var string: stri is "";
  begin
    for n range 0 to 4 do
      for count range 1 to 3 do
        stri := generateBrackets(n);
        writeln(stri <& ": " <& checkBrackets(stri));
      end for;
    end for;
  end func;


func balanced (str) {

    var depth = 0
    str.each { |c|
           if(c=='['){ ++depth }
        elsif(c==']'){ --depth < 0 && return false }
    }

    return !depth
}

for str [']','[','[[]','][]','[[]]','[[]]]][][]]','x[ y [ [] z ]][ 1 ][]abcd'] {
    printf("%sbalanced\t: %s\n", balanced(str) ? "" : "NOT ", str)
}


BEGIN
    INTEGER U;
    U := ININT;
    BEGIN

        TEXT PROCEDURE GENERATE(N); INTEGER N;
        BEGIN
            INTEGER R;
            TEXT T;
            T :- NOTEXT;
            WHILE N > 0 DO BEGIN
                R := RANDINT(1,2,U);
                T :- T & (IF R = 1 THEN "[" ELSE "]");
                N := N - 1;
            END;
            GENERATE :- T;
        END GENERATE;

        BOOLEAN PROCEDURE BALANCED(T); TEXT T;
        BEGIN
            INTEGER LEVEL;
            CHARACTER BRACE;
            BOOLEAN DONE;
            T.SETPOS(1);
            WHILE T.MORE AND NOT DONE DO BEGIN
                BRACE := T.GETCHAR;
                IF BRACE = '[' THEN LEVEL := LEVEL + 1;
                IF BRACE = ']' THEN LEVEL := LEVEL - 1;
                IF LEVEL < 0 THEN DONE := TRUE;
            END;
            BALANCED := LEVEL = 0;
        END BALANCED;

        INTEGER I,M;
        TEXT T;
        FOR I := 1 STEP 1 UNTIL 40 DO BEGIN
            M := RANDINT(0,10,U);
            T :- GENERATE(M);
            IF BALANCED(T) THEN OUTTEXT("    ") ELSE OUTTEXT(" NOT");
            OUTTEXT(" BALANCED: ");
            OUTTEXT(T);
            OUTIMAGE;
        END;

    END;
END


*        Array length              22/02/2017
ARRAYLEN START
         USING ARRAYLEN,12
         LR    12,15               end of prolog
         LA    1,(AEND-A)/L'A      hbound(a)
         XDECO 1,PG+13             edit
         XPRNT PG,L'PG             print
         BR    14                  exit
A        DC    CL6'apple',CL6'orange'   array
AEND     DC    0C
PG       DC    CL25'Array length='      buffer
         END   ARRAYLEN


start:
LDA #(Array_End-Array)   ;evaluates to 13
RTS

Array:
byte "apple",0
byte "orange",0
Array_End:


start:
MOVE.B #(Array_End-Array)   ;evaluates to 14
RTS

Array:
DC.B "apple",0
even
DC.B "orange",0
even
Array_End:


fun isBalanced s = checkBrackets 0 (String.explode s)
and checkBrackets 0 [] = true
  | checkBrackets _ [] = false
  | checkBrackets ~1 _ = false
  | checkBrackets counter (#"["::rest) = checkBrackets (counter + 1) rest
  | checkBrackets counter (#"]"::rest) = checkBrackets (counter - 1) rest
  | checkBrackets counter (_::rest) = checkBrackets counter rest


mata
function random_brackets(n) {
	return(invtokens(("[","]")[runiformint(1,2*n,1,2)],""))
}

function is_balanced(s) {
	n = strlen(s)
	if (n==0) return(1)
	a = runningsum(92:-ascii(s))
	return(all(a:>=0) & a[n]==0)
}
end


/* ARM assembly AARCH64 Raspberry PI 3B */
/*  program lenAreaString64.s   */

/*******************************************/
/* Constantes file                         */
/*******************************************/
/* for this file see task include a file in language AArch64 assembly*/
.include "../includeConstantesARM64.inc"
/*******************************************/
/* Initialized data                        */
/*******************************************/
.data
szMessLenArea:     .asciz "The length of area is :  @ \n"
szCarriageReturn:  .asciz "\n"

/* areas strings  */
szString1:  .asciz "Apples"
szString2:  .asciz "Oranges"
/* pointer items area */
tablesPoi:
ptApples:    .quad szString1
ptOranges:   .quad szString2
ptVoid:      .quad 0
/*******************************************/
/* UnInitialized data                      */
/*******************************************/
.bss
sZoneConv:   .skip 30
/*******************************************/
/*  code section                           */
/*******************************************/
.text
.global main
main:                        // entry of program

    ldr x1,qAdrtablesPoi     // begin pointer table
    mov x0,0                 // counter
1:                           // begin loop
    ldr x2,[x1,x0,lsl 3]     // read string pointer address item x0 (8 bytes by pointer)
    cmp x2,0                 // is null ?
    cinc x0,x0,ne            // no increment counter
    bne 1b                   // and loop

    ldr x1,qAdrsZoneConv     // conversion decimal
    bl conversion10S
    ldr x0,qAdrszMessLenArea
    ldr x1,qAdrsZoneConv
    bl strInsertAtCharInc    // insert result at @ character
    bl affichageMess

100:                         // standard end of the program
    mov x0,0                 // return code
    mov x8,EXIT              // request to exit program
    svc 0                    // perform the system call
qAdrtablesPoi:         .quad tablesPoi
qAdrszMessLenArea:     .quad szMessLenArea
qAdrsZoneConv:         .quad sZoneConv
qAdrszCarriageReturn:  .quad szCarriageReturn
/********************************************************/
/*        File Include fonctions                        */
/********************************************************/
/* for this file see task include a file in language AArch64 assembly */
.include "../includeARM64.inc"


report z_array_length.

data(internal_table) = value stringtab( ( `apple` ) ( `orange` ) ).

write: internal_table[ 1 ] , internal_table[ 2 ] , lines( internal_table ).


import Foundation

func isBal(str: String) -> Bool {

  var count = 0

  return !str.characters.contains { ($0 == "["  ? ++count : --count) < 0 } && count == 0

}


proc generate {n} {
    if {!$n} return
    set l [lrepeat $n "\[" "\]"]
    set len [llength $l]
    while {$len} {
	set tmp [lindex $l [set i [expr {int($len * rand())}]]]
	lset l $i [lindex $l [incr len -1]]
	lset l $len $tmp
    }
    return [join $l ""]
}

proc balanced s {
    set n 0
    foreach c [split $s ""] {
	# Everything unmatched is ignored, which is what we want
	switch -exact -- $c {
	    "\[" {incr n}
	    "\]" {if {[incr n -1] < 0} {return false}}
	}
    }
    expr {!$n}
}

for {set i 0} {$i < 15} {incr i} {
    set s [generate $i]
    puts "\"$s\"\t-> [expr {[balanced $s] ? {OK} : {NOT OK}}]"
}


with Ada.Text_IO;  use Ada.Text_IO;

procedure Array_Length is
   Fruits : constant array (Positive range <>) of access constant String
      := (new String'("orange"),
          new String'("apple"));

begin
   for Fruit of Fruits loop
      Ada.Text_IO.Put (Integer'Image (Fruit'Length));
   end loop;

   Ada.Text_IO.Put_Line ("  Array Size : " & Integer'Image (Fruits'Length));
end Array_Length;


# UPB returns the upper bound of an array, LWB the lower bound #
[]STRING fruits = ( "apple", "orange" );
print( ( ( UPB fruits - LWB fruits ) + 1, newline ) ) # prints 2 #


program:  readint(n) [n>0] readint(seed)
loop:     parse(render) [--n>0?]/done loop;
render:   random(i, 15) [i = (i+1)*2] loop2 = { 1 * };
loop2:    random(b, 2) ( [b&1?] ={<[>} | ={<]>} ) [--i>0?]/done loop2 = { 2 1 };
done:     ;

/* Reads decimal integer */
readint:  proc(n;i) string(spaces) [n=0] inta
int1:     [n = n*12+i] inta\int1;
inta:     char(i) [i<72?] [(i =- 60)>=0?];

/* LCG params: a = 29989, c = 28411, m = 35521 */
random:   proc(r,mod) [seed = (seed*72445 + 67373) % 105301]
          [r = seed % mod] [r = r<0 ? -r : r];

spaces:   <<
>>;

n: 0; i: 0; b: 0; seed: 0;


$$ MODE TUSCRIPT

SECTION gen_brackets
values="[']",brackets=""
LOOP n=1,12
 brackets=APPEND (brackets,"","~")
 LOOP m=1,n
 a=RANDOM_NUMBERS (1,2,1),br=SELECT(values,#a)
 brackets=APPEND(brackets,"",br)
 b=RANDOM_NUMBERS (1,2,1),br=SELECT(values,#b)
 brackets=APPEND(brackets,"",br)
 ENDLOOP
ENDLOOP
brackets=SPLIT (brackets,":~:")
ENDSECTION

MODE DATA
$$ BUILD X_TABLE brackets=*
 [[[[ (4 ]]]] )4
 [[[ (3 ]]] )3
 [[ (2 ]] )2
 [ (1 ] )1

$$ MODE TUSCRIPT
DO gen_brackets
LOOP b=brackets
status=CHECK_BRACKETS (b,brackets,a1,e1,a2,e2)
PRINT b," ",status
ENDLOOP


array: seq["apple"; "orange"]
length[array]
/Works as a one liner: length[seq["apple"; "orange"]]


System.debug(new String[] { 'apple', 'banana' }.size()); // Prints 2


@(define paren)@(maybe)[@(coll)@(paren)@(until)]@(end)]@(end)@(end)
@(do (defvar r (make-random-state nil))

     (defun generate-1 (count)
       (let ((bkt (repeat "[]" count)))
         (cat-str (shuffle bkt))))

     (defun generate-list (num count)
       [[generate tf (op generate-1 count)] 0..num]))
@(next :list @(generate-list 22 6))
@(output)
INPUT           MATCHED         REST
@(end)
@  (collect)
@    (all)
@parens
@    (and)
@{matched (paren)}@mismatched
@    (end)
@  (output)
@{parens 15} @{matched 15} @{mismatched 15}
@  (end)
@(end)


// Balanced brackets

function isStringBalanced(str: string): bool {
  var paired = 0;
  for (var i = 0; i < str.length && paired >= 0; i++) {
    var c = str.charAt(i);
    if (c == '[')
      paired++;
    else if (c == ']')
      paired--;
  }
  return (paired == 0);
}

function generate(n: number): string {
  var opensCount = 0, closesCount = 0;
  // Choose at random until n of one type generated
  var generated: string[] = new Array(); // Works like StringBuilder
  while (opensCount < n && closesCount < n) {
    if (Math.floor(Math.random() * 2) == 0) {
      ++opensCount;
      generated.push("[");
    } else {
      ++closesCount;
      generated.push("]");
    }
  }
  // Now pad with the remaining other brackets
  generated.push(opensCount == n ?
    "]".repeat(n - closesCount) :
    "[".repeat(n - opensCount));
  return generated.join("");
}

console.log("Supplied examples");
var tests: string[] = ["", "[]", "][", "[][]", "][][", "[[][]]", "[]][[]"];
for (var test of tests)
  console.log(`The string '${test}' is ${(isStringBalanced(test) ? "OK." : "not OK."));
console.log();
console.log("Random generated examples");
for (var example = 0; example < 10; example++) {
  var test = generate(Math.floor(Math.random() * 10) + 1);
  console.log(`The string '${test}' is ${(isStringBalanced(test) ? "OK." : "not OK.")}`);
}


set theList to {"apple", "orange"}
count theList
-- or
length of theList
-- or
number of items in theList


/* ARM assembly Raspberry PI  */
/*  program lenAreaString.s   */

/* Constantes    */
.equ STDOUT, 1     @ Linux output console
.equ EXIT,   1     @ Linux syscall
.equ WRITE,  4     @ Linux syscall
/* Initialized data */
.data
szMessLenArea: .ascii "The length of area is : "
sZoneconv:		 .fill 12,1,' '
szCarriageReturn:  .asciz "\n"

/* areas strings  */
szString1:  .asciz "Apples"
szString2:  .asciz "Oranges"
/* pointer items area */
tablesPoi:
ptApples:		.int szString1
ptOranges:   .int szString2
ptVoid:		.int 0

/* UnInitialized data */
.bss

/*  code section */
.text
.global main
main:                /* entry of program  */
    push {fp,lr}    /* saves 2 registers */

    ldr r1,iAdrtablesPoi  @ begin pointer table
    mov r0,#0    @ counter
1:              @ begin loop
    ldr r2,[r1,r0,lsl #2]    @ read string pointer address item r0 (4 bytes by pointer)
    cmp r2,#0                @ is null ?
    addne r0,#1             @ no increment counter
    bne 1b                  @ and loop

    ldr r1,iAdrsZoneconv   @ conversion decimal
    bl conversion10S
    ldr r0,iAdrszMessLenArea
    bl affichageMess

2:

100:   /* standard end of the program */
    mov r0, #0                  @ return code
    pop {fp,lr}                 @restaur 2 registers
    mov r7, #EXIT              @ request to exit program
    swi 0                       @ perform the system call
iAdrtablesPoi:		.int tablesPoi
iAdrszMessLenArea:  .int szMessLenArea
iAdrsZoneconv:		.int  sZoneconv
iAdrszCarriageReturn:  .int  szCarriageReturn
/******************************************************************/
/*     display text with size calculation                         */
/******************************************************************/
/* r0 contains the address of the message */
affichageMess:
    push {fp,lr}    			/* save  registres */
    push {r0,r1,r2,r7}    		/* save others registers */
    mov r2,#0   				/* counter length */
1:      	/* loop length calculation */
    ldrb r1,[r0,r2]  			/* read octet start position + index */
    cmp r1,#0       			/* if 0 its over */
    addne r2,r2,#1   			/* else add 1 in the length */
    bne 1b          			/* and loop */
                                /* so here r2 contains the length of the message */
    mov r1,r0        			/* address message in r1 */
    mov r0,#STDOUT      		/* code to write to the standard output Linux */
    mov r7, #WRITE             /* code call system "write" */
    swi #0                      /* call systeme */
    pop {r0,r1,r2,r7}     		/* restaur others registers */
    pop {fp,lr}    				/* restaur des  2 registres */
    bx lr	        			/* return  */

/***************************************************/
/*   conversion register signed décimal     */
/***************************************************/
/* r0 contient le registre   */
/* r1 contient l adresse de la zone de conversion */
conversion10S:
    push {r0-r5,lr}    /* save des registres */
    mov r2,r1       /* debut zone stockage */
    mov r5,#'+'     /* par defaut le signe est + */
    cmp r0,#0       /* nombre négatif ? */
    movlt r5,#'-'     /* oui le signe est - */
    mvnlt r0,r0       /* et inversion en valeur positive */
    addlt r0,#1
    mov r4,#10   /* longueur de la zone */
1: /* debut de boucle de conversion */
    bl divisionpar10 /* division  */
    add r1,#48        /* ajout de 48 au reste pour conversion ascii */
    strb r1,[r2,r4]  /* stockage du byte en début de zone r5 + la position r4 */
    sub r4,r4,#1      /* position précedente */
    cmp r0,#0
    bne 1b	       /* boucle si quotient different de zéro */
    strb r5,[r2,r4]  /* stockage du signe à la position courante */
    subs r4,r4,#1   /* position précedente */
    blt  100f         /* si r4 < 0  fin  */
    /* sinon il faut completer le debut de la zone avec des blancs */
    mov r3,#' '   /* caractere espace */
2:
    strb r3,[r2,r4]  /* stockage du byte  */
    subs r4,r4,#1   /* position précedente */
    bge 2b        /* boucle si r4 plus grand ou egal a zero */
100:  /* fin standard de la fonction  */
    pop {r0-r5,lr}   /*restaur desregistres */
    bx lr

/***************************************************/
/*   division par 10   signé                       */
/* Thanks to http://thinkingeek.com/arm-assembler-raspberry-pi/*
/* and   http://www.hackersdelight.org/            */
/***************************************************/
/* r0 contient le dividende   */
/* r0 retourne le quotient */
/* r1 retourne le reste  */
divisionpar10:
  /* r0 contains the argument to be divided by 10 */
   push {r2-r4}   /* save registers  */
   mov r4,r0
   ldr r3, .Ls_magic_number_10 /* r1 <- magic_number */
   smull r1, r2, r3, r0   /* r1 <- Lower32Bits(r1*r0). r2 <- Upper32Bits(r1*r0) */
   mov r2, r2, ASR #2     /* r2 <- r2 >> 2 */
   mov r1, r0, LSR #31    /* r1 <- r0 >> 31 */
   add r0, r2, r1         /* r0 <- r2 + r1 */
   add r2,r0,r0, lsl #2   /* r2 <- r0 * 5 */
   sub r1,r4,r2, lsl #1   /* r1 <- r4 - (r2 * 2)  = r4 - (r0 * 10) */
   pop {r2-r4}
   bx lr                  /* leave function */
   bx lr                  /* leave function */
.Ls_magic_number_10: .word 0x66666667


generate() {
    local b=()
    local i j tmp
    for ((i=1; i<=$1; i++)); do
        b+=( '[' ']')
    done
    for ((i=${#b[@]}-1; i>0; i--)); do
        j=$(rand $i)
        tmp=${b[j]}
        b[j]=${b[i]}
        b[i]=$tmp
    done
    local IFS=
    echo "${b[*]}"
}

# a random number in the range [0,n)
rand() {
    echo $(( $RANDOM % $1 ))
}

balanced() {
    local -i lvl=0
    local i
    for ((i=0; i<${#1}; i++)); do
        case ${1:i:1} in
            '[') ((lvl++));;
            ']') (( --lvl < 0 )) && return 1;;
        esac
    done
    (( lvl == 0 )); return $?
}

for ((i=0; i<=10; i++)); do
    test=$(generate $i)
    balanced "$test" && result=OK || result="NOT OK"
    printf "%s\t%s\n" "$test" "$result"
done


fruit: ["apple" "orange"]

print ["array length =" size fruit]


#include
"share/atspre_staload.hats"
#include
"share/atspre_staload_libats_ML.hats"

val A0 =
array0_tuple<string>
( "apple", "orange" )
val () =
println!("length(A0) = ", length(A0))

implement main0((*void*)) = ((*void*))


#import std
#import nat

balanced = @NiX ~&irB->ilZB ~&rh?/~&lbtPB ~&NlCrtPX

#cast %bm

main = ^(2-$'[]'*,balanced)* [email protected]*~ iota64


Public Function checkBrackets(s As String) As Boolean
'function checks strings for balanced brackets
Dim Depth As Integer
Dim ch As String * 1

Depth = 0
For i = 1 To Len(s)
  ch = Mid$(s, i, 1)
  If ch = "[" Then Depth = Depth + 1
  If ch = "]" Then
    If Depth = 0 Then 'not balanced
      checkBrackets = False
      Exit Function
    Else
      Depth = Depth - 1
    End If
  End If
Next
checkBrackets = (Depth = 0)
End Function

Public Function GenerateBrackets(N As Integer) As String
'generate a string with N opening and N closing brackets in random order
Dim s As String
Dim N2 As Integer, j As Integer
Dim Brackets() As String * 1
Dim temp As String * 1

'catch trivial value
If N <= 0 Then
  GenerateBrackets = ""
  Exit Function
End If

N2 = N + N
ReDim Brackets(1 To N2)
For i = 1 To N2 Step 2
 Brackets(i) = "["
 Brackets(i + 1) = "]"
Next i
'shuffle.
For i = 1 To N2
  j = 1 + Int(Rnd() * N2)
  'swap brackets i and j
  temp = Brackets(i)
  Brackets(i) = Brackets(j)
  Brackets(j) = temp
Next i
'generate string
s = ""
For i = 1 To N2
  s = s & Brackets(i)
Next i
GenerateBrackets = s
End Function

Public Sub BracketsTest()
Dim s As String
Dim i As Integer

For i = 0 To 10
 s = GenerateBrackets(i)
 Debug.Print """" & s & """: ";
 If checkBrackets(s) Then Debug.Print " OK" Else Debug.Print " Not OK"
Next
End Sub


Opt('MustDeclareVars',1)	 	; 1 = Variables must be pre-declared.

Local $aArray[2] = ["Apple", "Orange"]
Local $Max = UBound($aArray)
ConsoleWrite("Elements in array: " & $Max & @CRLF)

For $i = 0 To $Max - 1
	ConsoleWrite("aArray[" & $i & "] = '" & $aArray[$i] & "'" & @CRLF)
Next


For n = 1 To 10
	sequence = Generate_Sequence(n)
	WScript.Echo sequence & " is " & Check_Balance(sequence) & "."
Next

Function Generate_Sequence(n)
	For i = 1 To n
		j = Round(Rnd())
		If j = 0 Then
			Generate_Sequence = Generate_Sequence & "["
		Else
			Generate_Sequence = Generate_Sequence & "]"
		End If
	Next
End Function

Function Check_Balance(s)
	Set Stack = CreateObject("System.Collections.Stack")
	For i = 1 To Len(s)
		char = Mid(s,i,1)
		If i = 1 Or char = "[" Then
			Stack.Push(char)
		ElseIf Stack.Count <> 0 Then
			If char = "]" And Stack.Peek = "[" Then
				Stack.Pop
			End If
		Else
			Stack.Push(char)
		End If
	Next
	If Stack.Count > 0 Then
		Check_Balance = "Not Balanced"
	Else
		Check_Balance = "Balanced"
	End If
End Function


Module Module1

    Private rand As New Random

    Sub Main()
        For numInputs As Integer = 1 To 10 '10 is the number of bracket sequences to test.
            Dim input As String = GenerateBrackets(rand.Next(0, 5)) '5 represents the number of pairs of brackets (n)
            Console.WriteLine(String.Format("{0} : {1}", input.PadLeft(10, CChar(" ")), If(IsBalanced(input) = True, "OK", "NOT OK")))
        Next
        Console.ReadLine()
    End Sub

    Private Function GenerateBrackets(n As Integer) As String

        Dim randomString As String = ""
        Dim numOpen, numClosed As Integer

        Do Until numOpen = n And numClosed = n
            If rand.Next(0, 501) Mod 2 = 0 AndAlso numOpen < n Then
                randomString = String.Format("{0}{1}", randomString, "[")
                numOpen += 1
            ElseIf rand.Next(0, 501) Mod 2 <> 0 AndAlso numClosed < n Then
                randomString = String.Format("{0}{1}", randomString, "]")
                numClosed += 1
            End If
        Loop
        Return randomString
    End Function

    Private Function IsBalanced(brackets As String) As Boolean

        Dim numOpen As Integer = 0
        Dim numClosed As Integer = 0

        For Each character As Char In brackets
            If character = "["c Then numOpen += 1
            If character = "]"c Then
                numClosed += 1
                If numClosed > numOpen Then Return False
            End If
        Next
        Return numOpen = numClosed
    End Function
End Module


# usage:  awk -f arraylen.awk
#
function countElements(array) {
  for( e in array ) {c++}
  return c
}

BEGIN {
  array[1] = "apple"
  array[2] = "orange"

  print "Array length :", length(array), countElements(array)

  print "String length:", array[1], length(array[1])
}


' Static arrays

DECLARE fruit$[] = { "apple", "orange" }
PRINT UBOUND(fruit$)

' Dynamic arrays

DECLARE vegetable$ ARRAY 2
vegetable$[0] = "cabbage"
vegetable$[1] = "spinach"
PRINT UBOUND(vegetable$)

' Associative arrays

DECLARE meat$ ASSOC STRING
meat$("first") = "chicken"
meat$("second") = "pork"
PRINT UBOUND(meat$)


import datatypes as dt

fn is_valid(bracket string) bool {
    mut s := dt.Stack<string>{}
    for b in bracket.split('') {
        if b == '[' {
            s.push(b)
        } else {
            if s.peek() or {''} == '[' {
                s.pop() or {panic("WON'T GET HERE EVER")}
            } else {
                return false
            }
        }
    }
    return true
}

fn main() {
    brackets := ['','[]','[][]','[[][]]','][','][][','[]][[]','[][[][[]][][[][]]]']
    for b in brackets {
        println('$b ${is_valid(b)}')
    }
}


import "random" for Random

var isBalanced = Fn.new { |s|
    if (s.isEmpty) return true
    var countLeft = 0 // number of left brackets so far unmatched
    for (c in s) {
        if (c == "[") {
            countLeft = countLeft + 1
        } else if (countLeft > 0) {
            countLeft = countLeft - 1
        } else {
            return false
        }
    }
    return countLeft == 0
}

System.print("Checking examples in task description:")
var brackets = ["", "[]", "][", "[][]", "][][", "[[][]]", "[]][[]"]
for (b in brackets) {
    System.write((b != "") ? b : "(empty)")
    System.print("\t  %(isBalanced.call(b) ? "OK" : "NOT OK")")
}
System.print("\nChecking 7 random strings of brackets of length 8:")
var rand = Random.new()
for (i in 1..7) {
    var s = ""
    for (j in 1..8) s = s + ((rand.int(2) == 0) ? "[" : "]")
    System.print("%(s)  %(isBalanced.call(s) ? "OK" : "NOT OK")")
}


fruit=("apple" "orange" "lemon")
echo "${#fruit[@]}"


DIM X$(1 TO 2)
X$(1) = "apple"
X$(2) = "orange"
PRINT UBOUND(X$) - LBOUND(X$) + 1


@echo off

:_main
setlocal enabledelayedexpansion

:: This block of code is putting a list delimitered by spaces into an pseudo-array
:: In practice, this could be its own function _createArray however for the demonstration, it is built in
set colour_list=red yellow blue orange green
set array_entry=0
for %%i in (%colour_list%) do (
  set /a array_entry+=1
  set colours[!array_entry!]=%%i
)

call:_arrayLength colours
echo _arrayLength returned %errorlevel%
pause>nul
exit /b

:: _arrayLength returns the length of the array parsed to it in the errorcode
:_arrayLength
setlocal enabledelayedexpansion

:loop
set /a arrayentry=%arraylength%+1
if "!%1[%arrayentry%]!"=="" exit /b %arraylength%
set /a arraylength+=1
goto loop


section .data

MsgBalanced: db "OK", 10
MsgBalancedLen: equ 3

MsgUnbalanced: db "NOT OK", 10
MsgUnbalancedLen: equ 7

MsgBadInput: db "BAD INPUT", 10
MsgBadInputLen: equ 10

Open: equ '['
Closed: equ ']'

section .text

BalancedBrackets:

  xor rcx, rcx
  mov rsi, rdi
  cld

  processBracket:
    lodsb
    cmp al, 0
    je determineBalance

    cmp al, Open
    je processOpenBracket

    cmp al, Closed
    je processClosedBracket

    mov rsi, MsgBadInput
    mov rdx, MsgBadInputLen
    jmp displayResult

    processOpenBracket:
      add rcx, 1
      jmp processBracket

    processClosedBracket:
      cmp rcx, 0
      je unbalanced

      sub rcx, 1
      jmp processBracket

  determineBalance:
    cmp rcx, 0
    jne unbalanced

    mov rsi, MsgBalanced
    mov rdx, MsgBalancedLen
    jmp displayResult

  unbalanced:
    mov rsi, MsgUnbalanced
    mov rdx, MsgUnbalancedLen

  displayResult:
    mov rax, 1
    mov rdi, 1
    syscall
    ret


' Balanced brackets
PROGRAM "balancedbrackets"
VERSION "0.001"

IMPORT "xst"

DECLARE FUNCTION Entry()
INTERNAL FUNCTION IsStringBalanced(str$)
INTERNAL FUNCTION Generate$(n%%)

' Pseudo-random number generator
' Based on the rand, srand functions from Kernighan & Ritchie's book
' 'The C Programming Language'
DECLARE FUNCTION Rand()
DECLARE FUNCTION SRand(seed%%)

FUNCTION Entry()
  PRINT "Supplied examples"
  DIM tests$[6]
  tests$[0] = ""
  tests$[1] = "[]"
  tests$[2] = "]["
  tests$[3] = "[][]"
  tests$[4] = "][]["
  tests$[5] = "[[][]]"
  tests$[6] = "[]][[]"
  FOR example@@ = 0 TO UBOUND(tests$[])
    test$ = tests$[example@@]
    PRINT "The string '"; test$; "' is ";
    IFT IsStringBalanced(test$) THEN
      PRINT "OK."
    ELSE
      PRINT "not OK."
    END IF
  NEXT example@@
  PRINT
  PRINT "Random generated examples"
  XstGetSystemTime (@msec)
  SRand(INT(msec) MOD 32768)
  FOR example@@ = 1 TO 10
    test$ = Generate$(INT(Rand() / 32768.0 * 10.0) + 1)
    PRINT "The string '"; test$; "' is ";
    IFT IsStringBalanced(test$) THEN
      PRINT "OK."
    ELSE
      PRINT "not OK."
    END IF
  NEXT example@@
END FUNCTION

FUNCTION IsStringBalanced(s$)
  paired& = 0
  i%% = 1
  DO WHILE i%% <= LEN(s$) && paired& >= 0
    c$ = MID$(s$, i%%, 1)
    SELECT CASE c$
      CASE "[":
        INC paired&
      CASE "]":
        DEC paired&
    END SELECT
    INC i%%
  LOOP
END FUNCTION (paired& = 0)

FUNCTION Generate$(n%%)
  opensCount%% = 0
  closesCount%% = 0
  ' Choose at random until n%% of one type generated
  generated$ = ""
  DO WHILE opensCount%% < n%% && closesCount%% < n%%
    SELECT CASE (INT(Rand() / 32768.0 * 2.0) + 1)
      CASE 1:
        INC opensCount%%
        generated$ = generated$ + "["
      CASE 2:
        INC closesCount%%
        generated$ = generated$ + "]"
    END SELECT
  LOOP
  ' Now pad with the remaining other brackets
  IF opensCount%% = n%% THEN
    generated$ = generated$ + CHR$(']', n%% - closesCount%%)
  ELSE
    generated$ = generated$ + CHR$('[', n%% - opensCount%%)
  END IF
END FUNCTION generated$

' Return pseudo-random integer on 0..32767
FUNCTION Rand()
  #next&& = #next&& * 1103515245 + 12345
END FUNCTION USHORT(#next&& / 65536) MOD 32768

' Set seed for Rand()
FUNCTION SRand(seed%%)
  #next&& = seed%%
END FUNCTION

END PROGRAM


      DIM array$(1)
      array$() = "apple", "orange"
      PRINT "Number of elements in array = "; DIM(array$(), 1) + 1
      PRINT "Number of bytes in all elements combined = "; SUMLEN(array$())
      END


const Chars:[string] = ["[","]"];
func GenerateString(Amount:number=4):string{
	set Result:string = "";
	<|(*1..Amount)=>Result+=Chars[math.random(0,?Chars-1)];
	send Result;
}

func IsBalanced(String:string):boolean{
	set Pairs:number = 0;
	<|(*(0..(?String-1)))=>(String::at(_)=="[")?(Pairs<0)?=>send false,Pairs++,=>Pairs--;
	send (Opens==Closes)&(Pairs==0);
}

repeat 10 {
	set s = GenerateString(math.random(2,4)*2);
	log(`{s}: {IsBalanced(s)}`);
}


include c:\cxpl\codes;       \intrinsic code declarations

int     N, I, C, Nest;
char    Str;
[\Generate a string with N open brackets and N close brackets in arbitrary order
N:= IntIn(0);                           \get number of brackets/2 from keyboard
Str:= Reserve(2*N);
for I:= 0 to 2*N-1 do Str(I):= ^[;
C:= 0;                                  \initialize count of "]"
repeat  I:= Ran(2*N);                   \change N random locations to "]"
        if Str(I) # ^] then [Str(I):= ^]; C:= C+1];
until   C>=N;

\Determine whether string consists of nested pairs of open/close brackets
I:= 0;  C:= 0;  Nest:= false;
while I<2*N do
        [if Str(I) = ^[ then C:= C+1 else C:= C-1;
        if C<0 then Nest:= true;
        ChOut(0,Str(I));
        I:= I+1;
        ];
ChOut(0,9\tab\);
if Nest then Text(0,"NOT ");
Text(0,"OK
");
]


#include <stdio.h>

int main()
{
    const char *fruit[2] = { "apples", "oranges" };

    // Acquire the length of the array by dividing the size of all elements (found
    // with sizeof(fruit)) by the size of the first element.

    // Note that since the array elements are pointers to null-terminated character
    // arrays, the size of the first element is actually the size of the pointer
    // type - not the length of the string.

    // This size, regardless of the type being pointed to, is 8 bytes, 4 bytes, or
    // 2 bytes on 64-bit, 32-bit, or 16-bit platforms respectively.
    int length = sizeof(fruit) / sizeof(fruit[0]);

    printf("%d\n", length);

    return 0;
}


using System;

class Program
{
    public static void Main()
    {
        var fruit = new[] { "apple", "orange" };
        Console.WriteLine(fruit.Length);
    }
}


@Balanced[]s // each source must be started by specifying its file name; std extension .Ya could be ommitted and auto added by compiler

// all types are prefixed by `
// definition of anything new is prefixed by \, like \MakeNew_[]s and \len
// MakeNew_[]s is Ok ident in Ya: _ starts sign part of ident, which must be ended by _ or alphanum
`Char[^] \MakeNew_[]s(`Int+ \len) // `Char[^] and `Char[=] are arrays that owns their items, like it's usally in other langs;
	// yet in assignment of `Char[^] to `Char[=] the allocated memory is moved from old to new owner, and old string becomes empty
	// there are tabs at starts of many lines; these tabs specify what in C++ is {} blocks, just like in Python
	len & 1 ==0 ! // it's a call to postfix function '!' which is an assert: len must be even
	`Char[=] \r(len) // allocate new string of length len
	// most statements are analogous to C++ but written starting by capital letter: For If Switch Ret
	For `Char[] \eye = r; eye // // `Char[] is a simplest array of chars, which does not hold a memory used by array items; inc part of For loop is missed: it's Ok, and condition and init could also be missed
		*eye++ = '['; *eye++ = '[' // fill r by "[][][]...". The only place with ; as statement delemiter: required because the statement is not started at new line.
	// below is a shuffle of "[][][]..." array
	For `Char[] \eye = r; ++eye // var eye is already defined, but being the same `Char[] it's Ok by using already exisiting var. ++eye is used: it allows use of eye[-1] inside
		`Int+ \at = Random(eye/Length) // `Int+ is C++'s unsigned int. eye/Length: / is used for access to field, like in file path
		eye[-1],eye[at] = eye[at],eye[-1] // swap using tuples; eye[-1] accesses char that is out of current array, yet it's allowed
	Ret r // Ret is C's return
`Bool \AreBalanced(`Char[] \brackets)
	`Int+ \extra = 0
	For ;brackets ;++brackets
		Switch *brackets
			'[' // it's a C++'s 'case': both 'case' and ':' are skipped being of no value; but the code for a case should be in block, which is here specifyed by tabs at next line start
				++extra
			']'
				If !!extra // '!!' is `Bool not, like all other `Bool ops: && || ^^
					Ret No // No and False are C's false; Yes and True are C's true
				--extra
		// There is no default case, which is written as ':' - so if no case is Ok then it will fail just like if being written as on the next line
		//	: { 0! } // C's default: assert(0);
	Ret extra == 0
// function ala 'main' is not used: all global code from all modules are executed; so below is what typically is in ala 'main'
For `Int \n=10; n; --n
	// below note that new var 'brackets' is created inside args of func call
	//@Std/StdIO/ is used here to use Print function; else it maybe changed to Use @Std/StdIO at global level before this For loop
	@Std/StdIO/Print(; "%s : %s\n" ;`Char[=] \brackets = MakeNew_[]s(10) /* all bracket strings are of length 10 */; AreBalanced(brackets) ? "Ok" : "bad")
	// note that starting arg of Print is missed by using ';' - default arg value is allowed to use for any arg, even if next args are written


sub check_brackets(s$)
    local level, i

    for i = 1 to len(s$)
        switch mid$(s$, i, 1)
            case "[": level = level + 1 : break
            case "]": level = level - 1 : if level < 0 break 2
        end switch
    next i
    return level = 0
end sub

s$ = "[[]][]"

print s$, " = ";

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


#include <array>
#include <iostream>
#include <string>

int main()
{
    std::array<std::string, 2> fruit { "apples", "oranges" };
    std::cout << fruit.size();
    return 0;
}


shared void run() {
	value array = ["apple", "orange"];
	print(array.size);
}


/*
 * nizchka: March - 2016
 * This is a Clipper/XBase++ of RosettaCode Array_Length
 */

PROCEDURE MAIN()
        LOCAL FRUIT := { "apples","oranges" }

        ? LEN(FRUIT)
RETURN


; using count:
(count ["apple" "orange"])

; OR alength if using Java arrays:
(alength (into-array ["apple" "orange"]))


       identification division.
       program-id. array-length.

       environment division.
       configuration section.
       repository.
           function all intrinsic.

       data division.
       working-storage section.
       01 table-one.
          05 str-field pic x(7) occurs 0 to 5 depending on t1.

       77 t1           pic 99.

       procedure division.
       array-length-main.
       perform initialize-table
       perform display-table-info
       goback.

       initialize-table.
           move 1 to t1
           move "apples" to str-field(t1)

           add 1 to t1
           move "oranges" to str-field(t1).

      *> add an extra element and then retract table size
           add 1 to t1
           move "bananas" to str-field(t1).
           subtract 1 from t1
       .

       display-table-info.
           display "Elements: " t1 ", using " length(table-one) " bytes"
           display table-one
       .

       end program array-length.


<cfset testArray = ["apple","orange"]>
<cfoutput>Array Length = #ArrayLen(testArray)#</cfoutput>


MODULE AryLen;
IMPORT StdLog;

TYPE
	String = POINTER TO ARRAY OF CHAR;
VAR
	a: ARRAY 16 OF String;

PROCEDURE NewString(s: ARRAY OF CHAR): String;
VAR
	str: String;
BEGIN
	NEW(str,LEN(s$) + 1);str^ := s$; RETURN str
END NewString;

PROCEDURE Length(a: ARRAY OF String): INTEGER;
VAR
	i: INTEGER;
BEGIN
	i := 0;
	WHILE a[i] # NIL DO INC(i) END;
	RETURN i
END Length;

PROCEDURE Do*;
BEGIN
	a[0] := NewString("Apple");
	a[1] := NewString("Orange");
	StdLog.String("Length:> ");StdLog.Int(Length(a));StdLog.Ln
END Do;

END AryLen.


import std.stdio;

int main()
{
    auto fruit = ["apple", "orange"];
    fruit.length.writeln;
    return 0;
}


arrLength(arr) {
  return arr.length;
}

main() {
  var fruits = ['apple', 'orange'];
  print(arrLength(fruits));
}


var arr = ["apple", "orange"]
sizeOf(arr)


showmessage(  length(['a','b','c']).ToString );


select "std"

a = ["apple","orange"]
b = length(a)

show b


var xs = ["apple", "orange"]
print(xs.Length())


fruit$[] = [ "apples" "oranges" ]
print len fruit$[]


(length '("apple" "orange")) ;; list
   → 2
(vector-length #("apple" "orange")) ;; vector
   → 2


    var array := new string[]{"apple", "orange"};
    var length := array.Length;


iex(1)> length( ["apple", "orange"] )          # List
2
iex(2)> tuple_size( {"apple", "orange"} )      # Tuple
2


import Array
import Html

main : Html.Html
main =
    ["apple", "orange"]
      |> Array.fromList
      |> Array.length
      |> Basics.toString
      |> Html.text


1> length(["apple", "orange"]).     %using a list
2
1> tuple_size({"apple", "orange"}). %using a tuple
2


sequence s = {"apple","orange",2.95} -- Euphoria doesn't care what you put in a sequence

? length(s)

3 -- three objects

? length(s[1])

5 -- apple has 5 characters

? length(s[1][$])

1 -- 'e' is an atomic value

? length(s[$])

1 -- 2.95 is an atomic value


: STRING,  ( caddr len -- ) \ Allocate space & compile string into memory
             HERE  OVER CHAR+  ALLOT  PLACE ;

: "     ( -- ) [CHAR] " PARSE  STRING, ; \ Parse input to " and compile to memory

\ Array delimiter words
: {  ALIGN 0 C, ;               \ Compile 0 byte start/end of array
: }  ALIGN 0 C,  ;

\ String array words
: {NEXT}    ( str -- next_str)       \ Iterate to next string
           COUNT + ;

: {NTH}    ( n array_addr -- str)   \ Returns address of the Nth item in the array
           SWAP 0 DO {NEXT} LOOP ;

: {LEN} ( array_addr -- n)  \ count strings in the array
          0 >R                      \ Counter on Rstack
          {NEXT}
          BEGIN
             DUP [email protected]                 \ Fetch length byte
          WHILE                     \ While true
             R> 1+ >R               \ Inc. counter
             {NEXT}
          REPEAT
          DROP
          R> ;      \ return counter to data stack


      MODULE EXAMPLE
       CONTAINS
        SUBROUTINE ABOUND(A)
         CHARACTER*(*) A(:)	!One dimensional array, unspecified bounds.
          WRITE (6,*) "Lower bound",LBOUND(A),", Upper bound",UBOUND(A)
          WRITE (6,*) "Element size",LEN(A(LBOUND(A)))
          WRITE (6,*) A
        END SUBROUTINE ABOUND
      END MODULE EXAMPLE

      PROGRAM SHOWBOUNDS
       USE EXAMPLE
       CHARACTER*6 ARRAY(-1:1)
        ARRAY(-1) = "Apple"
        ARRAY(0) = "Orange"
        ARRAY(1) = ""
        CALL ABOUND(ARRAY)
        WRITE (6,*) "But, when it is at home..."
        WRITE (6,*) "L. bound",LBOUND(ARRAY),", U. bound",UBOUND(ARRAY)
      END


' FB 1.05.0 Win64

Dim fruit(1) As String = {"apple", "orange"}
Dim length As Integer = UBound(fruit) - LBound(fruit) + 1
Print "The length of the fruit array is"; length
Print
Print "Press any key to quit the program"
Sleep


a = ["apple", "orange"]
println[length[a]]


THE_LIST( <apple> <orange> )
COUNT[ 0 SW ~| COUNT_STEP# 0 SW SU ]
COUNT_STEP[ DR 1 SU ]

`THE_LIST COUNT# +<>


fun length(as: []int): int = (shape as)[0]


window 1
print fn ArrayCount( @[@"apple",@"orange",@"cherry",@"grape",@"lemon"] )
HandleEvents


Public Sub Main()
Dim siList As Short[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]

Print siList.Count

End


[indent=4]
/* Array length, in Genie */
init
    arr:array of string = {"apple", "orange"}
    stdout.printf("%d ", arr.length)
    print arr[1]


package main

import "fmt"

func main() {
	arr := [...]string{"apple", "orange", "pear"}

	fmt.Printf("Length of %v is %v.\n", arr, len(arr))
}


def fruits = ['apple','orange']
println fruits.size()


LOCAL aFruits := {"apple", "orange"}
Qout( Len( aFruits ) ) // --> 2


-- [[Char]] -> Int
length ["apple", "orange"]


let a arr 2
let a[0] "apple"
let a[1] "orange"
println len a


   # 'apple';'orange'
2
   $ 'apple';'orange'
2


(def our-array @["apple" "orange"])
(length our-array)


public class ArrayLength {
    public static void main(String[] args) {
        System.out.println(new String[]{"apple", "orange"}.length);
    }
}


/* Array length, in jsish */
var arr = new Array('apple', 'orange');
puts(arr.length);
puts(arr[1]);


include ..\Utilitys.tlhy

( "apple" "orange" ) len print

" " input


fun main(args: Array<String>) {
    println(arrayOf("apple", "orange").size)
}


FruitList$(0)="apple" 'assign 2 cells of a list array
FruitList$(1)="orange"
dimension=dimension(FruitList$()) 'first get the dimension of the array
if dimension>3 then
    print "Sorry, program only written for array dimensions of 3 or less."
    end
end if
call elements FruitList$(), dimension 'next get the size of each dimension
end

function dimension(array$())
    for dimension=1 to 4
        select case dimension
            case 1
                try: x$=array$(0)
                catch: goto [TryNext]
                end try
                exit for
            case 2
                try: x$=array$(0,0)
                catch: goto [TryNext]
                end try
                exit for
            case 3
                try: x$=array$(0,0,0)
                catch: goto [TryNext]
                end try
                exit for
            case 4
                exit for
        end select
    [TryNext]
    next dimension
    if dimension<4 then print "array dimension = "; dimension
    ArraySize(0)=dimension
end function

sub elements array$(), dimension
    select case dimension
        case 1
            try
                do
                    x$=array$(a)
                    a+=1
                loop
            catch: elements=a
            end try
            ArraySize(1)=elements-1
            print "dimension 1 has "; elements; " elements (cells), "_
                    "numbered 0 to "; ArraySize(1)
        case 2
            try
                do
                    x$=array$(a,0)
                    a+=1
                loop
            catch: elements=a
            end try
            ArraySize(1)=elements-1
            print "dimension 1 has "; elements; " elements (cells), "_
                    "numbered 0 to "; ArraySize(1)
            elements=0
            try
                do
                    x$=array$(0,b)
                    b+=1
                loop
            catch: elements=b
            end try            ArraySize(2)=elements-1
            print "dimension 2 has "; elements; " elements (cells), "_
                    "numbered 0 to "; ArraySize(2)
        case 3
            try
                do
                    x$=array$(a,0,0)
                    a+=1
                loop
            catch: elements=a
            end try
            ArraySize(1)=elements-1
            print "dimension 1 has "; elements; " elements (cells), "_
                    "numbered 0 to "; ArraySize(1)
            elements=0
            try
                do
                    x$=array$(0,b,0)
                    b+=1
                loop
            catch: elements=b
            end try
            ArraySize(2)=elements-1
            print "dimension 2 has "; elements; " elements (cells), "_
                    "numbered 0 to "; ArraySize(2)
            elements=0
            try
                do
                    x$=array$(0,0,c)
                    c+=1
                loop
            catch: elements=c
            end try
            ArraySize(3)=elements-1
            print "dimension 3 has "; elements; " elements (cells), "_
                    "numbered 0 to "; ArraySize(3)
    end select
   'print the explicit or implied DIMension statement for this array
    print "DIM array$("; a-1;
    if b>0 then print ","; b-1;
    if c>0 then print ","; c-1;
    print ")"
end sub


# Array length, in LIL
set a [list "apple"]
append a "orange"
print [count $a]
print [index $a 1]


implement Command;

include "sys.m";
sys: Sys;

include "draw.m";

include "sh.m";

init(nil: ref Draw->Context, nil: list of string)
{
	sys = load Sys Sys->PATH;

	a := array[] of {"apple", "orange"};
	sys->print("length of a: %d\n", len a);
}


fruits = ["apple", "orange"]
put fruits.count
-- 2


string fruit[] = {"apples", "oranges"};
puts(length(fruit));


put "apple","orange" into fruit
split fruit using comma
answer the number of elements of fruit


-- For tables as simple arrays, use the # operator:
fruits = {"apple", "orange"}
print(#fruits)

-- Note the # symbol does not work for non-integer-indexed tables:
fruits = {fruit1 = "apple", fruit2 = "orange"}
print(#fruits)

-- For this you can use this short function:
function size (tab)
  local count = 0
  for k, v in pairs(tab) do
    count = count + 1
  end
  return count
end

print(size(fruits))


\\ A is a pointer to array
A=("Apple", "Orange")
Print  Len(A)=2  ' True
Print Dimension(A, 0)  ' LBound (0 or 1), here 0
Print Dimension(A)  ' No of Dimensions 1
Print Dimension(A, 1) ' for 1 dimension array this is also Length=2
\\ A$( ) is an Array (not a pointer to array)
Dim Base 1, A$(2)
A$(1)="Apple", "Orange"
Print Dimension(A$(), 0)  ' LBound (0 or 1), here 1
Print Dimension(A$())  ' No of Dimensions 1
Print Dimension(A$(), 1) ' for 1 dimension array this is also Length=2
Link A to B$()  ' B$() is a reference to A
Print B$(0)=A$(1)
Print B$(1)=A$(2)
Dim C$()
\\ C$() get a copy of B$()
C$()=B$()
Print C$()  ' prints Apple Orange
\\ An array can link to a new name as reference, and can change major type
\\ here A$() get A() so we can read/store numbers and read/store strings in same array
\\ using two names
Link A$() to A()
\\ An array pointer can point to another array
A=A()
Print Dimension(A, 0)  ' LBound (0 or 1), here 1 (was 0)
\\ Because B$() is reference of A:
Print Dimension(B$(), 0)  ' LBound (0 or 1), here 1 (was 0)
Print B$(1)=A$(1)
Print B$(2)=A$(2)
Print Dimension(C$(), 0)  ' LBound (0 or 1), here 0
\\ change base preserve items
Dim Base 1, C$(Dimension(C$(), 1))
Print Dimension(C$(), 0)  ' LBound (0 or 1), here 1 (was 0)
Print C$()  ' prints Apple Orange
Print Len(C$()) ' Len return all items of an array - can be 0
Dim K(1,1,1,1,1,1)  ' Maximum 10 dimensions
Print Len(K()=1 ' True


a := Array(["apple", "orange"]);
numelems(a);


:- module array_length.
:- interface.

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

:- implementation.

:- import_module array, list.

main(!IO) :-
    Array = array(["apples", "oranges"]),
    io.write_int(size(Array), !IO).


fruits = ["apple", "orange"]
print fruits.len


fruit = array(2)
fruit[0] = "apple"
fruit[1] = "orange"
println len(fruit)

// outputs 2


var fruit = $array("apple", "orange");

$print($asize(fruit));


(println (length '("apple" "orange")))

; Nehal-Singhal 2018-05-25
(length '(apple orange))


echo(len(['apple', 'orange']))
# same
echo(['apple', 'orange'].len())


let fruit = ["apple", "orange"]
echo "The length of the fruit array is ", len(fruit)


MODULE ArrayLength;
IMPORT
  Strings,
  Out;
TYPE
  String = POINTER TO ARRAY OF CHAR;
VAR
  a: ARRAY 16 OF String;

PROCEDURE NewString(s: ARRAY OF CHAR): String;
VAR
  str: String;
BEGIN
  NEW(str,Strings.Length(s) + 1);COPY(s,str^);
  RETURN str
END NewString;

PROCEDURE Length(a: ARRAY OF String): LONGINT;
VAR
  i: LONGINT;
BEGIN
  i := 0;
  WHILE (a[i] # NIL) DO INC(i) END;
  RETURN i;
END Length;

BEGIN
  a[0] := NewString("apple");
  a[1] := NewString("orange");
  Out.String("length: ");Out.Int(Length(a),0);Out.Ln
END ArrayLength.


class Test {
  function : Main(args : String[]) ~ Nil {
    fruit := ["apples", "oranges"];
    fruit->Size()->PrintLine();
  }
}


(print (vector-length (vector "apple" "orange")))
(print (vector-length #("apple" "orange")))
(print (vector-length ["apple" "orange"]))

(print (size #("apple" "orange")))


[`apple' `orange'] length # leaves 2 on top of the stack


/* REXX */
a = .array~of('apple','orange')
say a~size 'elements'
Do e over a
  say e
  End
Say "a[2]="a[2]


array = ["apple", "orange"]
length(array)       \\ == 2
#array              \\ == 2


#!/usr/bin/instantfpc
//program ArrayLength;

{$mode objfpc}{$H+}

uses SysUtils, Classes;

const
  Fruits : array[0..1] of String = ('apple', 'orange');

begin
   WriteLn('Length of Fruits by function : ', Length(Fruits));
   WriteLn('Length of Fruits by bounds : ', High(Fruits) - Low(Fruits) + 1);
END.


my @array = qw "apple orange banana", 4, 42;

scalar @array;      #  5
0 + @arrray;        #  5
'' . @array;        # "5"
my $elems = @array; # $elems = 5

scalar @{  [1,2,3]  }; # [1,2,3] is a reference which is already a scalar

my $array_ref = \@array; # a reference
scalar @$array_ref;

# using subroutine prototypes, not generally recommended
# and not usually what you think they are
sub takes_a_scalar ($) { my ($a) = @_; return $a }

takes_a_scalar @array;

# the built-ins can also act like they have prototypes


constant fruits = {"apple","orange"}
?length(fruits)


"apple" "orange" stklen tolist len print


print count(['apple', 'orange']); // Returns 2


main =>
   L = ["apple", "orange"],
   println(len(L))),
   println(length(L)),
   println(L.len),
   println(L.length).


void main()
{
    array fruit = ({ "apple", "orange" });
    write("%d\n", sizeof(fruit));
}


 p: Proc Options(main);
 Dcl a(2) Char(6) Varying Init('apple','orange');
 Put Edit('Array a has',(hbound(a)-lbound(a)+1),' elements.')
         (Skip,a,f(2),a);
 Put Skip Data(a);
 End;


actor Main
    new create(env:Env)=>
        var c=Array[String](2)
        c.push("apple")
        c.push("orange")
        env.out.print("Array c is " + c.size().string() + " elements long!")


$Array = @( "Apple", "Orange" )
$Array.Count
$Array.Length


String[] arr = {"apple", "orange"};
void setup(){
  println(arr.length);
}


| ?- length(["apple", "orange"], X).

X = 2

yes


EnableExplicit
Define Dim fruit$(1); defines array with 2 elements at indices 0 and 1
fruit$(0) = "apple"
fruit$(1) = "orange"
Define length = ArraySize(fruit$()) + 1; including the element at index 0
If OpenConsole()
  PrintN("The length of the fruit array is " + length)
  PrintN("")
  PrintN("Press any key to close the console")
  Repeat: Delay(10) : Until Inkey() <> ""
  CloseConsole()
EndIf


>>> print(len(['apple', 'orange']))
2
>>>


Dim max As Integer, Index As Integer
Randomize Timer
max = Int(Rnd * 10) + 1
Dim StringAr(1 To max) As String

For Index = 1 To max
    If Int(Rnd * 6) + 1 <= 3 Then StringAr(Index) = "Apple" Else StringAr(Index) = "orange"
Next
Print UBound(Stringar)
End


a <- c('apple','orange')   # create a vector containing "apple" and "orange"
length(a)


#lang racket/base
(length '("apple" "orange")) ;; list
(vector-length #("apple" "orange")) ;; vector


my @array = <apple orange>;

say @array.elems;  # 2
say elems @array;  # 2
say + @array;      # 2
say @array + 0;    # 2


relation fruit
insert "apples"
insert "oranges"
project fruit count
print


let fruits = ["apple", "orange"]

Js.log(Js.Array.length(fruits))


/* REXX ----------------------------------------------
* The compond variable a. implements an array
* By convention, a.0 contains the number of elements
*---------------------------------------------------*/
a.=0                   /* initialize the "array" */
call store 'apple'
Call store 'orange'
Say 'There are' a.0 'elements in the array:'
Do i=1 To a.0
  Say 'Element' i':' a.i
  End
Exit
store: Procedure Expose a.
z=a.0+1
a.z=arg(1)
a.0=z
Return


See len(['apple', 'orange']) # output = 2


set "index" to 0
set "$array&index&" to "apple"
inc "index" by 1
set "$array&index&" to "orange"
* "Array length: ('index' + 1)"


puts ['apple', 'orange'].length  # or .size


fn main() {
    let array = ["foo", "bar", "baz", "biff"];
    println!("the array has {} elements", array.len());
}


(display (vector-length #("apple" "orange")))


$ include "seed7_05.s7i";

const array string: anArray is [] ("apple", "orange");

const proc: main is func
  begin
    writeln(length(anArray));
  end func;


put ("apple", "orange", "pear", "banana", "aubergine") into fruits
put the number of items in fruits


\\ Using a vector
\\ @v creates the vector
\\ <> ends the vector
\\ limit returns the length of a vector
\\ apple and orange are symbols (vs strings) in this case.
(limit (@v apple orange <>))

\\ As an list
(length [apple orange])


var arr = ['apple', 'orange'];
say arr.len;        #=> 2
say arr.end;        #=> 1 (zero based)


COMMENT ARRAY-LENGTH;
BEGIN

    INTEGER PROCEDURE ARRAYLENGTH(A); TEXT ARRAY A;
    BEGIN
        ARRAYLENGTH := UPPERBOUND(A, 1) - LOWERBOUND(A, 1) + 1;
    END ARRAYLENGTH;

    TEXT ARRAY A(1:2);
    INTEGER L;
    A(1) :- "APPLE";
    A(2) :- "ORANGE";
    L := ARRAYLENGTH(A);
    OUTINT(L, 0);
    OUTIMAGE;
END


    ar = ARRAY('2,2')
    ar<1,1> = 'apple'
    ar<1,2> = 'first'
    ar<2,1> = 'orange'
    ar<2,2> = 'second'
    OUTPUT = IDENT(DATATYPE(ar), 'ARRAY') PROTOTYPE(ar)
end


a = ["apple","orange"]
#.output("Number of elements in array: ",#.size(a,1))


SELECT COUNT() FROM (VALUES ('apple'),('orange'));


let
  val a = Array.fromList ["apple", "orange"]
in
  Array.length a
end;


clear
input str10 fruit
apple
orange
end

di _N
di c(N) " " c(k)


let fruits = ["apple", "orange"] // Declare constant array literal
let fruitsCount = fruits.count // Declare constant array length (count)

print(fruitsCount) // Print array length to output window


| Symsyn does not support Array of Strings
| The following code for an Array of Integers

A : 125 0
  #A []
| shows 125

| A list of fixed length strings can be handled this way

S : 'apple ' : 'orange'
  div #S 6 sz
  sz []
| shows 2


['apple', 'orange'] -> $::length -> !OUT::write


;# not recommended:
set mylistA {apple orange}   ;# actually a string
set mylistA "Apple Orange"   ;# same - this works only for simple cases

set lenA [llength $mylistA]
puts "$mylistA :  $lenA"

# better:  to build a list, use 'list' and/or 'lappend':
set mylistB [list apple orange "red wine" {green frog}]
lappend mylistB "blue bird"

set lenB [llength $mylistB]
puts "$mylistB :  $lenB"


#lang transd

MainModule : {
    _start: (lambda
        (with v ["apple", "orange"]
            (lout (size v))
        )
        (lout (size ["apple", "orange"]))
    )
}


#!/bin/bash
array=("orange" "apple")
echo "${#array[@]}"


> decl string<> stream
> append "two" "strings" stream
> out (size stream) endl console
2
> out (size "test string") endl console
11
>


void main() {
  string[] fruit = {"apple", "orange"};
  stdout.printf("%d\n", fruit.length);
}


Debug.Print "Array Length: " & UBound(Array("apple", "orange")) + 1


arr = Array("apple","orange")
WScript.StdOut.WriteLine UBound(arr) - LBound(arr) + 1


' declared in a module
Public Function LengthOfArray(ByRef arr As Variant) As Long
  If IsArray(arr) Then
     LengthOfArray = UBound(arr) - LBound(arr) + 1
  Else
     LengthOfArray = -1
  End If
End Function

' somewhere in the programm
' example 1
  Dim arr As Variant

  arr = Array("apple", "orange")

  Debug.Print LengthOfArray(arr) ' prints 2 as result

' example 2
  Dim arr As Variant

  ReDim arr(-2 To -1)
  arr(-2) = "apple"
  arr(-1) = "orange"

  Debug.Print LengthOfArray(arr) ' prints 2 as result


Module ArrayLength

    Sub Main()
        Dim array() As String = {"apple", "orange"}
        Console.WriteLine(array.Length)
    End Sub

End Module


// V, array length
// Tectonics: v run array-length.v
module main

// access array length
pub fn main() {
    arr := ["apple", "orange"]
    println(arr.len)
}


let io => import 'io';
let a => ['apple'; 'orange'];
len a -- io.writeln io.stdout;


var arr = ["apple", "orange"]
System.print(arr.count)


dim fruta$(3)
read fruta$(1), fruta$(2), fruta$(3)
data "apple", "orange", "pear"

print arraysize(fruta$(),1)
print fruta$(2)
end


	org &8000
	ld hl,TestArray
	call GetArrayLength_WordData_NullTerminated

	call Monitor            ;show registers to screen, code omitted to keep this example short

ReturnToBasic:
	RET

GetArrayLength_WordData_NullTerminated:
	push hl			;we'll need this later
loop_GetArrayLength_WordData_NullTerminated
	ld a,(hl)		;get the low byte
	ld e,a			;stash it in E
	inc hl			;next byte
	ld a,(hl)		;get the high byte
	dec hl			;go back to low byte, otherwise our length will be off.
	or a			;compare to zero. This is a shorter and faster way to compare A to zero than "CP 0"

	jr nz,keepGoing
		cp e		;compare to E
		jr z,Terminated_GetArrayLength			        ;both bytes were zero.
KeepGoing:
	inc hl
	inc hl								;next word
	jp loop_GetArrayLength_WordData_NullTerminated	                ;back to start
Terminated_GetArrayLength:
	pop de		;original array address is in DE
	;or a		;normally it's best to clear the carry, but in this situation execution only arrives here after a compare that
                        ;resulted in an equality to zero, which means the carry is guaranteed to be cleared.
	sbc hl,de	;there is no sub hl,de; only sbc

	srl h
	rr l		;divide HL by 2, since each element is 2 bytes.

	ret		;returns length in hl

TestArray:
	word Apple,Orange
	byte 0,0

Apple:
	byte "Apple",0
Orange:
	byte "Orange",0


List("apple", "orange").len().println() //-->2, == L("apple", "orange")
T("apple", "orange").len().println() //-->2, read only list (ROList)


const std = @import("std");

pub fn main() !void {
    // left hand side type can be ommitted
    const fruit: [2][]const u8 = [_][]const u8{ "apples", "oranges" };
    const stdout_wr = std.io.getStdOut().writer();
    // slices and arrays have an len field
    try stdout_wr.print("fruit.len = {d}\n", .{fruit.len});
}


program: array_length
  input: [a,b,c]
  output: 3


module AryLength;
type
	Vector = array 12 of string;
	Matrix = array *,* of string;
var
	a: Vector;
	b: Matrix;
begin
	writeln(len(a):4);		(* len(a) = len(a,0) *)

	b := new Matrix(10,11);
	writeln(len(b,0):4); 	(* first dimension *)
	writeln(len(b,1):4)		(* second dimension *)
end AryLength.


V dict = [‘key1’ = 1, ‘key2’ = 2]
V value2 = dict[‘key2’]


/* ARM assembly AARCH64 Raspberry PI 3B or android 64 bits */
/*  program hashmap64.s   */

/*******************************************/
/* Constantes file                         */
/*******************************************/
/* for this file see task include a file in language AArch64 assembly*/
.include "../includeConstantesARM64.inc"
.equ MAXI, 10
.equ HEAPSIZE,20000
.equ LIMIT, 10                  // key characters number for compute hash
.equ COEFF, 80                  // filling rate 80 = 80%

/*******************************************/
/* Structures                               */
/********************************************/
/* structure hashMap   */
    .struct  0
hash_count:                       //  stored values counter
    .struct  hash_count + 8
hash_key:                         //  key
    .struct  hash_key + (8 * MAXI)
hash_data:                        // data
    .struct  hash_data + (8 * MAXI)
hash_fin:
/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessFin:          .asciz "End program.\n"
szCarriageReturn:   .asciz "\n"
szMessNoP:          .asciz "Key not found !!!\n"
szKey1:             .asciz "one"
szData1:            .asciz "Ceret"
szKey2:             .asciz "two"
szData2:            .asciz "Maureillas"
szKey3:             .asciz "three"
szData3:            .asciz "Le Perthus"
szKey4:             .asciz "four"
szData4:            .asciz "Le Boulou"

.align 4
iptZoneHeap:    .quad sZoneHeap            // start heap address
iptZoneHeapEnd: .quad sZoneHeap + HEAPSIZE // end heap address
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
tbHashMap1:       .skip hash_fin         // hashmap
sZoneHeap:        .skip HEAPSIZE         // heap
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                          // entry of program

    ldr x0,qAdrtbHashMap1
    bl hashInit                // init hashmap
    ldr x0,qAdrtbHashMap1
    ldr x1,qAdrszKey1          // store key one
    ldr x2,qAdrszData1
    bl hashInsert
    cmp x0,#0                  // error ?
    bne 100f
    ldr x0,qAdrtbHashMap1
    ldr x1,qAdrszKey2         // store key two
    ldr x2,qAdrszData2
    bl hashInsert
    cmp x0,#0
    bne 100f

    ldr x0,qAdrtbHashMap1
    ldr x1,qAdrszKey3          // store key three
    ldr x2,qAdrszData3
    bl hashInsert
    cmp x0,#0
    bne 100f
    ldr x0,qAdrtbHashMap1
    ldr x1,qAdrszKey4          // store key four
    ldr x2,qAdrszData4
    bl hashInsert
    cmp x0,#0
    bne 100f

    ldr x0,qAdrtbHashMap1
    ldr x1,qAdrszKey2          // remove key two
    bl hashRemoveKey
    cmp x0,#0
    bne 100f

    ldr x0,qAdrtbHashMap1
    ldr x1,qAdrszKey1          // search key one
    bl searchKey
    cmp x0,#-1
    beq 1f
    bl affichageMess
    ldr x0,qAdrszCarriageReturn
    bl affichageMess
    b 2f
1:
    ldr x0,qAdrszMessNoP
    bl affichageMess
2:
    ldr x0,qAdrtbHashMap1
    ldr x1,qAdrszKey2          // search key two
    bl searchKey
    cmp x0,#-1
    beq 3f
    bl affichageMess
    ldr x0,qAdrszCarriageReturn
    bl affichageMess
    b 4f
3:
    ldr x0,qAdrszMessNoP
    bl affichageMess
4:
    ldr x0,qAdrtbHashMap1
    ldr x1,qAdrszKey4          // search key four
    bl searchKey
    cmp x0,#-1
    beq 5f
    bl affichageMess
    ldr x0,qAdrszCarriageReturn
    bl affichageMess
    b 6f
5:
    ldr x0,qAdrszMessNoP
    bl affichageMess
6:
    ldr x0,qAdrszMessFin
    bl affichageMess

100:                                  // standard end of the program
    mov x0, #0                        // return code
    mov x8, #EXIT                     // request to exit program
    svc #0                            // perform the system call

qAdrszCarriageReturn:     .quad szCarriageReturn
qAdrszMessFin:            .quad szMessFin
qAdrtbHashMap1:           .quad tbHashMap1
qAdrszKey1:               .quad szKey1
qAdrszData1:              .quad szData1
qAdrszKey2:               .quad szKey2
qAdrszData2:              .quad szData2
qAdrszKey3:               .quad szKey3
qAdrszData3:              .quad szData3
qAdrszKey4:               .quad szKey4
qAdrszData4:              .quad szData4
qAdrszMessNoP:            .quad szMessNoP
/***************************************************/
/*     init hashMap               */
/***************************************************/
// x0 contains address to hashMap
hashInit:
    stp x1,lr,[sp,-16]!         // save  registres
    stp x2,x3,[sp,-16]!         // save  registres
    mov x1,#0
    mov x2,#0
    str x2,[x0,#hash_count]      // init counter
    add x0,x0,#hash_key         // start zone key/value
1:
    lsl x3,x1,#3
    add x3,x3,x0
    str x2,[x3,#hash_key]
    str x2,[x3,#hash_data]
    add x1,x1,#1
    cmp x1,#MAXI
    blt 1b
100:
    ldp x2,x3,[sp],16         // restaur des  2 registres
    ldp x1,lr,[sp],16         // restaur des  2 registres
    ret
/***************************************************/
/*     insert key/datas               */
/***************************************************/
// x0 contains address to hashMap
// x1 contains address to key
// x2 contains address to datas
hashInsert:
    stp x1,lr,[sp,-16]!         // save  registres
    stp x2,x3,[sp,-16]!         // save  registres
    stp x4,x5,[sp,-16]!         // save  registres
    stp x6,x7,[sp,-16]!         // save  registres
    mov x6,x0                   // save address
    bl hashIndex                // search void key or identical key
    cmp x0,#0                   // error ?
    blt 100f

    ldr x3,qAdriptZoneHeap
    ldr x3,[x3]
    ldr x7,qAdriptZoneHeapEnd
    ldr x7,[x7]
    sub x7,x7,#50
    lsl x0,x0,#3               // 8 bytes
    add x5,x6,#hash_key        // start zone key/value
    ldr x4,[x5,x0]
    cmp x4,#0                  // key already stored ?
    bne 1f
    ldr x4,[x6,#hash_count]    // no -> increment counter
    add x4,x4,#1
    cmp x4,#(MAXI * COEFF / 100)
    bge 98f
    str x4,[x6,#hash_count]
1:
    str x3,[x5,x0]            // store heap key address in hashmap
    mov x4,#0
2:                            // copy key loop in heap
    ldrb w5,[x1,x4]
    strb w5,[x3,x4]
    cmp w5,#0
    add x4,x4,#1
    bne 2b
    add x3,x3,x4
    cmp x3,x7
    bge 99f
    add x1,x6,#hash_data
    str x3,[x1,x0]           // store heap data address in hashmap
    mov x4,#0
3:                            // copy data loop in heap
    ldrb w5,[x2,x4]
    strb w5,[x3,x4]
    cmp w5,#0
    add x4,x4,#1
    bne 3b
    add x3,x3,x4
    cmp x3,x7
    bge 99f
    ldr x0,qAdriptZoneHeap
    str x3,[x0]               // new heap address

    mov x0,#0                 // insertion OK
    b 100f
98:                           // error hashmap
    adr x0,szMessErrInd
    bl affichageMess
    mov x0,#-1
    b 100f
99:                           // error heap
    adr x0,szMessErrHeap
    bl affichageMess
    mov x0,#-1
100:
    ldp x6,x7,[sp],16         // restaur des  2 registres
    ldp x4,x5,[sp],16         // restaur des  2 registres
    ldp x2,x3,[sp],16         // restaur des  2 registres
    ldp x1,lr,[sp],16         // restaur des  2 registres
    ret
szMessErrInd:          .asciz "Error : HashMap size Filling rate Maxi !!\n"
szMessErrHeap:         .asciz "Error : Heap size  Maxi !!\n"
.align 4
qAdriptZoneHeap:       .quad iptZoneHeap
qAdriptZoneHeapEnd:    .quad iptZoneHeapEnd
/***************************************************/
/*     search void index in hashmap              */
/***************************************************/
// x0 contains hashMap address
// x1 contains key address
hashIndex:
    stp x1,lr,[sp,-16]!         // save  registres
    stp x2,x3,[sp,-16]!         // save  registres
    stp x4,x5,[sp,-16]!         // save  registres
    add x4,x0,#hash_key
    mov x2,#0             // index
    mov x3,#0             // characters sum
1:                        // loop to compute characters sum
    ldrb w0,[x1,x2]
    cmp w0,#0             // string end ?
    beq 2f
    add x3,x3,x0          // add to sum
    add x2,x2,#1
    cmp x2,#LIMIT
    blt 1b
2:
    mov x5,x1             // save key address
    mov x0,x3
    mov x1,#MAXI
    udiv x2,x0,x1
    msub x3,x2,x1,x0           // compute remainder -> x3
    mov x1,x5             // key address

3:
    ldr x0,[x4,x3,lsl #3] // loak key for computed index
    cmp x0,#0             // void key ?
    beq 4f
    bl comparStrings      // identical key ?
    cmp x0,#0
    beq 4f                // yes
    add x3,x3,#1          // no search next void key
    cmp x3,#MAXI          // maxi ?
    csel x3,xzr,x3,ge     // restart to index 0
    b 3b
4:
    mov x0,x3             // return index void array or key equal
100:
    ldp x4,x5,[sp],16         // restaur des  2 registres
    ldp x2,x3,[sp],16         // restaur des  2 registres
    ldp x1,lr,[sp],16         // restaur des  2 registres
    ret

/***************************************************/
/*     search key in hashmap              */
/***************************************************/
// x0 contains hash map address
// x1 contains key address
searchKey:
    stp x1,lr,[sp,-16]!         // save  registres
    stp x2,x3,[sp,-16]!         // save  registres
    mov x2,x0
    bl hashIndex
    lsl x0,x0,#3
    add x1,x0,#hash_key
    ldr x1,[x2,x1]
    cmp x1,#0
    beq 2f
    add x1,x0,#hash_data
    ldr x0,[x2,x1]
    b 100f
2:
    mov x0,#-1
100:
    ldp x2,x3,[sp],16         // restaur des  2 registres
    ldp x1,lr,[sp],16         // restaur des  2 registres
    ret
/***************************************************/
/*     remove key in hashmap              */
/***************************************************/
// x0 contains hash map address
// x1 contains key address
hashRemoveKey:
    stp x1,lr,[sp,-16]!         // save  registres
    stp x2,x3,[sp,-16]!         // save  registres
    mov x2,x0
    bl hashIndex
    lsl x0,x0,#3
    add x1,x0,#hash_key
    ldr x3,[x2,x1]
    cmp x3,#0
    beq 2f
    str xzr,[x2,x1]            // raz key address
    add x1,x0,#hash_data
    str xzr,[x2,x1]            // raz datas address
    mov x0,0
    b 100f
2:
    adr x0,szMessErrRemove
    bl affichageMess
    mov x0,#-1
100:
    ldp x2,x3,[sp],16         // restaur des  2 registres
    ldp x1,lr,[sp],16         // restaur des  2 registres
    ret
szMessErrRemove:         .asciz "\033[31mError remove key !!\033[0m\n"
.align 4
/************************************/
/* Strings case sensitive comparisons  */
/************************************/
/* x0 et x1 contains the address of strings */
/* return 0 in x0 if equals */
/* return -1 if string x0 < string x1 */
/* return 1  if string x0 > string x1 */
comparStrings:
    stp x1,lr,[sp,-16]!  // save  registres
    stp x2,x3,[sp,-16]!  // save  registres
    stp x4,x5,[sp,-16]!  // save  registres
    mov x2,#0            // characters counter
1:
    ldrb w3,[x0,x2]      // byte string 1
    ldrb w4,[x1,x2]      // byte string 2
    cmp w3,w4
    blt 2f
    bgt 3f
    cmp w3,#0            // 0 end string ?
    beq 4f
    add x2,x2,#1         // else add 1 in counter
    b 1b                 // and loop
2:
    mov x0,#-1           // smaller
    b 100f
3:
    mov x0,#1            // greather
    b 100f
4:
    mov x0,#0           // equals
100:
    ldp x4,x5,[sp],16   // restaur des  2 registres
    ldp x2,x3,[sp],16   // restaur des  2 registres
    ldp x1,lr,[sp],16   // restaur des  2 registres
    ret
/********************************************************/
/*        File Include fonctions                        */
/********************************************************/
/* for this file see task include a file in language AArch64 assembly */
.include "../includeARM64.inc"


var map:Object = {key1: "value1", key2: "value2"};
trace(map['key1']); // outputs "value1"

// Dot notation can also be used
trace(map.key2); // outputs "value2"

// More keys and values can then be added
map['key3'] = "value3";
trace(map['key3']); // outputs "value3"


with Ada.Containers.Ordered_Maps;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO;

procedure Associative_Array is

   -- Instantiate the generic package Ada.Containers.Ordered_Maps

   package Associative_Int is new Ada.Containers.Ordered_Maps(Unbounded_String, Integer);
   use Associative_Int;

   Color_Map : Map;
   Color_Cursor : Cursor;
   Success : Boolean;
   Value : Integer;
begin

   -- Add values to the ordered map

   Color_Map.Insert(To_Unbounded_String("Red"), 10, Color_Cursor, Success);
   Color_Map.Insert(To_Unbounded_String("Blue"), 20, Color_Cursor, Success);
   Color_Map.Insert(To_Unbounded_String("Yellow"), 5, Color_Cursor, Success);

   -- retrieve values from the ordered map and print the value and key
   -- to the screen

   Value := Color_Map.Element(To_Unbounded_String("Red"));
   Ada.Text_Io.Put_Line("Red:" & Integer'Image(Value));
   Value := Color_Map.Element(To_Unbounded_String("Blue"));
   Ada.Text_IO.Put_Line("Blue:" & Integer'Image(Value));
   Value := Color_Map.Element(To_Unbounded_String("Yellow"));
   Ada.Text_IO.Put_Line("Yellow:" & Integer'Image(Value));
end Associative_Array;


var names = {}   // empty map
names["foo"] = "bar"
names[3] = 4

// initialized map
var names2 = {"foo": bar, 3:4}

// lookup map
var name = names["foo"]
if (typeof(name) == "none") {
    println ("not found")
} else {
    println (name)
}

// remove from map
delete names["foo"]


main:(

  MODE COLOR = BITS;
  FORMAT color repr = $"16r"16r6d$;

  # This is an associative array which maps strings to ints #
  MODE ITEM = STRUCT(STRING key, COLOR value);
  REF[]ITEM color map items := LOC[0]ITEM;

  PROC color map find = (STRING color)REF COLOR:(
    REF COLOR out;
# linear search! #
    FOR index FROM LWB key OF color map items TO UPB key OF color map items DO
      IF color = key OF color map items[index] THEN
        out := value OF color map items[index]; GO TO found
      FI
    OD;
      NIL EXIT
    found:
      out
  );

  PROC color map = (STRING color)REF COLOR:(
    REF COLOR out = color map find(color);
    IF out :=: REF COLOR(NIL) THEN # extend color map array #
      HEAP[UPB key OF color map items + 1]ITEM color map append;
      color map append[:UPB key OF color map items] := color map items;
      color map items := color map append;
      value OF (color map items[UPB value OF color map items] := (color, 16r000000)) # black #
    ELSE
      out
    FI
  );

  # First, populate it with some values #
  color map("red") := 16rff0000;
  color map("green") := 16r00ff00;
  color map("blue") := 16r0000ff;
  color map("my favourite color") := 16r00ffff;

  # then, get some values out #
  COLOR color := color map("green"); # color gets 16r00ff00 #
  color := color map("black"); # accessing unassigned values assigns them to 16r0 #

  # get some value out without accidentally inserting new ones #
  REF COLOR value = color map find("green");
  IF value :=: REF COLOR(NIL) THEN
    put(stand error, ("color not found!", new line))
  ELSE
    printf(($"green: "f(color repr)l$, value))
  FI;

  # Now I changed my mind about my favourite color, so change it #
  color map("my favourite color") := 16r337733;

  # print out all defined colors #
  FOR index FROM LWB color map items TO UPB color map items DO
    ITEM item = color map items[index];
    putf(stand error, ($"color map("""g""") = "f(color repr)l$, item))
  OD;

  FORMAT fmt;
  FORMAT comma sep = $"("n(UPB color map items-1)(f(fmt)", ")f(fmt)")"$;

  fmt := $""""g""""$;
  printf(($g$,"keys: ", comma sep, key OF color map items, $l$));
  fmt := color repr;
  printf(($g$,"values: ", comma sep, value OF color map items, $l$))

)


// Cannot / Do not need to instantiate the algorithm implementation (e.g, HashMap).
Map<String, String> strMap = new Map<String, String>();
strMap.put('a', 'aval');
strMap.put('b', 'bval');

System.assert( strMap.containsKey('a') );
System.assertEquals( 'bval', strMap.get('b') );
// String keys are case-sensitive
System.assert( !strMap.containsKey('A') );


⍝  Create a namespace ("hash")
      X←⎕NS ⍬

      ⍝ Assign some names
      X.this←'that'
      X.foo←88

      ⍝  Access the names
      X.this
that

      ⍝  Or do it the array way
      X.(foo this)
88  that

      ⍝  Namespaces are first class objects
      sales ← ⎕NS ⍬
      sales.(prices quantities) ← (100 98.4 103.4 110.16) (10  12 8  10)
      sales.(revenue ← prices +.× quantities)
      sales.revenue
4109.6


/* ARM assembly Raspberry PI  or android 32 bits */
/*  program hashmap.s   */

/*      */

/* REMARK 1 : this program use routines in a include file
   see task Include a file language arm assembly
   for the routine affichageMess conversion10
   see at end of this program the instruction include */
/* for constantes see task include a file in arm assembly */
/************************************/
/* Constantes                       */
/************************************/
.include "../constantes.inc"
.equ MAXI, 10                   @ size hashmap
.equ HEAPSIZE,20000
.equ LIMIT, 10                  @ key characters number for compute index
.equ COEFF, 80                  @ filling rate 80 = 80%

/*******************************************/
/* Structures                               */
/********************************************/
/* structure hashMap   */
    .struct  0
hash_count:                       //  stored values counter
    .struct  hash_count + 4
hash_key:                         //  key
    .struct  hash_key + (4 * MAXI)
hash_data:                        // data
    .struct  hash_data + (4 * MAXI)
hash_fin:
/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessFin:          .asciz "End program.\n"
szCarriageReturn:   .asciz "\n"
szMessNoP:          .asciz "Key not found !!!\n"
szKey1:             .asciz "one"
szData1:            .asciz "Ceret"
szKey2:             .asciz "two"
szData2:            .asciz "Maureillas"
szKey3:             .asciz "three"
szData3:            .asciz "Le Perthus"
szKey4:             .asciz "four"
szData4:            .asciz "Le Boulou"

.align 4
iptZoneHeap:    .int sZoneHeap            // start heap address
iptZoneHeapEnd: .int sZoneHeap + HEAPSIZE // end heap address
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
//sZoneConv:        .skip 24
tbHashMap1:       .skip hash_fin         @ hashmap
sZoneHeap:        .skip HEAPSIZE         @ heap
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                          @ entry of program

    ldr r0,iAdrtbHashMap1
    bl hashInit                @ init hashmap
    ldr r0,iAdrtbHashMap1
    ldr r1,iAdrszKey1          @ store key one
    ldr r2,iAdrszData1
    bl hashInsert
    cmp r0,#0                  @ error ?
    bne 100f
    ldr r0,iAdrtbHashMap1
    ldr r1,iAdrszKey2          @ store key two
    ldr r2,iAdrszData2
    bl hashInsert
    cmp r0,#0
    bne 100f
    ldr r0,iAdrtbHashMap1
    ldr r1,iAdrszKey3          @ store key three
    ldr r2,iAdrszData3
    bl hashInsert
    cmp r0,#0
    bne 100f
    ldr r0,iAdrtbHashMap1
    ldr r1,iAdrszKey4          @ store key four
    ldr r2,iAdrszData4
    bl hashInsert
    cmp r0,#0
    bne 100f

    ldr r0,iAdrtbHashMap1
    ldr r1,iAdrszKey2          @ remove key two
    bl hashRemoveKey
    cmp r0,#0
    bne 100f

    ldr r0,iAdrtbHashMap1
    ldr r1,iAdrszKey1         @ search key
    bl searchKey
    cmp r0,#-1
    beq 1f
    bl affichageMess
    ldr r0,iAdrszCarriageReturn
    bl affichageMess
    b 2f
1:
    ldr r0,iAdrszMessNoP
    bl affichageMess
2:
    ldr r0,iAdrtbHashMap1
    ldr r1,iAdrszKey2
    bl searchKey
    cmp r0,#-1
    beq 3f
    bl affichageMess
    ldr r0,iAdrszCarriageReturn
    bl affichageMess
    b 4f
3:
    ldr r0,iAdrszMessNoP
    bl affichageMess
4:
    ldr r0,iAdrtbHashMap1
    ldr r1,iAdrszKey4
    bl searchKey
    cmp r0,#-1
    beq 5f
    bl affichageMess
    ldr r0,iAdrszCarriageReturn
    bl affichageMess
    b 6f
5:
    ldr r0,iAdrszMessNoP
    bl affichageMess
6:
    ldr r0,iAdrszMessFin
    bl affichageMess

100:                                  @ standard end of the program
    mov r0, #0                        @ return code
    mov r7, #EXIT                     @ request to exit program
    svc #0                            @ perform the system call

iAdrszCarriageReturn:     .int szCarriageReturn
iAdrszMessFin:            .int szMessFin
iAdrtbHashMap1:           .int tbHashMap1
iAdrszKey1:               .int szKey1
iAdrszData1:              .int szData1
iAdrszKey2:               .int szKey2
iAdrszData2:              .int szData2
iAdrszKey3:               .int szKey3
iAdrszData3:              .int szData3
iAdrszKey4:               .int szKey4
iAdrszData4:              .int szData4
iAdrszMessNoP:            .int szMessNoP
/***************************************************/
/*     init hashMap               */
/***************************************************/
// r0 contains address to hashMap
hashInit:
    push {r1-r3,lr}             @ save  registers
    mov r1,#0
    mov r2,#0
    str r2,[r0,#hash_count]      @ init counter
    add r0,r0,#hash_key         @ start zone key/value
1:
    lsl r3,r1,#3
    add r3,r3,r0
    str r2,[r3,#hash_key]
    str r2,[r3,#hash_data]
    add r1,r1,#1
    cmp r1,#MAXI
    blt 1b
100:
    pop {r1-r3,pc}             @ restaur registers
/***************************************************/
/*     insert key/datas               */
/***************************************************/
// r0 contains address to hashMap
// r1 contains address to key
// r2 contains address to datas
hashInsert:
    push {r1-r8,lr}             @ save  registers
    mov r6,r0                   @ save address
    bl hashIndex                @ search void key or identical key
    cmp r0,#0                   @ error ?
    blt 100f

    ldr r3,iAdriptZoneHeap
    ldr r3,[r3]
    ldr r8,iAdriptZoneHeapEnd
    ldr r8,[r8]
    sub r8,r8,#50
    lsl r0,r0,#2               @ 4 bytes
    add r7,r6,#hash_key        @ start zone key/value
    ldr r4,[r7,r0]
    cmp r4,#0                  @ key already stored ?
    bne 1f
    ldr r4,[r6,#hash_count]    @ no -> increment counter
    add r4,r4,#1
    cmp r4,#(MAXI * COEFF / 100)
    bge 98f
    str r4,[r6,#hash_count]
1:
    str r3,[r7,r0]
    mov r4,#0
2:                            @ copy key loop in heap
    ldrb r5,[r1,r4]
    strb r5,[r3,r4]
    cmp r5,#0
    add r4,r4,#1
    bne 2b
    add r3,r3,r4
    cmp r3,r8
    bge 99f
    add r7,r6,#hash_data
    str r3,[r7,r0]
    mov r4,#0
3:                            @ copy data loop in heap
    ldrb r5,[r2,r4]
    strb r5,[r3,r4]
    cmp r5,#0
    add r4,r4,#1
    bne 3b
    add r3,r3,r4
    cmp r3,r8
    bge 99f
    ldr r0,iAdriptZoneHeap
    str r3,[r0]               @ new heap address

    mov r0,#0                 @ insertion OK
    b 100f
98:                           @ error hashmap
    adr r0,szMessErrInd
    bl affichageMess
    mov r0,#-1
    b 100f
99:                           @ error heap
    adr r0,szMessErrHeap
    bl affichageMess
    mov r0,#-1
100:
    pop {r1-r8,lr}             @ restaur registers
    bx lr                      @ return
szMessErrInd:          .asciz "Error : HashMap size Filling rate Maxi !!\n"
szMessErrHeap:         .asciz "Error : Heap size  Maxi !!\n"
.align 4
iAdriptZoneHeap:       .int iptZoneHeap
iAdriptZoneHeapEnd:    .int iptZoneHeapEnd
/***************************************************/
/*     search void index in hashmap              */
/***************************************************/
// r0 contains hashMap address
// r1 contains key address
hashIndex:
    push {r1-r4,lr}       @ save  registers
    add r4,r0,#hash_key
    mov r2,#0             @ index
    mov r3,#0             @ characters sum
1:                        @ loop to compute characters sum
    ldrb r0,[r1,r2]
    cmp r0,#0             @ string end ?
    beq 2f
    add r3,r3,r0          @ add to sum
    add r2,r2,#1
    cmp r2,#LIMIT
    blt 1b
2:
    mov r5,r1             @ save key address
    mov r0,r3
    mov r1,#MAXI
    bl division           @ compute remainder -> r3
    mov r1,r5             @ key address

3:
    ldr r0,[r4,r3,lsl #2] @ loak key for computed index
    cmp r0,#0             @ void key ?
    beq 4f
    bl comparStrings      @ identical key ?
    cmp r0,#0
    beq 4f                @ yes
    add r3,r3,#1          @ no search next void key
    cmp r3,#MAXI          @ maxi ?
    movge r3,#0           @ restart to index 0
    b 3b
4:
    mov r0,r3             @ return index void array or key equal
100:
    pop {r1-r4,pc}        @ restaur registers

/***************************************************/
/*     search key in hashmap              */
/***************************************************/
// r0 contains hash map address
// r1 contains key address
searchKey:
    push {r1-r2,lr}           @ save  registers
    mov r2,r0
    bl hashIndex
    lsl r0,r0,#2
    add r1,r0,#hash_key
    ldr r1,[r2,r1]
    cmp r1,#0
    moveq r0,#-1
    beq 100f
    add r1,r0,#hash_data
    ldr r0,[r2,r1]
100:
    pop {r1-r2,pc}            @ restaur registers
/***************************************************/
/*     remove key in hashmap              */
/***************************************************/
// r0 contains hash map address
// r1 contains key address
hashRemoveKey:                  @ INFO: hashRemoveKey
    push {r1-r3,lr}             @ save  registers
    mov r2,r0
    bl hashIndex
    lsl r0,r0,#2
    add r1,r0,#hash_key
    ldr r3,[r2,r1]
    cmp r3,#0
    beq  2f
    add r3,r2,r1
    mov r1,#0                   @ raz key address
    str r1,[r3]
    add r1,r0,#hash_data
    add r3,r2,r1
    mov r1,#0
    str r1,[r3]                 @ raz datas address
    mov r0,#0
    b 100f
2:
    adr r0,szMessErrRemove
    bl affichageMess
    mov r0,#-1
100:
    pop {r1-r3,pc}            @ restaur registers
szMessErrRemove:         .asciz "\033[31mError remove key !!\033[0m\n"
.align 4
/************************************/
/* Strings case sensitive comparisons  */
/************************************/
/* r0 et r1 contains the address of strings */
/* return 0 in r0 if equals */
/* return -1 if string r0 < string r1 */
/* return 1  if string r0 > string r1 */
comparStrings:
    push {r1-r4}         @ save des registres
    mov r2,#0            @ characters counter
1:
    ldrb r3,[r0,r2]      @ byte string 1
    ldrb r4,[r1,r2]      @ byte string 2
    cmp r3,r4
    movlt r0,#-1         @ smaller
    movgt r0,#1	         @ greather
    bne 100f             @ not equals
    cmp r3,#0            @ 0 end string ?
    moveq r0,#0          @ equals
    beq 100f             @ end string
    add r2,r2,#1         @ else add 1 in counter
    b 1b                 @ and loop
100:
    pop {r1-r4}
    bx lr
/***************************************************/
/*      ROUTINES INCLUDE                           */
/***************************************************/
.include "../affichage.inc"


; create a dictionary
d: #[
	name: 		"john"
	surname: 	"doe"
	age: 		34
]

print d


(*------------------------------------------------------------------*)

#define ATS_DYNLOADFLAG 0

#include "share/atspre_staload.hats"

(*------------------------------------------------------------------*)
(* Interface                                                        *)

(* You can put the interface in a .sats file. You will have to remove
   the word "extern". *)

typedef alist_t (key_t  : [email protected]+,
                 data_t : [email protected]+,
                 size   : int) =
  list (@(key_t, data_t), size)
typedef alist_t (key_t  : [email protected]+,
                 data_t : [email protected]+) =
  [size : int]
  alist_t (key_t, data_t, size)

extern prfun
lemma_alist_t_param :
  {size  : int} {key_t : [email protected]} {data_t : [email protected]}
  alist_t (key_t, data_t, size) -<prf> [0 <= size] void

extern fun {key_t : [email protected]}     (* Implement key equality with this. *)
alist_t$key_eq : (key_t, key_t) -<> bool

(* alist_t_nil: create an empty association list. *)
extern fun
alist_t_nil :
  {key_t : [email protected]} {data_t : [email protected]}
  () -<> alist_t (key_t, data_t, 0)

(* alist_t_set: add an association, deleting old associations with an
   equal key. *)
extern fun {key_t  : [email protected]}
           {data_t : [email protected]}
alist_t_set {size : int}
            (alst : alist_t (key_t, data_t, size),
             key  : key_t,
             data : data_t) :<>
    [sz : int | 1 <= sz]
    alist_t (key_t, data_t, sz)

(* alist_t_get: find an association and return its data, if
   present. *)
extern fun {key_t  : [email protected]}
           {data_t : [email protected]}
alist_t_get {size : int}
            (alst : alist_t (key_t, data_t, size),
             key  : key_t) :<>
    Option data_t

(* alist_t_delete: delete all associations with key. *)
extern fun {key_t  : [email protected]}
           {data_t : [email protected]}
alist_t_delete {size : int}
               (alst : alist_t (key_t, data_t, size),
                key  : key_t ) :<>
    [sz : int | 0 <= sz]
    alist_t (key_t, data_t, sz)

(* alist_t_make_pairs_generator: make a closure that returns
   the association pairs, one by one. This is a form of iterator.
   Analogous generators can be made for the keys or data values
   alone. *)
extern fun {key_t  : [email protected]}
           {data_t : [email protected]}
alist_t_make_pairs_generator
          {size : int}
          (alst : alist_t (key_t, data_t, size)) :<!wrt>
    () -<cloref,!refwrt> Option @(key_t, data_t)

(*------------------------------------------------------------------*)
(* Implementation                                                   *)

#define NIL list_nil ()
#define :: list_cons

primplement
lemma_alist_t_param alst =
  lemma_list_param alst

implement
alist_t_nil () =
  NIL

implement {key_t} {data_t}
alist_t_set (alst, key, data) =
  @(key, data) :: alist_t_delete (alst, key)

implement {key_t} {data_t}
alist_t_get (alst, key) =
  let
    fun
    loop {n : nat}
         .<n>.                  (* <-- proof of termination *)
         (lst : alist_t (key_t, data_t, n)) :<>
        Option data_t =
      case+ lst of
      | NIL => None ()
      | head :: tail =>
        if alist_t$key_eq (key, head.0) then
          Some (head.1)
        else
          loop tail

    prval _ = lemma_alist_t_param alst
  in
    loop alst
  end

implement {key_t} {data_t}
alist_t_delete (alst, key) =
  let
    fun
    delete {n : nat}
           .<n>.                (* <-- proof of termination *)
           (lst : alist_t (key_t, data_t, n)) :<>
        [m : nat] alist_t (key_t, data_t, m) =
      (* This implementation is *not* tail recursive, but has the
         minor advantage of preserving the order of entries without
         doing a lot of work. *)
      case+ lst of
      | NIL => lst
      | head :: tail =>
        if alist_t$key_eq (key, head.0) then
          delete tail
        else
          head :: delete tail

    prval _ = lemma_alist_t_param alst
  in
    delete alst
  end

implement {key_t} {data_t}
alist_t_make_pairs_generator alst =
  let
    typedef alist_t = [sz : int] alist_t (key_t, data_t, sz)

    val alst_ref = ref alst

    (* Cast the ref to a pointer so it can be enclosed in the
       closure. *)
    val alst_ptr = $UNSAFE.castvwtp0{ptr} alst_ref
  in
    lam () =>
      let
        val alst_ref = $UNSAFE.castvwtp0{ref alist_t} alst_ptr
      in
        case+ !alst_ref of
        | NIL => None ()
        | head :: tail =>
          begin
            !alst_ref := tail;
            (* For a keys generator, change the following line to
               "Some (head.0)"; for a data values generator, change
               it to "Some (head.1)". *)
            Some head
          end
      end
  end

(*------------------------------------------------------------------*)
(* Demonstration program                                            *)

implement
alist_t$key_eq<string> (s, t) =
  s = t

typedef s2i_alist_t = alist_t (string, int)

fn
s2i_alist_t_set (map  : s2i_alist_t,
                 key  : string,
                 data : int) :<> s2i_alist_t =
  alist_t_set<string><int> (map, key, data)

fn
s2i_alist_t_set_ref (map  : &s2i_alist_t >> _,
                     key  : string,
                     data : int) :<!wrt> void =
  (* Update a reference to a persistent alist. *)
  map := s2i_alist_t_set (map, key, data)

fn
s2i_alist_t_get (map  : s2i_alist_t,
                 key  : string) :<> Option int =
  alist_t_get<string><int> (map, key)

extern fun {}        (* {} = a template without template parameters *)
s2i_alist_t_get_dflt$dflt :<> () -> int
fn {}                (* {} = a template without template parameters *)
s2i_alist_t_get_dflt (map  : s2i_alist_t,
                      key  : string) : int =
  case+ s2i_alist_t_get (map, key) of
  | Some x => x
  | None () => s2i_alist_t_get_dflt$dflt<> ()

overload [] with s2i_alist_t_set_ref
overload [] with s2i_alist_t_get_dflt

implement
main0 () =
  let
    implement s2i_alist_t_get_dflt$dflt<> () = 0
    var map = alist_t_nil ()
    var gen : () -<cloref1> @(string, int)
    var pair : Option @(string, int)
  in
    map["one"] := 1;
    map["two"] := 2;
    map["three"] := 3;
    println! ("map[\"one\"] = ", map["one"]);
    println! ("map[\"two\"] = ", map["two"]);
    println! ("map[\"three\"] = ", map["three"]);
    println! ("map[\"four\"] = ", map["four"]);
    gen := alist_t_make_pairs_generator<string><int> map;
    for (pair := gen (); option_is_some pair; pair := gen ())
      println! (pair)
  end

(*------------------------------------------------------------------*)


associative_array := {key1: "value 1", "Key with spaces and non-alphanumeric characters !*+": 23}
MsgBox % associative_array.key1
	. "`n" associative_array["Key with spaces and non-alphanumeric characters !*+"]


; Associative arrays in AutoIt.
; All the required functions are below the examples.

; Initialize an error handler to deal with any COM errors..
global $oMyError = ObjEvent("AutoIt.Error", "AAError")

; first example, simple.
global $simple

; Initialize your array ...
AAInit($simple)

AAAdd($simple, "Appple", "fruit")
AAAdd($simple, "Dog", "animal")
AAAdd($simple, "Silicon", "tetravalent metalloid semiconductor")

ConsoleWrite("It is well-known that Silicon is a " & AAGetItem($simple, "Silicon") & "." & @CRLF)
ConsoleWrite(@CRLF)

; A more interesting example..

$ini_path = "AA_Test.ini"
; Put this prefs section in your ini file..
; [test]
; foo=foo value
; foo2=foo2 value
; bar=bar value
; bar2=bar2 value

global $associative_array
AAInit($associative_array)

; We are going to convert this 2D array into a cute associative array where we
; can access the values by simply using their respective key names..
$test_array = IniReadSection($ini_path, "test")

for $z = 1 to 2 ; do it twice, to show that the items are *really* there!
	for $i = 1 to $test_array[0][0]
		$key_name = $test_array[$i][0]
		ConsoleWrite("Adding '" & $key_name & "'.." & @CRLF)
		; key already exists in "$associative_array", use the pre-determined value..
		if AAExists($associative_array, $key_name) then
			$this_value = AAGetItem($associative_array, $key_name)
			ConsoleWrite("key_name ALREADY EXISTS! : =>" & $key_name & "<=" & @CRLF)
		else
			$this_value = $test_array[$i][1]
			; store left=right value pair in AA
			if $this_value then
				AAAdd($associative_array, $key_name, $this_value)
			endif
		endif
	next
next

ConsoleWrite(@CRLF & "Array Count: =>" & AACount($associative_array) & "<=" & @CRLF)
AAList($associative_array)

ConsoleWrite(@CRLF & "Removing 'foo'..")
AARemove($associative_array, "foo")

ConsoleWrite(@CRLF & "Array Count: =>" & AACount($associative_array) & "<=" & @CRLF)
AAList($associative_array)

AAWipe($associative_array)

; end

func AAInit(ByRef $dict_obj)
$dict_obj = ObjCreate("Scripting.Dictionary")
endfunc

; Adds a key and item pair to a Dictionary object..
func AAAdd(ByRef $dict_obj, $key, $val)
    $dict_obj.Add($key, $val)
    If @error Then return SetError(1, 1, -1)
endfunc

; Removes a key and item pair from a Dictionary object..
func AARemove(ByRef $dict_obj, $key)
	$dict_obj.Remove($key)
	If @error Then return SetError(1, 1, -1)
endfunc

; Returns true if a specified key exists in the associative array, false if not..
func AAExists(ByRef $dict_obj, $key)
	return $dict_obj.Exists($key)
endfunc

; Returns a value for a specified key name in the associative array..
func AAGetItem(ByRef $dict_obj, $key)
	return $dict_obj.Item($key)
endfunc

; Returns the total number of keys in the array..
func AACount(ByRef $dict_obj)
	return $dict_obj.Count
endfunc

; List all the "Key" > "Item" pairs in the array..
func AAList(ByRef $dict_obj)
ConsoleWrite("AAList: =>" & @CRLF)
	local $k = $dict_obj.Keys ; Get the keys
	; local $a = $dict_obj.Items ; Get the items (for reference)
	for $i = 0 to AACount($dict_obj) -1 ; Iterate the array
		ConsoleWrite($k[$i] & " ==> " & AAGetItem($dict_obj, $k[$i]) & @CRLF)
	next
endfunc

; Wipe the array, obviously.
func AAWipe(ByRef $dict_obj)
	$dict_obj.RemoveAll()
endfunc

; Oh oh!
func AAError()
	Local $err = $oMyError.number
	If $err = 0 Then $err = -1
	SetError($err)  ; to check for after this function returns
endfunc

;; End AA Functions.


BEGIN {
  a["red"] = 0xff0000
  a["green"] = 0x00ff00
  a["blue"] = 0x0000ff
  for (i in a) {
    printf "%8s %06x\n", i, a[i]
  }
  # deleting a key/value
  delete a["red"]
  for (i in a) {
    print i
  }
  # check if a key exists
  print ( "red" in a )   # print 0
  print ( "blue" in a )  # print 1
}


DECLARE associative ASSOC STRING

associative("abc") = "first three"
associative("xyz") = "last three"

PRINT associative("xyz")


global values$, keys$
dim values$[1]
dim keys$[1]

call updateKey("a","apple")
call updateKey("b","banana")
call updateKey("c","cucumber")

gosub show

print "I like to eat a " + getValue$("c") + " on my salad."

call deleteKey("b")
call updateKey("c","carrot")
call updateKey("e","endive")
gosub show

end

show:
for t = 0 to countKeys()-1
   print getKeyByIndex$(t) + " " + getValueByIndex$(t)
next t
print
return

subroutine updateKey(key$, value$)
   # update or add an item
   i=findKey(key$)
   if i=-1 then
      i = freeKey()
      keys$[i] = key$
   end if
   values$[i] = value$
end subroutine

subroutine deleteKey(key$)
   # delete by clearing the key
   i=findKey(key$)
   if i<>-1 then
      keys$[i] = ""
   end if
end subroutine

function freeKey()
   # find index of a free element in the array
   for n = 0 to keys$[?]-1
      if keys$[n]="" then return n
   next n
   redim keys$[n+1]
   redim values$[n+1]
   return n
end function

function findKey(key$)
   # return index or -1 if not found
   for n = 0 to keys$[?]-1
      if key$=keys$[n] then return n
   next n
   return -1
end function

function getValue$(key$)
   # return a value by the key or "" if not existing
   i=findKey(key$)
   if i=-1 then
      return ""
   end if
   return values$[i]
end function

function countKeys()
   # return number of items
   # remember to skip the empty keys (deleted ones)
   k = 0
   for n = 0 to keys$[?] -1
      if keys$[n]<>"" then k++
   next n
   return k
end function

function getValueByIndex$(i)
   # get a value by the index
   # remember to skip the empty keys (deleted ones)
   k = 0
   for n = 0 to keys$[?] -1
      if keys$[n]<>"" then
         if k=i then return values$[k]
         k++
      endif
   next n
   return ""
end function

function getKeyByIndex$(i)
   # get a key by the index
   # remember to skip the empty keys (deleted ones)
   k = 0
   for n = 0 to keys$[?] -1
      if keys$[n]<>"" then
         if k=i then return keys$[k]
         k++
      endif
   next n
   return ""
end function


::assocarrays.cmd
@echo off
setlocal ENABLEDELAYEDEXPANSION
set array.dog=1
set array.cat=2
set array.wolf=3
set array.cow=4
for %%i in (dog cat wolf cow) do call :showit array.%%i !array.%%i!
set c=-27
call :mkarray sicko flu 5 measles 6 mumps 7 bromodrosis 8
for %%i in (flu measles mumps bromodrosis) do call :showit "sicko^&%%i" !sicko^&%%i!
endlocal
goto :eof

:mkarray
set %1^&%2=%3
shift /2
shift /2
if "%2" neq "" goto :mkarray
goto :eof

:showit
echo %1 = %2
goto :eof


      REM Store some values with their keys:
      PROCputdict(mydict$, "FF0000", "red")
      PROCputdict(mydict$, "00FF00", "green")
      PROCputdict(mydict$, "0000FF", "blue")

      REM Retrieve some values using their keys:
      PRINT FNgetdict(mydict$, "green")
      PRINT FNgetdict(mydict$, "red")
      END

      DEF PROCputdict(RETURN dict$, value$, key$)
      IF dict$ = "" dict$ = CHR$(0)
      dict$ += key$ + CHR$(1) + value$ + CHR$(0)
      ENDPROC

      DEF FNgetdict(dict$, key$)
      LOCAL I%, J%
      I% = INSTR(dict$, CHR$(0) + key$ + CHR$(1))
      IF I% = 0 THEN = "" ELSE I% += LEN(key$) + 2
      J% = INSTR(dict$, CHR$(0), I%)
      = MID$(dict$, I%, J% - I%)


  new$hash:?myhash
& (myhash..insert)$(title."Some title")
& (myhash..insert)$(formula.a+b+x^7)
& (myhash..insert)$(fruit.apples oranges kiwis)
& (myhash..insert)$(meat.)
& (myhash..insert)$(fruit.melons bananas)
& out$(myhash..find)$fruit
& (myhash..remove)$formula
& (myhash..insert)$(formula.x^2+y^2)
& out$(myhash..find)$formula;


h = [:]  #Empty hash

h[:a] = 1  #Assign value
h[:b] = [1 2 3] #Assign another value

h2 = [a: 1, b: [1 2 3], 10 : "ten"]  #Initialized hash

h2[:b][2]  #Returns 3


System.Collections.HashTable map = new System.Collections.HashTable();
map["key1"] = "foo";