Estruturas de Dados 2020/2021 (CC1007) - DCC/FCUP

Aula Prática #02 - Input/Output e Mooshak
(semana de 22/02 a 26/02)


Exercícios para submissão

Para efeitos da nota atribuída à resolução de exercícios ao longo do semestre, os exercícios que pode submeter desta aula são:

Prazo de submissão: 13 de Março (submeter no Mooshak de EDados)

É encorajado que vão falando com os docentes e outros colegas se tiverem dificuldades. No entanto, qualquer ajuda mais direta que tenham recebido de outros colegas deve ser reconhecida nos comentário do programa que submetem.
Depois do prazo os problemas continuarão disponíveis no Mooshak, mas as submissões não contarão para a sua nota.
Cada aula vale 10% da nota desta componente. Como existem 12 aulas com submissões, pode ter pontuação máxima mesmo sem ter feito tudo.
Para um problema contar tem acertar todos os testes (ou seja, ter accepted). Mesmo que resolva todos os problemas, o máximo numa aula é de 100%.
Para ter 100% bastará sempre resolver os exercícios do guião principal.


Exercício 1) Introdução à classe Scanner

Use a documentação da classe Scanner como referência quando precisar.

// Importa a classe Scanner, que será usada para leitura de dados
import java.util.Scanner;

public class Sum {
   public static void main(String[] args) {

      // Cria um objecto Scanner para ler da entrada padrão ("standard input")
      Scanner stdin = new Scanner(System.in);

      // Chama o método nextInt() para ir buscar o próximo inteiro
      int a = stdin.nextInt();
      int b = stdin.nextInt();

      // Imprime a soma dos dois números
      System.out.println(a+b);
   }

}

  1. O meu primeiro programa com Scanner.
    Copie este pedaço de código para um ficheiro, compile-o e execute o programa. A execução deverá ficar "parada" à espera que introduza dois números. Escreva 2 3, carregue no enter e verifique que o programa escreve 5 como resultado.
  2. Importação de classes.
    Experimente apagar/comentar a segunda linha do programa com a instrução import e compile de novo o código. O que acontece?
    A classe Scanner faz parte do pacote java.util, que contém toda uma série de classes muito úteis que iremos aos poucos começar a usar.
  3. Espaçamento.
    Experimente executar o programa novamente, mas desta vez escrever 2, carregar no enter, depois escrever 3 e carregar novamente no enter, verificando que o programa continue a funcionar. Isto acontece porque o método nexInt() aceita qualquer tipo de espaçamento entre inteiros (sejam apenas um ou vários espaços, tabs e mudanças de linha).
  4. Erro no tipo de dados. (Input Mismatch)
    Execute novamente o programa mas desta vez dê como input 2.5 3.6. O que acontece? Porquê?
  5. Lendo outro tipo de dados.
    Modifique o programa para que passe a conseguir ler número com casas decimais ao invés de inteiros. Queremos usar doubles em vez de ints. Que método deverá ser chamado no lugar do nextInt()? (espreite a documentação da classe Scanner, com todos os métodos disponíveis). Teste o seu programa para garantir que com 2.5 3.6 como entrada o resultado é 6.1.
    (Nota: se usar um computador configurado para português, pode acontecer que ao tentar ler um número decimal com um ponto receba um "Input Mismatch"; nesse caso é esperado que use uma vírgula no lugar do ponto; não há problema pois quando submeter o seu programa ele irá aceitar na mesma pontos - em todo o caso, se desejar usar pontos também no seu computador pode modificar o Locale de todo o programa ou apenas no Scanner)

Exercício 2) Leitura de strings

import java.util.Scanner;

public class Count {
   public static void main(String[] args) {
	
      Scanner stdin = new Scanner(System.in);
		
      // Ciclo para iterar sobre todas as linhas do input
      int counter = 0;
      while (stdin.hasNextLine()) {
         counter++;
         String s = stdin.nextLine();
         System.out.println(counter + ": " + s);
      }
   }
}

  1. Executando o programa.
    Faça download do ficheiro hamlet.txt contendo alguns versos de Hamlet, uma peça de William Shakespeare. Compile o código de cima e execute-o fornecendo como input o ficheiro hamlet.txt usando redirecionamento de input na shell:
     
    $ java Count < hamlet.txt
    1: To be or not to be that is the question
    2: Whether tis nobler in the mind to suffer
    3: The slings and arrows of outrageous fortune
    4: Or to take arms against a sea of troubles

     
    Note que redirecionar o input é "equivalente" a introduzir manualmente o conteúdo do ficheiro via teclado.
  2. Lendo tokens
    Altere o programa, substituindo a chamada a hasNextLine() por hasNext(), e a chamada a nextLine() por next(). Recompile e execute novamente o código com o mesmo input. O que acontece agora? O que está a ser contado?
    Em Java não existe nenhum "nextString" e o método next deve ser usado para ler pedaços de input (tokens) separados por algum tipo de espaçamento (sejam espaços ou mudanças de linha)

Exercício 3) Usando arrays

import java.util.Scanner;

public class ReadNumbers {

