# [!java|scala]Arrays[/!][!python]Lists[/!] e nós

O objetivo deste exercício é reproduzir o padrão da primeira linha nas outras linhas com um deslocamento de uma célula (veja a guia Objetivo para detalhes). A maior diferença entre este exercício e os outros sobre padrões é que tem que ler o padrão (na primeira linha) antes de reproduzí-lo. Não pode fazer de outro jeito por que o mesmo código será executado em três mundos diferentes, cada um com um próprio padrão.

Uma solução é ler a próxima célula e copiá-la à posição antes de voltar para ler a segunda célula. Mas já que é proibido usar os métodos de teletransporte de buggle para uma posição específica (`setPos()` e similares), esta abordagem seria muito difícil de implementar.

O mais simples é armazenar a sequência de cores que constituem o padrão inteiro numa [!java|scala]array[/!][!python]list[/!]. Mas antes de fazer isto, devemos aprender um pouco sobre o que [!java|scala]arrays[/!][!python]lists[/!] são.

## [!java|scala]Arrays[/!][!python]List[/!]

[!java|scala]Uma array[/!][!python]Uma list[/!] é uma sequência ordenada de variáveis que ficam juntas. é similar a uma estante onde em cada prateleira se coloca um valor separado. Cada variável da sequência é identificada pela posição dela e pode armazenar um valor específico. [!java|scala]todas as células da array devem armazenar valores do mesmo tipo por que arrays são homogêneas em [!thelang]. É possível burlar esta restrição a usar tipos de dados `[!java]Object[/!][!scala]Any[/!]` que contenham [!java]praticamente[/!] qualquer outro tipo de dados. [!java]Tipos primitivos como aqueles que vimos anteriormente (int, boolean, double, char, etc) não podem ser armazenados numa variável Object, mas suas contrapartidas objetificadas (Integer, Boolean, Double, Char, Boolean, etc) podem.[/!] Entretanto, é boa prática fazer o tipo de uma array o mais específico possível, p.ex., se planea armazenar alguns inteiros na sua array, faça dela uma array de inteiros, não de [!java]Object[/!][!scala]Any[/!].[/!] [!python]Lists podematé mesmo misturar valores de diferentes tipos, como valores inteiros em algumas células e cores em outras células.[/!]

T é o nome da [!java|scala]array[/!][!python]list[/!], [!java|python]T[0][/!][!scala]T(0)[/!] é o nome da primeira célula, [!java|python]T[1][/!][!scala]T(1)[/!] é o nome da segunda célula, [!java|python]T[2][/!][!scala]T(2)[/!] da terceira e etc. E sim, a primeira célula é numerada [!java|python]T[0][/!][!scala]T(0)[/!] e a última de uma [!java|scala]array[/!][!python]list[/!] de tamanho N é [!java|python]T[N-1][/!][!scala]T(N-1)[/!]. Pode parecer estranho contar a partir de 0 e não de 1 como normalmente, mas por motivos históricos isto agora é inevitável.

### Uso básico

Podemos usar uma variável inteira i para acessar com [!java|python]T[i][/!][!scala]T(i)[/!] as células: quando o valor de i é 0, [!java|python]T[i][/!][!scala]T(i)[/!] acessa [!java|python]T[0][/!][!scala]T(0)[/!]; quando o valor de i é 10, [!java|python]T[i][/!][!scala]T(i)[/!] acessa [!java|python]T[10][/!][!scala]T(10)[/!]. Sizemos que i é o índice em T. `[!java|python]T[i][/!][!scala]T(i)[/!]` pode ser usada simplesmente como qualquer variável. Podemos configurar um novo valor:

    [!java|python]T[i][/!][!scala]T(i)[/!] = 78[!java];[/!]

Podemos recuperar e usar valor dele:

    x = [!java|python]T[i][/!][!scala]T(i)[/!][!java];[/!]

Podemos testar este valor:

    if ([!java|python]T[i][/!][!scala]T(i)[/!] > 0) [!scala|java]{[/!][!python]:[/!]
        [!java|scala]//[/!][!python]#[/!] instruções...
    [!java|scala]}[/!]

