2. [TD]: O problema
Palavras-chave: algoritmos, noções básicas de Java: matrizes, E/S, loops, testes, gestão de exceções
Leituras recomendadas: capítulo 1 de [ref1]: Noções básicas da linguagem Java
2.1. Support
A pasta [support / chap-02] contém o algoritmo a traduzir para C# e Java.
2.2. O problema a resolver
Pretende-se escrever um programa que, na noite das eleições, consiga calcular o número de lugares obtidos pelas diferentes listas em disputa. Mais adiante, será apresentado o método de cálculo dos lugares para uma eleição proporcional com base na média mais elevada, tal como explicado num artigo do jornal Ouest-France de 15 de março de 1986.
Iremos escrever uma aplicação Java de «consola», c.a.d, uma aplicação que utiliza o teclado e o ecrã para comunicar com o utilizador. A aplicação solicitará ao utilizador as seguintes informações (introduzidas através do teclado):
- número de lugares a preencher
- número de listas em concorrência
- para cada lista: o seu nome e o número de votos
Com estas informações, a aplicação calcula os lugares obtidos por cada uma das listas e apresenta-os no ecrã da seguinte forma:
onde [Xi] é o nome da lista n.º i e [Ni] o número de lugares que esta obteve.
Artigo do Ouest-France de 15 de março de 1986:


2.3. A solução algorítmica
Uma solução algorítmica poderia ser a seguinte:
| début-programme
// dados
saisieOK : booléen
nbSiègesAPourvoir : entier
nbListes : entier
nomListe[] : chaînes de caractères
voixListe[] : entier
elimineListe[] : booléen
siegesListe[] : entier
moyenneListe[] : réel
i : entier
nbVoixUtiles : entier
quotientElectoral : réel
nbSiègesPourvus : entier
moyenneMax : réel
Max : entier iSiège : entier
// código
// número de lugares a preencher
saisieOK<-faux
tant que non saisieOK
écrire "Nombre de sièges à pourvoir : "
lire nbSiègesAPourvoir
si nbSiègesAPourvoir n'est pas un entier >0 alors
écrire "Erreur : tapez un nombre entier >0"
sinon
saisieOK<-vrai
finsi
fintantque
// número de listas concorrentes
saisieOK<-faux
tant que non saisieOK
écrire "Nombre de listes en compétition : "
lire nbListes
si nbListes n'est pas un entier >0 alors
écrire "Erreur : tapez un nombre entier >0"
sinon
saisieOK<-vrai
finsi
fintantque
// dimensionamento das tabelas
dimensionner les tableau nomListe, voixListe, elimineListe, siegesListe, moyenneListe à nbListes éléments
// introdução dos nomes e votos das listas
totalVoix<-0
pour i variant de 0 à nbListes-1
// introdução do nome da lista i
saisieOK<-faux
tantque non saisieOK
écrire "Nom de la liste n° ", i, " : "
lire nomListe[i]
si nomListe[i] est vide alors
écrire "Erreur : Tapez un nom non vide"
sinon
saisieOK<-vrai
finsi
fintantque
// introdução do número de votos da lista i
saisieOK<-faux
tantque non saisieOK
écrire "Nombre de voix de la liste ", nomListe[i] , " : "
lire voixListe[i]
si voixListe[i] n'est pas un nombre entier >=0 alors
écrire "Erreur : tapez un nombre entier >=0"
sinon
saisieOK<-vrai
finsi
fintantque
// incrementa-se o total de votos
totalVoix<- totalVoix+voixListe[i]79.finpour 80.
// cálculo dos votos válidos
nbVoixUtiles<-0
pour i variant de 0 à nbListes-1
si (voixListe[i]/totalVoix)<0.05 alors
elimineListe[i]<-vrai
sinon
elimineListe[i]<-faux
nbVoixUtiles<-nbVoixUtiles+voixListe[i]
finsi
finpour
// existem listas que não foram eliminadas?
si nbVoixUtiles=0 alors
écrire "Erreur : toutes les listes ont été éliminées"
arrêt du programme
finsi
// distribuição dos lugares pelo quociente
quotientElectoral <- nbVoixUtiles / nbSiègesAPourvoir
nbSiègesPourvus<- 0
pour i variant de 0 à nbListes-1
si non elimineListe[i] alors
siegesListe[i]<- partie entière de (voixListe[i]/quotientElectoral)
moyenneListe[i] <- voixListe[i] / (siegesListe[i]+1)
nbSiègesPourvus<-nbSiègesPourvus+siegesListe[i]
sinon
siegesListe[i]<-0
finsi
finpour
// distribuição dos lugares restantes pela média mais elevada
// É atribuído 1 lugar em cada volta do ciclo
pour iSiège variant de 0 à nbSiègesAPourvoir - nbSiègesPourvus - 1
// identificação da lista com a média mais elevada
moyenneMax<- (-1)
pour i variant de 0 à nbListes-1
si non elimineListe[i] alors
si moyenneListe[i] > moyenneMax alors
moyenneMax <- moyenneListe[i]
iMax <- i
finsi
finsi
finpour
// atribui-se 1 lugar à lista com a média mais elevada
siegeListe[iMax] <- siegeListe[iMax]+1
// e altera-se a sua média
moyenneListe[iMax] <- voixListe[iMax]/(siegeListe[iMax]+1)
finpour
// exibição dos resultados sem ordenação
pour i variant de 0 à nbListes-1
si elimineListe[i] alors
écrire "La liste ", nomListe[i], " a été éliminée"
sinon
écrire "La liste ", nomListe[i], " a obtenu ",
siegesListe[i], " siège(s)"
finsi
finpour
fin-programme
|
2.4. Trabalho a realizar
Q1: traduzir o algoritmo para C#. Implementá-lo com o Visual Studio.
Q2: traduzir o algoritmo para Java, inspirando-se no código C#. Implementar o programa Java num ambiente Eclipse semelhante ao seguinte:
- [1]: o projeto chama-se [elections-01]
- [2]: a aplicação será colocada num pacote, neste caso [istia.st.elections]
- [3]: [MainElections.java] é o código-fonte da aplicação escrita na parte anterior
- [4]: a classe [MainElections] é executada
Um exemplo de execução poderia ser o seguinte:
