É 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.
// Importa a classe Scanner, que será usada para leitura de dadosimportjava.util.Scanner;publicclassSum{publicstaticvoidmain(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 inteiroint a = stdin.nextInt();int b = stdin.nextInt();// Imprime a soma dos dois números
System.out.println(a+b);}}
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.
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.
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).
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ê?
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
importjava.util.Scanner;publicclassCount{publicstaticvoidmain(String[] args){
Scanner stdin =new Scanner(System.in);// Ciclo para iterar sobre todas as linhas do inputint counter =0;while(stdin.hasNextLine()){
counter++;
String s = stdin.nextLine();
System.out.println(counter +": "+ s);}}}
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.
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
importjava.util.Scanner;publicclassReadNumbers{// Escrever os numeros guardados num array no stdoutstaticvoidwriteArray(int v[]){for(int i=0; i<v.length; i++)
System.out.println("v["+ i +"] = "+ v[i]);}publicstaticvoidmain(String[] args){
Scanner stdin =new Scanner(System.in);int v[]=newint[10];// Cria um novo array com espaço para 10 inteiros int n = stdin.nextInt();// Ler a quantidade de numeros que se seguemfor(int i=0; i<n; i++)// Ler os numeros a partir do stdin
v[i]= stdin.nextInt();
writeArray(v);// Chamar procedimento que escreve}}
Executando o código.
Compile e execute este código, redirecionando o input a partir do ficheiro numbers.txt $ java ReadNumbers < numbers.txt
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.
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.
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 qualquer submissão é possível visualizar o resultado obtido em cada um dos testes feitos ao código submetido. É também possível aceder aos testes públicos onde o programa submetido não responde correctamente. Para isso basta carregar no resultado da submissão, que aparece a sublinhado na listagem.
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)
Este problema é uma continuação do exercício anterior (falta acrescentar uma nova função para calcular a média)
Para imprimir um double com duas casas decimais pode usar a instrução printf (como no C). Por exemplo, imprimir uma variável x com duas casas decimais seria System.out.printf("%.2f\n", x);
Note que não tem de verificar se o input obedece aos limites dados no enunciado. Pelo contrário, essas restrições estão lá para lhe garantir que os dados respeitam esses limites (ex: assim sabe que nunca irão existir mais que 1000 números inteiros nos inputs que são dados ao seu programa no Mooshak).
Todas as linhas do input e do output devem terminar com o caracter de mudança de linha (mesmo a última)
Por uma questão de performance e dado que a máquina virtual que vos foi fornecida contém Java 1.8, decidi colocar como versão oficial no Mooshak também Java 1.8 (é nessa versão que os vossos programas serão compilados).
Exercício 5) Mais dois problemas no Mooshak
Para consolidar os conhecimentos destas duas primeiras aulas, submeta os seguintes problemas no Mooshak:
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.
Resolva e submeta com sucesso o problema [ED243] Pizza
Guarda os ingredientes que o Mario não gosta num array a[] de tamanho N
Inicialize um contador a zero
Faça um ciclo com P iterações e em cada uma delas:
Leia os ingredientes da pizza i para um array de b[] de tamanho Ki
Crie uma função que receba a[] e b[] e verifique a pizza está ok, ou seja, se não há ingredientes em comum (basta fazer um dois ciclos no tamanho dos arrays e comparar elemento a elemento e ver se algum par é igual)
Chame a função para cada pizza e se estiver ok, incremente um contador
Este exercício vem na sequência da aula anterior, onde implementou uma forma um pouco naive de verificar se um dado número é primo. Executar esse procedimento neste problema para todos os números no intervalo vai excecer o limite de tempo (pode experimentar para verificar o que acontece).
Aqui é suposto que pesquise um pouco seguindo a sugestão do enunciado: veja por exemplo a entrada da Wikipedia sobre o Crivo de Eratóstenes (existem muitos recursos possíves online)
A ideia é precisamente implementar o crivo, criando um array de booleanos prime[i] (de tamanho 10 milhões) que tenha uma posição i a true se o número i for primo, e false caso contrário.
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.