É muito fácil percorrer toda a [!scala|java]array[/!][!python]list[/!], por exemplo para iniciar as células.

    [!java]for (int i = 0; i<T.length; i++) {[/!][!python]for i in range(len(T)):[/!][!scala]for (i <- 0 to T.length-1) {[/!]
       [!java|python]T[i][/!][!scala]T(i)[/!] = 3[!java];[/!]
    [!java|scala]}[/!]

[!java|scala]A notação `T.length` recupera o comprimento (length) da array T,[/!] [!python]A função `len()` recupera o comprimento da lista T,[/!] a permitir que se construa um loop clássico facilmente. [!python]Na verdade, a função `len()` é muito mais genérica e pode ser usada para recuperar o comprimento de muitos objetos. Aplicada numa cadeia, por exemplo, ela retorna a quantidade de caracteres na cadeia.[/!] [!scala]Não se esqueça de começar em `0` e terminar em `T.length-1` ao invés de ir de `1` até `T.length`.[/!]

Se quer simplesmente iterar nos valores de T sem controlar o índice, pode simplesmente escrever:

    [!java]for (int i: T) {[/!][!scala]for (i <- T) {[/!][!python]for i in T:[/!]
      ação()[!java];[/!]
    [!java|scala]}[/!]

[!java]Esta construção é chamada um loop extendido em Java. A variável i assume todos os valores do conjunto localizado a direita do dois-pontos (:), um depois do outro.[/!] [!python|scala]Isto é na verdade muito similar à construção anterior. Simplesmente, `[!python]range(n)[/!][!scala]i to j[/!]` retorna um conjunto de inteiros sobre os quais o loop for itera. Na verdade, [!thelang] oferece formas muito mais elegantes de percorrer [!python]lists[/!][!scala]arrays[/!] e outras coleções de dados, mas isto fica para um conjunto específico de exercícios (que ainda será escrito no PLM).[/!]

### Declarar uma [!python]list[/!][!java|scala]array[/!]

[!python]

Se sabe antecipadamente o conteúdo da sua lista, pode atribuir os valores todos juntos. Ponha eles simplesmente entre colchetes e separados por vírgulas como segue:

    L = [1, 3, 5, 7, 9]
    # L agora é uma array de 5 valores, todos eles inteiros

Por outro lado, provavelmente vai criar uma lista vazia e depois anexar-la os valores separadamente:

    L2 = []
    # neste momento, L2 é uma lista vazia
    L2.append(1)
    L2.append(3)
    L2.append(5)
    L2.append(7)
    L2.append(9)
    # E agora o seu conteúdo é igual ao de L, vista antes

[/!] [!java|scala]

Para declarar uma variável chamada T que pode guardar uma array de inteiros, deve escrever:

    [!java]int[] T;[/!][!scala]var T:Array[Int][/!]

[!java]`int` significa que os elementos da array são do tipo inteiro; `[]` significa que estamos a falar de uma array e `T` é o nome da variável. Por motivos históricos, também pode ser escrito como `int T[]` (com o [] depois do nome da variável), mas como assim é menos legível, é melhor evitar esta forma.[/!] [!scala]A notação `[Int]` especializa o tipo Array (que é genérico), a especificar que cada célula desta array é um inteiro. Um array de booleanos deve ser escrito simplesmente como `Array[Boolean]`.[/!]

### Alocar uma array

Declarar uma variável `T` que armazena uma array apenas reserva o nome `T` para uso futuro, mas não reserva a área de memória para armazenar as células. A array ainda não está inicializada: ela não tem qualquer valor. O que significa `[!java]T[4][/!][!scala]T(4)[/!]` se ainda não dissemos que a array tem 5 células?

Primeiramente, temos que dar um valor a `T`:

    [!java]T = new int[10];[/!][!scala]var T = new Array[Int](10)[/!]

`new` (novo) significa que queremos criar algo e `[!java]int[10][/!][!scala]Array[Int](10)[/!]` significa que é uma array de 10 valores inteiros. Como resultado, uma array de 10 células para valores inteiros é criada na memória e a variável `T` faz referência a esta array.

O tamanho de uma array é fixo e não pode ser mudado depois da criação da array. O tamanho de uma array `T` pode ser recuperado ao se consultar a variável `T.length`.

Ao alocar pode especificar o tamanho com uma variável: `[!java]int[] T = new int[i];[/!][!scala]var T = new Array[Int](i);[/!]` Neste caso, o tamanho da array será ajustado para o valor de `i` quando `new` for chamado. O tamanho da array ainda não pode ser modificado: mesmo se a variável `i` mudar depois disto, o tamanho permanece o do valor dado no momento da alocação. [!java]Além disto, é proibido escrever algo como `int T[10];` no momento de declarar a variável. Deve usar a instrução `new` para alocar o array, como em `int[] T = new int[10];` [/!]

#### Declaração e inicialização

Se sabe previamente o conteúdo da sua array, pode declarar, alocar e inicializar-la toda de uma vez:

    [!java]int[] T = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };[/!][!scala]var T = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)[/!]