   // Escrever os numeros guardados num array no stdout
   static void writeArray(int v[]) {
      for (int i=0; i<v.length; i++)          
         System.out.println("v[" + i + "] = " + v[i]);      
   }
   
   public static void main(String[] args) {

      Scanner stdin = new Scanner(System.in);

      int v[] = new int[10];     // Cria um novo array com espaço para 10 inteiros           
      int n = stdin.nextInt();   // Ler a quantidade de numeros que se seguem
      
      for (int i=0; i<n; i++)    // Ler os numeros a partir do stdin
         v[i] = stdin.nextInt();
      
      writeArray(v);             // Chamar procedimento que escreve
   }
}
  1. Executando o código.
    Compile e execute este código, redirecionando o input a partir do ficheiro numbers.txt
    $ java ReadNumbers < numbers.txt
  2. Posições do array por preencher.
    Substitua o 10 no início do input por um 5 e execute novamente o programa. O que acontece? Porquê? Note como o atributo length de um array indica o tamanho que foi alocado, e não o número de posições "preenchidas". Note também qual o valor por omissão de um inteiro.
  3. Saindo fora dos limites do array. (ArrayIndexOutOfBoundsException)
    Mude o ficheiro de input para passar a conter 11 números (mude a primeira linha para 11 e acrescente um número no final da segunda linha) e execute novamente o programa. O que acontece? Porquê? Note que ao contrário do C, o Java indica explicitamente quando saimos fora dos limites de um array.
    Modifique o programa para passar a aceitar uma qualquer quantidade de números inteiros (a que for indicada na primeira linha de input) e teste a sua alteração.
  4. Calculando a amplitude.
    Acrescente uma função que recebe um array e devolve um inteiro indicando a amplitude (diferença entre máximo e mínimo) dos valores guardados no array. Teste o seu funcionamento e certifique-se que funciona independentemente da magnitude dos números (podem ser tão pequenos - incluindo números negativos - ou grandes como quiserem, assumindo que cabem num int).

Exercício 4) O meu primeiro problema no Mooshak


Nesta unidade curricular vamos usar o sistema Mooshak para avaliar automaticamente os programas feitos (ver ajuda do Mooshak).

Para aceder ao sistema use o seu login (com "up") e a password que lhe foi enviada para o email institucional (email enviado a 20 Fev com o título "[EDados] Password para o Mooshak - login")
(se tiver problemas em aceder envie uma mensagem no Slack ao docente Pedro Ribeiro)

  1. Resolva e submeta com sucesso o problema [ED183] Estatísticas
    Dicas:

Exercício 5) Mais dois problemas no Mooshak

Para consolidar os conhecimentos destas duas primeiras aulas, submeta os seguintes problemas no Mooshak:


  1. Resolva e submeta com sucesso o problema [ED120] Desenhando um Losango
    Algumas dicas:
    • Este problema é essencialmente igual a algo sugerido na aula anterior;
    • Para o resolver apenas necessita de saber como usar ciclos. Quantos pontos existem na primeira linha? E na segunda? E na terceira? E cardinais?

  2. Resolva e submeta com sucesso o problema [ED121] Palíndromos
    • Para a leitura do input pode usar o que aprendeu exercicio 2 desta aula;
    • Se quiser aceder ao i-ésimo caracter de uma String pode usar o método char charAt(int i), como viu na aula anterior.
    • Primeiro converta a a linha lida numa string só com letras minúsculas (sem espaços e pontuações). Faça para isso uma função que receba uma string e devolva a mesma string com os espaços retirados e todas as maiúsculas convertidas em minúsculas. Para isso é útil conhecer a classe Character, que contém várias funções para lidar com caracteres. Em particular:
      • A função boolean Character.isLetter(char c) indica se o caracter c é uma letra;
      • A função char Character.toLowerCase(char c) converte o caracter para a sua versão minúscula
    • Faça agora uma outra função que recebe uma string e devolve um valor booleano indicando se a string é ou não um palíndromo, sendo que pode aplicar esta função à linha já sem espaços e maiúsculas.

Exercícios extra para consolidação de conhecimentos

Estes exercícios são opcionais e permitem-lhe exercitar os seus conhecimentos de leitura/escrita, de uso de instruções condicionais e de uso de instruções de ciclo. As dicas estão acessíveis se carregar no botão, mas estão "escondidas" para o caso de preferir primeiro tentar fazer sem spoilers.


  1. Resolva e submeta com sucesso o problema [ED243] Pizza



  2. Resolva e submeta com sucesso o problema [ED244] Primos



Exercício de Desafio

Para esta semana o desafio tem a ver com a eficiência algorítmica. Deve tentar resolver o seguinte problema, que está disponível para submissão no Mooshak:

Devem submeter para verificar se a solução não só está correcta do ponto de vista do que calcula, mas também se está suficientemente eficiente e consegue responder em menos de um segundo seja qual for o input dentro das restrições dadas. Um programa correcto, mas não eficiente, irá apenas resolver parcialmente o probema (passa nos testes "pequenos", mas excede o limite de tempo nos testes "grandes").

Para este problema não vou dar nenhuma dica, ficando à espera de ver os vossos programas :)

Nota: é também agora possível submeter o desafio da semana anterior no Mooshak de EDados.