11  Entrada de dados e o começo de listas

Nessa aula, temos dois tópicos principais, como fazer a entrada de dados, através de comandos de entrada e com argumentos na linha de comando. Além disso também veremos como tratar de um tipo especial de variável, onde é possível, guardar mais de um valor.

11.1 O comando input

Quando queremos inserir dados, em Julia, basta colocar dados. Mas, como podemos fazer para entrar dados em um programa comum?

Para isso temos o comando readline(), que interrompe a execução do programa e espera pela entrada de uma String, o que ocorre quando a tecla “enter” é pressionada.

println("Digite o seu nome")
resposta = readline()
println("O seu nome é: ", resposta)

Caso, ao rodar o programa, você digitar Maria, e pressionar a tecla enter, a resposta final do seu programa será O seu nome é: Maria.

Como o readline() lê Strings, se quisermos ler números, é necessário usar o comando parse. O comando parse de forma simples possui dois parâmetros, o primeiro corresponde ao tipo que se quer transformar, e o segundo o valor original.

println("Digite um inteiro")
valor = parse(Int64, readline())
println("O numero digitado foi ", valor)

Sabendo ler números do teclado, vamos a um exercício simples, ler uma sequência de números inteiros terminada por zero e devolver a sua soma.

function somaVarios()
    soma = 0.0
    println("Digite um número")
    n = parse(Float64, readline())
    while  n!=0
        soma = soma + n
        println("Digite um número")
        n = parse(Float64, readline())
    end
    println("A soma é: ", soma)
end

Observe o seguinte exemplo que calcula os quadrados dos números de uma lista terminada por zero.

function leQ()
  x = readline()
  n = parse(Float64, x)
  while n != 0
    println("$n ao quadrado é ", n * n)
    x = readline()
    n = parse(Float64, x)
  end
end

Notem que o readline também pode receber uma variável de arquivo para que dados sejam lidos diretamente. Mas, nesse caso temos que tomar Ocuidado para abrir (open()) e fechar (close()) o arquivo. Como abaixo:

function leQ()
    println("Digite um número")
    f = open("numeros.txt", "r+")
    x = readline(f)
    n = parse(Float64, x)
    while n != 0
        println("$n ao quadrado é ", n * n)
        println("Digite outro número")
        x = readline(f)
        n = parse(Float64, x)
    end
    close(f)
end

11.2 Lendo através da linha de comando

A outra forma de ler comandos é através da constante ARGS que é preparada na chamada de um programa. Para entender melhor isso, vamos ver o seguinte programa.

println(ARGS)

Se a linha acima está no arquivo args.jl, ao chamar julia args.jl com diversos parâmetros, teremos diversos resultados diferentes.

Por exemplo ao chamar:

julia args.jl 1 2 3 abc

Teremos como resposta

["1", "2", "3", "abc"]

Vamos analisar um pouco melhor essa resposta observando que cada parâmetro está em uma posição.

tam = length(ARGS)
println("O tamanho dos argumentos é: ", tam)
for i in 1:tam
    println(ARGS[i])
end

Olhando o código acima, podemos ver que a função length() devolve o número de argumentos, ou seja, o tamanho da lista ARGS. Além disso com os colchetes é possível acessar a cada posição da lista de forma individual.

O exemplo abaixo soma os parâmetros inteiros dados como argumentos. Ele também ilustra uma boa prática que é, sempre colocar o código em módulos, no caso abaixo em funções:

function SomaEntrada()
    tam = length(ARGS)
    s = 0
    i = 1
    while i <= tam
        valor = parse(Int, ARGS[i])
        println(valor)
        s = s + valor
        i = i + 1
    end
    println("A soma foi: ", s)
end
SomaEntrada()

A flexibilidade que temos ao usar listas é enorme! Por isso, listas ou vetores, merecem um tópico próprio.

11.3 Listas

Vamos primeiro brincar um pouco no console.

vetor = [1, 2, 3]
println(vetor[1])
println(length(vetor))
vetor[2] = vetor[2] + 1
vetor[1] = 2 * vetor[3]
println(vetor)
1
3
[6, 3, 3]

Como disse antes, o for foi feito para manipular vetores, vamos ver umas funções, a primeira que imprime os elementos de um vetor um por linha.

function imprimeVetor(v)
    for el in v
        println(el)
    end
end

Isso também pode ser feito por meio dos índices do vetor:

function imprimeVetor(v)
    for i in 1:lenght(v)
        println(v[i])
    end
end

Como cada posição é independente, podemos calcular a soma dos elementos ímpares de um vetor

function somaImpVetor(v)
    soma = 0
    for i in 1:length(v)
        if v[i] % 2 == 1
            soma = soma + v[i]
        end
    end
    return soma
end

Também vimos em aula alguns outros exemplos, como calcular a média dos elementos em um vetor.

function mediaV(v)
   soma = 0.0
   for i in v
      soma = soma + i
   end
   return soma / length(v)
end

Devolver a soma dos elementos ímpares de um vetor

function somaImpar(v)
    soma = 0
    for i in v
        if i % 2 == 1
            soma = soma + i
        end
    end
    return soma
end

Imprimir os números divisíveis por 5 de um vetor.

function imprimeDivisivelPor5(v)
    for i in v
        if i % 5 == 0
            println(i)
        end
    end
end

Com uma pequena variação e usando o comando push!() podemos ver como devolver um vetor com os números divisíveis por 5.

function devolveDivisivelPor5(v)
    x = []  # começa com um vetor vazio
    for i in v
        if i % 5 == 0
            push!(x, i)  # adiciona um elemento ao vetor x
        end
    end
    return x
end

11.3.1 Álgebra linear e Listas

A manipulação de listas é uma parte fundamental da álgebra linear, que estuda vetores e matrizes. Funções como o produto escalar de dois vetores são exemplos clássicos. Abaixo temos dois exemplos de produto escalar de dois vetores. lembrado esse é definido como a soma dos produtos de elementos em posições iguais.

function dotProduct(a, b)
    soma = 0
    if length(a) != length(b)
       return soma   # o produto não está definido se os tamanhos são diferentes
    end
    for i in 1:length(a)
        soma = soma + a[i] * b[i]
    end
    return soma
end

Acima vimos que um caso especial do uso do for, consiste em fazer Ofor varias entre 1 e um tamanho (1:lenght(a))

Observem a diferença na versão abaixo:

function dotProduct(a, b)
    soma = 0
    if length(a) != length(b)
       return soma   # o produto não está definido se os tamanhos são diferentes
    end   
    i = 1
    for x in a
        soma = soma + x * b[i]
        i = i + 1
    end 
    return soma
end

11.3.2 Exercício de permutação

Para terminar, vamos fazer uma função onde dado um vetor de inteiros de tamanho \(n\), verifica se esse vetor é uma permutação dos números de 1 a \(n\). Para isso, veremos se cada número de 1 a \(n\) está no vetor.

Mas, sem esquecer dos testes:

@testset "Verifica Permutação" begin
    @test permuta([1,2,3])
    @test permuta([3, 2, 1])
    @test permuta([1])
    @test permuta([2, 1])
    @test permuta([4, 2, 3, 1])
    @test !permuta([1, 1])
    @test !permuta([1, 3])
    @test permuta([])
end

e o código:

function permuta(v)
   tam = length(v)
   for i in 1:tam
      if  !(i in v)
         return false
      end
   end
   return true
end

Foi usado o comando in de Julia que verifica se um elemento está no vetor.