Para saber o tamanho da array para alocar, o compilador conta os valores dados. Este código é equivalente a:

    [!java]int[] T = new int[10];
    T[0] = 1;
    T[1] = 2;
    ...
    T[9] = 10;[/!][!scala]var T = new Array[Int](10);
    T(0) = 1
    T(1) = 2
    ...
    T(9) = 10[/!]

também é equivalente a:

    [!java]int[] T = new int[10];
    for (int i=0; i<T.length; i++) {
      T[i] = i+1;
    }[/!][!scala]var T = new Array[Int](10);
    for (i <- 0 to T.length-1) {
      T(i) = i+1
    }[/!]

[/!]

### [!python]Lists[/!][!scala|java]Arrays[/!] e parâmetros de métodos

Não há nenhum problema em passar uma [!python]list[/!][!java|scala]array[/!] para um método como parâmetro. Este método pode então usar este parâmetro como se fosse definido localmente:

    [!java]boolean has42First(int[] array) {
        return array[0] == 42;
    }[/!][!python]def has42First(list):
      return list[0] == 42[/!][!scala]def has42First(array:Array[Int]):Boolean = {
      return array(0) == 42
    }[/!]

No lado de quem invoca também é bastante simples:

    [!java]int[] tab = new int[10];[/!][!scala]var tab = new Array[Int] (10)[/!][!python]tab = [1, 3, 5, 7, 9][/!]
    [!java|scala]// inicialização de valores omitida
    [/!]if (has42First(tab))[!java|scala] {[/!][!python]:[/!]
       [!java|scala]//[/!][!python]#[/!] faz algo
    [!java|scala]}[/!]

[!java]

Se quer alocar e inicializar o array de uma vez só, é um pouco mais complicado pois o compilador terá que saber o tipo do parâmetro queestá a criar. Para isto, use a seguinte construção (feia):

    if (has42First(   new int[] {1, 3, 5, 7, 9}   ) {
       // faz algo
    }

[/!]

Métodos também podem retornar [!java|scala]arrays[/!][!python]lists[/!] como resultado sem nenhuma complicação. Aqui está um método que retorna uma [!java|scala]array[/!][!python]list[/!] do tamanho pedido, preenchido com 42s.

    [!java]int[] fill42(int size) {
        int[] res = new int[size];
        for (int i=0; i<size; i++)
            res[i] = 42;
        return res;
    }[/!][!scala]def fill42(size:Int):Array[Int] = {
        var res = new Array[int] (size)
        for (i <- 0 to size -1) {
            res(i) = 42;
        }
        return res;
    }[/!][!python]def fill42(size):
        res = []
        for i in range(size):
            res.append(42)
        return res[/!]

## Objetivo deste exercício

Finalmente! Depois desta longa explicação, podemos voltar ao exercício.

A sua missão é bastante simples, na verdade. O seu código deve guardar o padrão de cores observado na primeira linha numa [!java|scala]array[/!][!python]list[/!]. [!python]O mais fácil é criar uma lista vazia e depois usar `append()`para adicionar as cores uma por uma à medida que for a ler elas (com `getGroundColor()`).[/!] [!java|scala]Para isto, deve declarar e alocar uma array de `Cor`. Mas atencção, existem vários mundos, de diferentes tamanhos; use `getWorldHeight()` para recuperar o tamanho do mundo atual. Uma que a array esteja alocada, preencha ela a ler a cor do chão em cada um dos pontos (com `getGroundColor()`).[/!]

Uma vez que conseguiu ler e gravar o padrão na primeira linha, tem que reaplicar o padrão nas outras linhas, por exemplo a executar `getWorldHeight()` vezes um método escrito especificamente para isto.