Skip to Content

Ordenación Elemental

Número de ejecuciones de un programa

Para analizar la eficiencia de un algoritmo, es necesario contar el número de veces que se ejecutan las instrucciones.

Para contar cuántas veces se ejecuta una operación, debemos tener en cuenta todos los comandos disponibles.

En el comando skip\skip no se ejecuta ninguna operación, por lo que el número de operaciones es 0.

ops(skip)=0\textnormal{ops}(\skip) = 0

En el caso de for\for, debemos tener en cuenta que la siguiente ecuación vale si no hay interés en contar las operaciones que involucran el índice kk.

ops(for  k:=n  to  m  do  C(k)  od)=nmops(C(k))\textnormal{ops}(\for \; k:= n \; \too \; m \; \do \; C(k) \; \od) = \displaystyle{\sum_{n}^{m} \textnormal{ops}(C(k))}

Para if\if contamos cuantas veces se ejecuta durante la evaluiación de bb y luego cuantas en la ejecución de CC y DD (caso verdadero y falso)

ops(if  b  then  C  else  D  fi)={ops(b)+ops(C)si b es verdaderoops(b)+ops(D)si b es falso\textnormal{ops}(\if \; b \; \then \; C \; \else \; D \; \fi) = \begin{cases} \textnormal{ops}(b) + \textnormal{ops}(C) & \text{si } b \text{ es verdadero} \\ \textnormal{ops}(b) + \textnormal{ops}(D) & \text{si } b \text{ es falso} \end{cases}

Para la asignación, debemos considerar el caso de modificación de la variable. Debemos considerar que tal vez, el nuevo valor es la llamada a una función que también tiene un costo.

ops(x:=e)={ops(e)+1si x es modificadaops(e)si x no es modificada\textnormal{ops}(x := e) = \begin{cases} \textnormal{ops}(e) + 1 & \text{si } x \text{ es modificada} \\ \textnormal{ops}(e) & \text{si } x \text{ no es modificada} \end{cases}

Para las expresiones, consideramos el caso de contar comparaciones:

ops(e<f)={ops(e)+ops(f)+1si se cuentan comparacionesops(e)+ops(f)caso contrario \textnormal{ops}(e<f) = \begin{cases} \textnormal{ops}(e) + \textnormal{ops}(f) + 1 & \text{si se cuentan comparaciones} \\ \textnormal{ops}(e) + \textnormal{ops}(f) & \text{caso contrario } \end{cases}

En el caso de los ciclos (do\do) tenemos que:

ops(do  bC  od)=ops(b)+k=1n  dk\textnormal{ops}(\do \; b \rightarrow C \; \od) = \textnormal{ops}(b) + \displaystyle{\sum_{k=1}^n \; d_k}

Donde nn es el número de veces que el cuerpo del ciclo se ejecuta, y dkd_k s el número de operaciones que se ejecutan en la kk-ésima iteración.

Ejercicios resueltos - Número de ejecuciones de un programa

1.

Calcular el número de asignaciones de la variable tt en el siguiente algoritmo:

t:=0for  i:=1  to  n  dofor  j:=1  to  n2  dofor  k:=1  to  n3  dot:=t+1ododod  ops(t:=0)+ops(for  i:=1  to  n  dofor  j:=1  to  n2  dofor  k:=1  to  n3  dot:=t+1ododod)=1+(1=1n(1=1n2(1=1n31)))=1+(1=1n(1=1n2n3))=1+(1=1nn2n3)=1+(nn2n3)=1+n6\begin{aligned} &t := 0 \\ &\for \; i := 1 \; \too \; n \; \do \\ &\quad \for \; j := 1 \; \too \; n^2 \; \do \\ &\quad\quad \for \; k := 1 \; \too \; n^3 \; \do \\ &\quad\quad\quad t := t + 1 \\ &\quad\quad \od \\ &\quad \od \\ &\od \\ &\; \\ &\textnormal{ops}(t := 0) + \textnormal{ops}( \\ &\for \; i := 1 \; \too \; n \; \do \\ &\quad \for \; j := 1 \; \too \; n^2 \; \do \\ &\quad\quad \for \; k := 1 \; \too \; n^3 \; \do \\ &\quad\quad\quad t := t + 1 \\ &\quad\quad \od \\ &\quad \od \\ &\od \\ &) \\ &= 1 + (\sum_{1=1}^{n} ( \sum_{1=1}^{n^2} ( \sum_{1=1}^{n^3} 1))) \\ &= 1 + (\sum_{1=1}^{n} ( \sum_{1=1}^{n^2} n^3 )) \\ &= 1 + (\sum_{1=1}^{n} n^2 \cdot n^3) \\ &= 1 + (n \cdot n^2 \cdot n^3) \\ &= 1 + \underline{n^6} \end{aligned}

2.

Calcular el número de asignaciones de la variable tt en el siguiente algoritmo:

t:=0for  i:=1  to  n  dofor  j:=1  to  i  dofor  k:=1  to  n3  dot:=t+1ododod  ops(t:=0)+ops(for  i:=1  to  n  dofor  j:=1  to  i  dofor  k:=j  to  j+3  dot:=t+1ododod)=1+(i=1n(j=1i(k=jj+31)))=1+(i=1n(j=1i4))=1+(i=1ni4)=1+(4i=1ni)=1+(4n(n+1)2)=1+2(n2+n)=1+2n2+2n\begin{aligned} &t := 0 \\ &\for \; i := 1 \; \too \; n \; \do \\ &\quad \for \; j := 1 \; \too \; i \; \do \\ &\quad\quad \for \; k := 1 \; \too \; n^3 \; \do \\ &\quad\quad\quad t := t + 1 \\ &\quad\quad \od \\ &\quad \od \\ &\od \\ &\; \\ &\textnormal{ops}(t := 0) + \textnormal{ops}( \\ &\for \; i := 1 \; \too \; n \; \do \\ &\quad \for \; j := 1 \; \too \; i \; \do \\ &\quad\quad \for \; k := j \; \too \; j+3 \; \do \\ &\quad\quad\quad t := t + 1 \\ &\quad\quad \od \\ &\quad \od \\ &\od \\ &) \\ &= 1 + (\sum_{i=1}^{n} ( \sum_{j=1}^{i} ( \sum_{k=j}^{j+3} 1))) \\ &= 1 + (\sum_{i=1}^{n} ( \sum_{j=1}^{i} 4 )) \\ &= 1 + (\sum_{i=1}^{n} i \cdot 4) \\ &= 1 + (4 \cdot \sum_{i=1}^{n} i ) \\ &= 1 + (4 \cdot \frac{n \cdot (n + 1)}{2}) \\ &= 1 + 2(n^2 + n) \\ &= 1 + \underline{2n^2 + 2n} \end{aligned}

3.

Calcular el orden del número de asignaciones a la variable tt del siguiente algoritmo:

t:=0while  t<n  dot:=t2od\begin{aligned} &t := 0 \\ &\while \; t < n \; \do \\ &\quad \quad t := t * 2 \\ &\od \end{aligned}

Podemos probar distintos valores de nn y observar la relación en la que las asignaciones crecen conforme nn (dato de entrada) aumenta.


nnops\textnormal{ops}
1111
2222
3333
4444
5544
6644
7744
8844
9955
10101010

El orden es 2log(n)\approx 2 \log (n)


4.

Calcular el orden del número de asignaciones a la variable tt del siguiente algoritmo:

for  i:=1  to  n  dot:=iwhile  t>0  dot:=t  div  2odod\begin{aligned} &\for \; i := 1 \; \too \; n \; \do \\ &\quad t := i \\ &\quad \while \; t > 0 \; \do \\ &\quad \quad t := t \; \textnormal{div} \; 2 \\ &\quad \od \\ &\od \end{aligned}

Siguiendo la lógica del ejercicio anterior, probamos valores de nn y observamos el crecimiento:


nnops\textnormal{ops}
1122
2255
3388
441212
551616
662020

El orden es n2\approx n^2

Ordenación por selección (Selection Sort)

Este algoritmo consiste en seleccionar el menor elemento de un arreglo e intercambiarlo por el que está en la primera posición. Luego el menor elemento de los siguientes a la primera posición va en la segunda posición, y asi sucesivamente.

Veamos como aplicar este algoritmo en un arreglo:


recta

El arreglo aa es una permutación del original. A partir del segmento a[1,i)a[1, i) los elementos menores del arreglo están ordenados (invariante del ciclo).

Si quisieramos escribir este algoritmo en pseudocódigo, primero podemos escribir un procedimiento que recorra el arreglo, llamando una función que nos devuelva la posición del menor elemento a partir de una posición dada. Luego, intercambiamos el elemento de la posición actual con el menor elemento encontrado con un procedimiento.

{  n0a=A  }proc  selection_sort(in/out  a:array[1..n]  of  T)var  i,  minp:  nati:=1{    Invariante    }while  i<n  dominp:=min_pos_from(a,i)swap(a,i,minp)i:=i+1odend  proc{  a  estaˊ ordenado y es permutacioˊn de  A  }\begin{aligned} &\{ \; n \geq 0 \land a = A \; \} \\ &\proc \; selection\_sort(\inout \; a : \array [1..n] \; \of \; \bft) \\ &\quad \var \; i, \; minp: \; \nat \\ &\quad i := 1 \quad\quad\quad\quad\quad\quad \{- \;\; \textnormal{Invariante} \;\; -\} \\ &\quad \while \; i < n \; \do \\ &\quad \quad minp := min\_pos\_from (a,i) \\ &\quad \quad swap(a, i, minp) \\ &\quad \quad i := i+1 \\ &\quad \od \\ &\bfend \; \proc \\ &\{ \; a \; \textnormal{está ordenado y es permutación de} \; A \; \} \\ \end{aligned}

El swapswap sería:

{  a=A1i,jn  }proc  swap(in/out  a:array[1..n]  of  T,  in  i,j:nat)var  tmp:Ttmp:=a[i]a[i]:=a[j]a[j]:=tmpend  proc{  a[i]=A[j]a[j]=A[i]kchar"338{i,j}    a[k]=A[k]  }\begin{aligned} &\{ \; a = A \land 1 \leq i, j \leq n \; \} \\ &\proc \; swap(\inout \; a : \array [1..n] \; \of \; \bft, \; \bfin \; i, j : \nat) \\ &\quad \var \; tmp : \bft \\ &\quad tmp := a[i] \\ &\quad a[i] := a[j] \\ &\quad a[j] := tmp \\ &\bfend \; \proc \\ &\{\; a[i] = A[j] \land a[j] = A[i] \land \forall k \not\in \{ i, j \} \implies a[k]=A[k] \; \} \\ \end{aligned}

Para hacer min_pos_frommin\_pos\_from, podemos seguir la siguiente lógica:


recta

El invariante es igual al anterior, pero ahora incluimos el mínimo del segmento a[i,j)a[i, j) en la posición minpminp.

{  0<in  }fun  min_pos_from(a:array[1..n]  of  T,  i:nat)  ret  minp:  natvar  j:natminp:=ij:=i+1{    Invariante:   a[minp]  es el mıˊnimo de  a[i,j]    }while  jn  doif  a[j]<a[minp]  thenminp:=jfij:=j+1odend  fun{  a[minp]  es el mıˊnimo de  a[i,n]  }\begin{aligned} &\{ \; 0 < i \leq n \; \} \\ &\fun \; min\_pos\_from(a : \array [1..n] \; \of \; \bft, \; i : \nat) \; \ret \; minp: \; \nat \\ &\quad \var \; j : \nat \\ &\quad minp := i \\ &\quad j := i+1 \quad\quad\quad\quad\quad\quad \{- \;\; \textnormal{Invariante: } \; a[minp] \; \textnormal{es el mínimo de} \; a[i,j] \;\; -\} \\ &\quad \while \; j \leq n \; \do \\ &\quad \quad \if \; a[j] < a[minp] \; \then \\ &\quad \quad \quad minp := j \\ &\quad \quad \fi \\ &\quad \quad j := j+1 \\ &\quad \od \\ &\bfend \; \fun \\ &\{ \; a[minp] \; \textnormal{es el mínimo de} \; a[i,n] \; \} \\ \end{aligned}

Una manera de hacer lo mismo y con menos código es usando for\for:

proc  selection_sort(in/out  a:array[1..n]  of  T)for  i:=1  to  n1  dominp:=min_pos_from(a,i)swap(a,i,minp)odend  procfun  min_pos_from(a:array[1..n]  of  T,  i:nat)  ret  minp:  natminp:=ifor  j:=i+1  to  n  doif  a[j]<a[minp]  thenminp:=jfiodend  fun\begin{aligned} &\proc \; selection\_sort(\inout \; a : \array [1..n] \; \of \; \bft) \\ &\quad \for \; i := 1 \; \too \; n - 1 \; \do \\ &\quad \quad minp := min\_pos\_from(a,i) \\ &\quad \quad swap(a, i, minp) \\ &\quad \od \\ &\bfend \; \proc \\ &&\\ &\fun \; min\_pos\_from(a : \array [1..n] \; \of \; \bft, \; i : \nat) \; \ret \; minp: \; \nat \\ &\quad minp := i \\ &\quad \for \; j := i+1 \; \too \; n \; \do \\ &\quad \quad \if \; a[j] < a[minp] \; \then \\ &\quad \quad \quad minp := j \\ &\quad \quad \fi \\ &\quad \od \\ &\bfend \; \fun \\ \end{aligned}

De esta forma, las variables que sirven de índices estan declaradas en el contexto/scope de for\for


Ejercicios resueltos - Ordenación por selección

1.

Ordenar el siguiente arreglo [7,1,10,3,4,9,5][7, 1, 10, 3, 4, 9, 5] usando el algoritmo de ordenación por selección, mostrar en cada paso de iteración el elemento seleccionado y como queda el arreglo luego de cada intercambio.

[7,1,10,3,4,9,5]{ pos. actual =1,minp=2}[1,7,10,3,4,9,5]{ pos. actual =2,minp=4}[1,3,10,7,4,9,5]{ pos. actual =3,minp=5}[1,3,4,7,10,9,5]{ pos. actual =4,minp=7}[1,3,4,5,10,9,7]{ pos. actual =5,minp=7}[1,3,4,5,7,9,10]{ pos. actual =6,minp=6}{ arreglo ordenado }\begin{array}{ll} [\underline{7}, \underline{1}, 10, 3, 4, 9, 5] \\ \{- \quad \textnormal{ pos. actual } = 1, \quad minp = 2 \quad -\} \\ \\ [1, \underline{7}, 10, \underline{3}, 4, 9, 5] \\ \{- \quad \textnormal{ pos. actual } = 2, \quad minp = 4 \quad -\} \\ \\ [1, 3, \underline{10}, 7, \underline{4}, 9, 5] \\ \{- \quad \textnormal{ pos. actual } = 3, \quad minp = 5 \quad -\} \\ \\ [1, 3, 4, \underline{7}, 10, 9, \underline{5}] \\ \{- \quad \textnormal{ pos. actual } = 4, \quad minp = 7 \quad -\} \\ \\ [1, 3, 4, 5, \underline{10}, 9, \underline{7}] \\ \{- \quad \textnormal{ pos. actual } = 5, \quad minp = 7 \quad -\} \\ \\ [1, 3, 4, 5, 7, \underline{9}, 10] \\ \{- \quad \textnormal{ pos. actual } = 6, \quad minp = 6 \quad -\} \\ \{- \quad \textnormal{ arreglo ordenado } \quad -\} \\ \end{array}

2.

Ordenar el siguiente arreglo [1,2,3,4,5][1, 2, 3, 4, 5] usando el algoritmo de ordenación por selección, mostrar en cada paso de iteración el elemento seleccionado y como queda el arreglo luego de cada intercambio.

[1,2,3,4,5]{ pos. actual =1,minp=1}[1,2,3,4,5]{ pos. actual =2,minp=2}[1,2,3,4,5]{ pos. actual =3,minp=3}[1,2,3,4,5]{ pos. actual =4,minp=4}[1,2,3,4,5]{ pos. actual =5,minp=5}{ arreglo ordenado }\begin{array}{ll} [\underline{1}, 2, 3, 4, 5] \\ \{- \quad \textnormal{ pos. actual } = 1, \quad minp = 1 \quad -\} \\ \\ [1, \underline{2}, 3, 4, 5] \\ \{- \quad \textnormal{ pos. actual } = 2, \quad minp = 2 \quad -\} \\ \\ [1, 2, \underline{3}, 4, 5] \\ \{- \quad \textnormal{ pos. actual } = 3, \quad minp = 3 \quad -\} \\ \\ [1, 2, 3, \underline{4}, 5] \\ \{- \quad \textnormal{ pos. actual } = 4, \quad minp = 4 \quad -\} \\ \\ [1, 2, 3, 4, \underline{5}] \\ \{- \quad \textnormal{ pos. actual } = 5, \quad minp = 5 \quad -\} \\ \{- \quad \textnormal{ arreglo ordenado } \quad -\} \\ \end{array}

Ordenación por inserción (Insertion Sort)

Este algoritmo consiste en insertar un elemento en la posición correcta de un arreglo ordenado. Se comprueba si el elemento es menor al anterior, y si lo es, se intercambian.

Veamos como aplicar este algoritmo en un arreglo:


recta

El arreglo aa es una permutación del original. Un segmento inicial a[1,i)]a[1,i)] del arreglo está ordenado, en general, a[1,i)a[1,i) no contiene los mínimos del arreglo (invariante del ciclo).

Si quisieramos escribir este algoritmo en pseudocódigo, podemos escribir un procedimiento que recorra el arreglo, utilizando un procedimiento que se encargue de insertar un elemento en la posición correcta.

{  n0a=A  }proc  insertion_sort(in/out  a:array[1..n]  of  T)for  i:=2  to  n  doinsert(a,i)odend  proc{  a  estaˊ ordenado y es permutacioˊn de  A  }\begin{aligned} &\{ \; n \geq 0 \land a = A \; \} \\ &\proc \; insertion\_sort(\inout \; a : \array [1..n] \; \of \; \bft) \\ &\quad \for \; i := 2 \; \too \; n \; \do \\ &\quad \quad insert(a, i) \\ &\quad \od \\ &\bfend \; \proc \\ &\{ \; a \; \textnormal{está ordenado y es permutación de} \; A \; \} \\ \end{aligned}

Para hacer insertinsert, podemos seguir la siguiente lógica:


recta

Como invariante, tenemos que aa es una permutación de AA, el segmento a[1,i]a[1,i] sin celda jj está ordenado y, a[j,i]a[j,i] también está ordenado.

{  0<ina=A  }proc  insert(in/out  a:array[1..n]  of  T,  in  i:nat)var  j:natj:=i{    Invariante mencionado    }while  j>1    a[j]<a[j1]  doswap(a,j1,j)j:=j1odend  proc{  a[1,i]  estaˊ ordenado y es permutacioˊn de  A  }\begin{aligned} &\{ \; 0 < i \leq n \land a = A \; \} \\ &\proc \; insert(\inout \; a : \array [1..n] \; \of \; \bft, \; \bfin \; i : \nat) \\ &\quad \var \; j : \nat \\ &\quad j := i \quad\quad\quad\quad\quad\quad \{- \;\; \textnormal{Invariante mencionado} \;\; -\} \\ &\quad \while \; j > 1 \; \land \; a[j] < a[j-1] \; \do \\ &\quad \quad swap(a, j-1, j) \\ &\quad \quad j := j-1 \\ &\quad \od \\ &\bfend \; \proc \\ &\{ \; a[1,i] \; \textnormal{está ordenado y es permutación de} \; A \; \} \\ \end{aligned}

(Se utiliza el mismo swapswap que en el algoritmo de selección). Tanto este algoritmo como el de selección tienen complejidad cuadrática O(n2)\bigO(n^2) (en el peor caso), ya que sería necesario recorrer el arreglo completo en cada iteración.


Ejercicios resueltos - Ordenación por inserción

Ordenar el siguiente arreglo [7,1,10,3,4,9,5][7, 1, 10, 3, 4, 9, 5] usando el algoritmo de ordenación por inserción, mostrar en cada paso de iteración el elemento seleccionado y como queda el arreglo luego de cada intercambio.

[7,1,10,3,4,9,5]{1<7, se intercambian }[1,7,10,3,4,9,5]{10char"338<7, siguiente iteracioˊ}[1,7,10,3,4,9,5]{3<10, se intercambian }[1,7,3,10,4,9,5]{3<7, se intercambian }[1,3,7,10,4,9,5]{3char"338<1, siguiente iteracioˊ}[1,3,7,4,10,9,5]{4<7, se intercambian }[1,3,4,7,10,9,5]{4char"338<3, siguiente iteracioˊ}[1,3,4,7,9,10,5]{9char"338<7, siguiente iteracioˊ}[1,3,4,7,9,10,5]{10char"338<9, siguiente iteracioˊ}[1,3,4,7,9,10,5]{5<10, se intercambian }[1,3,4,7,9,5,10]{5<9, se intercambian }[1,3,4,7,5,9,10]{5<7, se intercambian }[1,3,4,5,7,9,10]{5char"338<4, se recorrioˊ todo el arreglo }{ arreglo ordenado }\begin{array}{ll} [\underline{7}, \underline{1}, 10, 3, 4, 9, 5] \\ \{- \quad 1 < 7, \quad \textnormal{ se intercambian } \quad -\} \\ \\ [1, \underline{7}, \underline{10}, 3, 4, 9, 5] \\ \{- \quad 10 \not< 7, \quad \textnormal{ siguiente iteración } \quad -\} \\ \\ [1, 7, \underline{10}, \underline{3}, 4, 9, 5] \\ \{- \quad 3 < 10, \quad \textnormal{ se intercambian } \quad -\} \\ \\ [1, \underline{7}, \underline{3}, 10, 4, 9, 5] \\ \{- \quad 3 < 7, \quad \textnormal{ se intercambian } \quad -\} \\ \\ [\underline{1}, \underline{3}, 7, 10, 4, 9, 5] \\ \{- \quad 3 \not< 1, \quad \textnormal{ siguiente iteración } \quad -\} \\ \\ [1, 3, \underline{7}, \underline{4}, 10, 9, 5] \\ \{- \quad 4 < 7, \quad \textnormal{ se intercambian } \quad -\} \\ \\ [1, \underline{3}, \underline{4}, 7, 10, 9, 5] \\ \{- \quad 4 \not< 3, \quad \textnormal{ siguiente iteración } \quad -\} \\ \\ [1, 3, 4, \underline{7}, \underline{9}, 10, 5] \\ \{- \quad 9 \not< 7, \quad \textnormal{ siguiente iteración } \quad -\} \\ \\ [1, 3, 4, 7, \underline{9}, \underline{10}, 5] \\ \{- \quad 10 \not< 9, \quad \textnormal{ siguiente iteración } \quad -\} \\ \\ [1, 3, 4, 7, 9, \underline{10}, \underline{5}] \\ \{- \quad 5 < 10, \quad \textnormal{ se intercambian } \quad -\} \\ \\ [1, 3, 4, 7, \underline{9}, \underline{5}, 10] \\ \{- \quad 5 < 9, \quad \textnormal{ se intercambian } \quad -\} \\ \\ [1, 3, 4, \underline{7}, \underline{5}, 9, 10] \\ \{- \quad 5 < 7, \quad \textnormal{ se intercambian } \quad -\} \\ \\ [1, 3, \underline{4}, \underline{5}, 7, 9, 10] \\ \{- \quad 5 \not< 4, \quad \textnormal{ se recorrió todo el arreglo } \quad -\} \\ \{- \quad \textnormal{ arreglo ordenado } \quad -\} \\ \end{array}

2.

Ordenar el siguiente arreglo [1,2,3,4,5][1, 2, 3, 4, 5] usando el algoritmo de ordenación por selección, mostrar en cada paso de iteración el elemento seleccionado y como queda el arreglo luego de cada intercambio.

[1,2,3,4,5]{2char"338<1, siguiente iteracioˊ}[1,2,3,4,5]{3char"338<2, siguiente iteracioˊ}[1,2,3,4,5]{4char"338<3, siguiente iteracioˊ}[1,2,3,4,5]{5char"338<4, se recorrioˊ todo el arreglo }{ arreglo ordenado }\begin{array}{ll} [\underline{1}, \underline{2}, 3, 4, 5] \\ \{- \quad 2 \not< 1, \quad \textnormal{ siguiente iteración } \quad -\} \\ \\ [1, \underline{2}, \underline{3}, 4, 5] \\ \{- \quad 3 \not< 2, \quad \textnormal{ siguiente iteración } \quad -\} \\ \\ [1, 2, \underline{3}, \underline{4}, 5] \\ \{- \quad 4 \not< 3, \quad \textnormal{ siguiente iteración } \quad -\} \\ \\ [1, 2, 3, \underline{4}, \underline{5}] \\ \{- \quad 5 \not< 4, \quad \textnormal{ se recorrió todo el arreglo } \quad -\} \\ \{- \quad \textnormal{ arreglo ordenado } \quad -\} \\ \end{array}