Sie sind auf Seite 1von 9

Relatorio do Trabalho Pratico

Joao Pereira
Francisco Mendes
3 de Janeiro de 2015

Conte
udo
1 Introdu
c
ao
2 Desenvolvimento do Projeto
2.1 Tarefa A . . . . . . . . . . .
2.2 Tarefa B . . . . . . . . . . .
2.3 Tarefa C . . . . . . . . . . .
2.4 Tarefa D . . . . . . . . . . .
2.5 Tarefa E . . . . . . . . . . .
2.6 Makefile e runtests.sh . . .

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

3 Conclus
ao

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

1
1
2
3
5
7
8
9

Introdu
c
ao

Este relat
orio descreve o processo de desenvolvimento do trabalho pratico realizado no
ambito da unidade curricular Laborat
orios de Inform
atica I. Neste projeto, aplicamos os conhecimentos adquiridos ao longo do semestre, e evolumos
as nossas capacidades de programacao, gestao de projetos, uso de comandos
UNIX, uso de sistemas de controle de versoes e capacidades de trabalho em
grupo. Quanto ao projeto em si, este e inspirado no jogo LightBot facilmente
acessvel online e que consiste em criar sequencias de comandos que possibilitem
ao robot ligar todas as luzes de um tabuleiro.

Desenvolvimento do Projeto

Neste captulo, passamos entao a expor a forma como o nosso trabalho funciona.

2.1

Tarefa A

Nesta fase do projeto foi-nos pedido que fizessemos um programa que validasse
o input fornecido. Para tal, criamos a funcao tarefa.
1

Caso o input passado fosse uma lista vazia, era devolvido 1, ou seja, havia
um erro na primeira linha. Caso contrario, se o tabuleiro fosse uma lista vazia, ou seja, se n
ao houvesse nenhuma linha constituda apenas por caracteres
alfabeticos, ent
ao daria erro na primeira linha. Se houvesse uma parte valida
correspondente ao tabuleiro, i.e. uma ou mais linhas com caracteres alfabeticos,
ent
ao a func
ao verificaLength iria verificar se as linhas do tabuleiro tinham
todas o mesmo tamanho e se nao tivessem, devolvia o Int correspondente `a
primeira linha com comprimento diferente. Senao, esta funcao devolvia 0 e a
func
ao validaTab prosseguia.
A seguir, ia correr a funcao ver posInicial que verifica se linha da posicao
inicial e v
alida da seguinte forma: se o char que corresponde `a orientacao inicial
for ou N ou S ou E ou O e se os dois primeiros elementos do resultado de
words(posi
c~
aoInicial) aplicada ao tabuleiro em questao correspondem a duas
coordenadas v
alidas, (i.e. se forem dois n
umeros inteiros e a posicao correspondente estiver dentro do tabuleiro) entao a linha correspondente `a posicao inicial
e v
alida e vai passar para a verificacao da proxima condicao. Caso contrario,
d
a o n
umero da linha da posicao inicial.
A seguir, os comandos s
ao verificados pela funcao valida linhaCom aplicada
ao tabuleiro. Esta func
ao verifica se todos os elementos da linha de comandos
s
ao ou A ou S ou D ou E ou L. Se nao forem, entao e devolvido o Int
que corresponde `
a linha dos comandos. Caso contrario, esta funcao devolve 0 e
chegamos `
au
ltima avaliac
ao que verifica se ha mais linhas depois dos comandos.
Se houver, ent
ao e devolvido o Int que corresponde `a primeira linha imediatamnete a seguir `
a lista de comandos. Caso contrario, e devolvido 0 e o tabuleiro e
considerado v
alido.

2.2

Tarefa B

Nesta fase, tinhamos de criar um programa que dado um input valido, era
devolvida a pr
oxima posic
ao do robot se o primeiro comando fosse valido e ERRO
caso contr
ario. Este programa e constitudo pelas seguintes funcoes principais:
estadoInicial que dado um tabuleiro, cria um tuplo com as coordenadas
e a orientac
ao com que o Robot comeca o jogo;
verPosicao que dado um tabuleiro e um estado, i.e., um tuplo constitudo
pela posic
ao em que o Robot se encontra e a orientacao do mesmo, devolve
a letra correspondente `a posicao;
converteEstado que dado um estado, converte-o para uma string da seguinte forma:
>>> converteEstado (1,1,N)
"1 1 N"
proxPosicao que dado um tabuleiro e o estado atual do Robot, devolve
a pr
oxima posic
ao dependendo da orientacao;
2

Ent
ao, a func
ao tarefa funciona da seguinte forma:
1. Se o primeiro comando for um L e se a letra correspondente `a posicao
inicial f
or mai
uscula, entao estamos perante uma luz que vai ser ligada e a
posic
ao e orientac
ao do robot vao-se manter inalteradas, pelo que vai ser
devolvida a string correspondente `a posicao inicial, i.e. converteEstado
(estadoInicial t) em que t e o input. Senao passa-se `a proxima fase;
2. Se o primeiro comando for S e a proxima posicao esta dentro do tabuleiro
e se altura do tabuleiro no estado inicial for superior `a da proxima posicao
ou se f
or igual `
a altura da proxima posicao subtrada 1 entao e possvel o
robot saltar e e mostrada a string correspondente `a proxima posicao.Caso
contr
ario, passa-se `
a proxima condicao;
3. Caso o primeiro comando seja A, se a proxima posicao estiver dentro
do tabuleiro e a altura da posicao atual for igual `a da proxima, entao
e possvel que o robot avance e e devolvida a string correspondente ao
pr
oximo estado. Caso contrario, continua para o passo 4;
4. No caso do primeiro comando ser E, e aplicada uma rotacao no estado
inicial (a posic
ao mantem-se, mudando apenas a orientacao) e e imprimida
a string correspondente ao segundo estado. Caso contrario passa-se para
au
ltima verificac
ao;
5. Se o primeiro comando passado ao robot for D entao aplica-se uma
rotac
ao `
a direita ao estado inicial e imprime-se esse estado. Caso contrario,
e imprimida a string ERRO.

2.3

Tarefa C

Nesta tarefa, foi-nos pedido que criassemos um programa que dado um input
constitudo pelo tabuleiro, pela posicao inicial e pelos comandos, verificasse se
estes comandos ligavam as luzes todas do tabuleiro. Para tal, criamos a funcao
tarefa que chama a func
ao aux aplicada ao input, `a lista de comandos, ao
n
umero de jogadas corretas (acumulador que comeca em 0), `a lista de luzes do
tabuleiro e ao resultado da tarefa B aplicada ao tabuleiro e ao primeiro elemento
da lista de comandos. A funcao tB faz o mesmo que faz a funcao tarefa na
parte B mas sofreu algumas alteracoes para que quando fosse ligada uma luz, a
string devolvida contivesse um L no nicio e depois o estado do robot.
Antes de passar `
a descricao geral do programa, devem ser explicadas duas
func
oes muitos importantes ao funcionamento do mesmo:
func
ao lampadas que dado um tabuleiro, calcula uma lista de strings cujos
elementos correpondem `as posicoes onde existem luzes. Esta funcao funciona recursivamente e nao faz mais do que varrer o tabuleiro `a procura de
letras mai
usculas e, caso as encontre, guarda as coordenadas da posicao
correspondente.

func
ao proxTab que dado uma lista de strings com o tabuleiro, estado
inicial e lista de comandos, calcula a lista neste formato para o proximo
estado, i.e. se a lista de comandos for vazia entao o resultado e igual `a lista
passada `
a func
ao. Se o primeiro comando for aplicavel entao da a lista
constituda pelo tabuleiro, pelo proximo estado e pela tail da lista de
comandos. Caso contrario, devolve a lista com o tabuleiro, estado inicial
e a tail da lista de comandos.
A func
ao aux aplicada aos parametros descritos acima funciona da seguinte
forma:
1. Se a lista de luzes f
or vazia, entao e devolvida a palavra FIM juntamente
com o n
umero de jogadas corretas efetuadas.
2. Caso contr
ario, se a lista de comandos for vazia, ou seja, se todos os
comandos tiverem sido executados, entao significa que as luzes nao foram
todas ligadas e por isso e imprimido INCOMPLETO.
3. Se o primeiro elemento da string resultante da aplicacao da funcao tB ao
conjunto formado pelo tabuleiro e estado atual do robot e ao primeiro
comando da lista de comandos for um L (relembrando a alteracao que
fizemos `
a func
ao da tarefa B referida acima) entao:
Se essa luz estiver na lista de luzes entao ainda nao foi ligada e por
isso e devolvida a string correspondente `a posicao onde esta o robot
usando a func
ao limpa que remove o L e a orientacao do resultado da
func
ao tB e de seguida calcula-se o resultado da funcao aux aplicada
ao resultado de proxTab , `a tail da lista de comandos, ao n
umero
de jogadas corretas mais 1, `a lista de luzes sem a luz que foi agora
ligada e ao resultado de tB aplicada ao resultado da funcao proxTab
t em que t e o input.
Se essa luz n
ao estiver na lista de luzes significa que ja foi ligada e
que agora vai ser desligada. Entao e imprimida uma string com as
coordenadas da luz e calcula-se o resultado da funcao aux aplicada
ao resultado de proxTab, `a tail da lista de comandos, ao n
umero de
jogadas corretas mais 1, `a lista de luzes com a luz que foi agora desligada e ao resultado de tB aplicada ao resultado da funcao proxTab
t em que t e o input.
4. Se a condic
ao referida no ponto 3 nao for cumprida, verifica-se se a aplicacao
do primeiro comando da lista de comandos e possvel e se for, chama-se
recursivamente a func
ao aux aplicada ao proxTab da lista com o tabuleiro,
estado atual e lista de comandos, `a tail da lista de comandos, ao n
umero
de jogadas corretas mais um, `a lista de luzes por ligar e `a tB aplicada ao
resultado de proxTab.
5. Se nenhuma das condicoes anteriores e verificada, entao chama-se a funcao
aux com os mesmos argumentos com que foi chamada mudando apenas a
lista de comandos que passa a ser a tail dessa lista.
4

Esta func
ao vai correr recursivamente ate ligar todas as luzes ou ate esgotar
os comandos.

2.4

Tarefa D

O objetivo desta tarefa era criar um programa que dado um input constitudo
pelo tabuleiro e pelo estado inicial, cria uma lista de comandos que liga todas as
luzes. Com esse fim em vista, procuramos utilizar um algoritmo que funcionasse
para todos os casos possveis, i.e. em que todas as lampadas sao acessveis ao
robot e acabamos por implementar uma solucao inspirada no algoritmo A*.
Ent
ao, a nossa tarefa funciona da seguinte forma:
1. Dado o input, a func
ao tarefa chama a funcao lista comandos aplicada
aos par
ametos tabuleiro, posicao inicial (passada como um par de inteiros),
orientac
ao inicial e a lista de luzes do tabuleiro calculada pela funcao
lista luzes, parecida com a que utilizamos anteriromente.
ent
2. E
ao calculado o resultado de lista comandos que e uma funcao recursiva que calcula os comandos necessarios para chegar da posicao inicial
ate `
a posic
ao que e o primeiro elemento da lista de luzes e depois chama-se
recursivamente para calcular os comandos a partir da primeira luz ate `a
segunda e assim sucessivamente ate percorrer todas as luzes. Note-se que
ou
ltimo elemento da lista de comandos necessarios para passar de uma
posic
ao `
a outra e um L, ou seja, quando chega aos destinos que sao as
luzes, estas s
ao ligadas.
Esses comandos s
ao calculados atraves de caminhos, i.e. uma lista de pares
de posic
oes em que a primeira posicao do par e a origem e a segunda e a proxima
posic
ao. Note-se que a dist
ancia do ponto de origem ao ponto seguinte e sempre
1 e o movimento entre os dois e sempre possvel. A funcao responsavel por converter um caminho numa lista de comandos e a converte comandos que dado
um caminho (do tipo [(Pos,Pos)]) e a orientacao inicial e o tabuleiro, converte
em lista de comandos necessarios a percorrer esse caminho.
Ent
ao, dadas duas posi
c
oes como conseguimos obter um caminho
v
alido entre as duas?
Os caminhos s
ao criados a partir de listas de posicoes consecutivas e acessveis ao
nesta parte que entra em acao
robot atraves da func
ao converte caminhos. E
a func
ao a est inspirada no algoritmo A* que calcula a lista de posicoes que
formar
ao o caminho. Esta funcao nao faz mais que chamar a funcao a est aux
com um par
ametro predefinido que vai ser explicada depois de explicar o funcionamento da func
ao a est (nao confundir com a est).
A func
ao a est, dado um tabuleiro, uma posicao inicial, uma posicao pretendida, uma lista de posicoes percorridas pelo robot (que devera ser [ ] na
primeira iterac
ao da func
ao), doravante conhecida como lista aberta, a lista de
posic
oes que o robot tem de percorrer para chegar `a posicao atual, doravante
conhecida como lista fechada e que tambem devera ser [ ] na primeira iteracao,
5

esta func
ao calcula as posic
oes que o robot deve percorrer para chegar `a posicao
pretendida a partir da inicial da seguinte forma:
1. Se a posic
ao pretendida estiver na lista fechada, entao significa que ja se
alcancou a posic
ao pretendida e o algoritmo termina. Senao, passa-se para
o passo 2.
2. Se n
ao existirem movimentos possveis a partir da posicao atual que nao
estejam na lista aberta e na lista fechada, i.e. se nao existirem posicoes
acessveis que ainda nao tenham sido percorridas, entao devolve a lista
com as posic
oes que o robot percorreu ate chegar `a poiscao onde esta
(esta u
ltima posic
ao esta includa na lista). Note-se que nestes casos, o
resultado n
ao e v
alido mas sera u
til para o caculo de um caminho valido
atraves de outra funcao explicada mais `a frente.
3. Caso hajam posic
oes possveis que ainda nao tenham sido percorridas,
adiciona-se a posic
ao atual `a lista aberta e e escolhida a posicao possvel
que tem menor dist
ancia (valor absoluto da diferenca dos valores das coordenadas) `
a posic
ao objetivo para a nova posicao e adiciona-se `a lista fe ent
chada. E
ao chamada recursivamente a funcao aplicada ao tabuleiro, `a
nova posic
ao, `
a posic
ao objetivo e `as listas aberta e fechada alteradas. Esta
func
ao vai correr recursivamente ate ser encontrado um caminho possvel
ou ate chegar a um estado em que nao existem movimentos possveis.
Exemplo:
>>> a_est ["BbbC","Cccb","aaba","aaaa"] (3,0) (0,3) [] []
[(2,0),(1,0),(0,0),(0,1),(1,1),(2,1),(2,2),(1,2),(0,2),(0,3)]
>>> a_est ["aaaa","acca","acca","acca","aaca"] (0,0) (3,0) [] []
[(1,0)]
No primeiro caso, facilmente se observa que foi encontrado um caminho
possvel. J
a no segundo, o resultado tera de ser tratado por uma funcao diferente
para que um caminho v
alido seja obtido.
Passo agora a explicar a funcao a est aux que dado um tabuleiro, a posicao
inicial, a posic
ao pretendida e uma lista que corresponde `a lista aberta:
Se a func
ao a est encontrou um caminho da posicao inicial ate `a pretendida (i.e. se a posic
ao pretendida faz parte da lista de posicoes calculadas),
insere a posic
ao inicial na primeira posicao da lista de posicoes resultante
da func
ao a est e o algoritmo acaba, sendo que o resultado pode ser agora
trabalhado pela func
ao converte caminhos;
Caso contr
ario, vai ser calculado recursivamente, ate obter uma solucao,
o resultado da func
ao a est aplicada aos mesmos pontos e tabuleiro mas
em que a lista aberta contem a u
ltima posicao do resultado anterior, funcionando como uma restricao sobre os movimentos possveis na proxima
vez que executar a funcao.
6

Usando o algoritmo descrito em acima conseguimos resolver todos os casos


de teste que concebemos e conseguimos tambem obter 20 pontos na avaliacao
do mooshak.

2.5

Tarefa E

Nesta tarefa, foi-nos proposto criar um programa que dado um input (constitudo pelo tabuleiro, estado inicial e lista de comandos), gera o codigo de um
documento html onde e possvel visualizar o tabuleiro em 3D usando a framework X3DOM.
Para tal, definimos 3 listas de Strings que vao ser comuns a todos os documentos html:
cabecalho - Esta parte do codigo e responsavel pela importacao das bibliotecas necess
arias ao funcionamento do X3DOM e `a definicao de outras
caractersticas da p
agina html;
pontos - Parte do c
odigo responsavel pela definicao das shapes que vao
formar o tabuleiro e da forma do robot;
fim - parte burocr
aticanecessaria ao documento para que a estrutura da
p
agina esteja correta;
Dado um input, a func
ao tarefa vai juntar estas listas de strings comuns a
todos os documentos com as partes varaveis. Estas partes variaveis sao geradas
pela func
ao geraHtml, que cria o codigo referente ao tabuleiro, e pela gerAnim,
que cria o c
odigo respons
avel pela animacao do robot.
A func
ao geraHtml recebe uma lista de triplos em que os dois primeiros
elementos s
ao do tipo Int e o terceiro e um Char. O formato desta lista coincide
com o resultado da func
ao processa que dado um tabuleiro , devolve uma lista
de triplos em que os dois primeiros elementos sao uma posicao do tabuleiro
e o terceiro e a letra correspondente `a posicao. Na funcao tarefa, a funcao
geraHtml e passada com o argumento que e o resultado da funcao processa
aplicada ao tabuleiro que esta no input.
A func
ao geraHtml aplicada a uma lista do tipo [(Int, Int, Char)] aplica
a todos os elementos da lista a funcao aux que funciona da seguinte forma:
1. Se a altura da posic
ao atual for 0, se houver uma luz naquela posicao entao
gera o c
odigo html responsavel por criar um paralelpipedo amarelo, que
simboliza a existencia de luz. Se nao houver uma luz, entao gera o codigo
html respons
avel por criar um paralelpipedo azul, que indica que nao
existe uma luz naquela posicao. Depois a funcao termina.
2. Caso contr
ario, se a posicao que queremos gerar corresponde a uma luz e
est
a no topo do tabuleiro, i.e. nao existem paralelippedos gerados acima
do atual ent
ao e gerado um paralelpipedo amarelo e chama-se a funcao
aux para gerar as shapes que deverao ficar abaixo da que foi gerada agora.

3. Se nenhuma das condicoes anteriores se verificar, entao gera-se a shape


correspondente `
a posicao sem luz para a altura atual e calcula-se as restantes shapes que deverao ficar abaixo chamando recursivamente a funcao
aux.
Desta forma, e criado o tabuleiro todo. Para gerar o robot e as animacoes
correspondentes, usamos a funcao gerAnim. Esta funcao recebe o input da
func
ao tarefa e devolve o c
odigo html com a estrutura necessaria ao funcionamento das animac
oes e define a duracao da animacao, as posicoes por onde deve
passar o robot, os tempos em que devem ser executadas animacoes e rotacoes e
de quantos graus devem ser essas rotacoes.
A durac
ao da animac
ao e diretamente proporcional ao n
umero de comandos
passados ao robot e os valores da key da PositionInterpolator (mecanismo
respon
avel por gerar as translacoes do robot) sao obtidos adicionando sempre
1 dividido pelo comprimento da lista de comandos ao valor anterior, enquanto
que este e menor que 1. As posicoes para a keyValue sao obtidas atraves
da func
ao posicoes que dado o estado inicial, a lista de comandos a executar e o tabuleiro cria uma string com todas as posicoes por onde o robot deve
passar. Os valores para a key da orientationInterpolator (mecanismo respons
avel pelas rotac
oes do robot) sao obtidos filtrando os valores da key da
PositionInterpolator em que ocorre uma rotacao, i.e. e executado um comando D ou E e os valores para a keyValue sao obtidos atraves da aplicacao
das rotac
oes `
a orientac
ao original atraves da funcao lista angulos.
Desta forma, a func
ao tarefa gera-se a representacao visual do tabuleiro.
Note-se que o mooshak atribui Presentation Error `a nossa tarefa E, no entanto a estrutura do html e valida e a representacao grafica do tabuleiro funciona
corretamente.

2.6

Makefile e runtests.sh

Quando e executado o programa make, os programas das diferentes tarefa vao


ser compilados e v
ao ser corridos varios testes atraves do script runtests.sh
que est
a na pasta tests. Depois e gerada a documentacao haddock na pasta doc
e o relat
orio e convertido para pdf.
O script runtests.sh verifica se existe um ficheiro com extensao .out e se
houver, compara o conte
udo desse ficheiro com o output da tarefa a ser testada
e se forem iguais, e imprimida uma string que confirma que o teste teve um
resultado correto. Caso contrario, e imprimida uma mensagem de erro.
Se n
ao existir um ficheiro com extensao .out entao, se o ficheiro corresponder
a um ficheiro de testes da tarefa E, e gerado o ficheiro html com a visualizacao
do tabuleiro. Se o ficheiro f
or um teste da tarefa D entao e criado um ficheiro
com extens
ao .res que contem os dados do ficheiro original mais o resultado
da tarefa D e calcula-se o output desse ficheiro pela tarefa C e guarda-se num
ficheiro com extens
ao .out. Se existir a palavra FIMno ficheiro devolvido
ent
ao o teste e bem sucedido. Caso contrario da erro. No fim, os ficheiros com
extens
ao .out e .res s
ao eliminados.

Se o ficheiro de teste n
ao for nem da tarefa D nem da E entao o teste e
ignorado.

Conclus
ao

Este projeto foi uma experiencia verdadeiramente enriquecedora uma vez que
foi a primeira ves que fomos expostos ao desenvolvimento de um projeto de
software do incio ao fim.
Durante o desenvolvimento deste projeto utilizamos maioritariamente aquilo
que nos foi lecionado nas aulas de Laboratorios de Informatica e Programacao
Funcional mas por vezes tivemos de recorrer a outras tecnicas e conhecimentos
n
ao lecionados principalmente na implementacao das animacoes na tarefa E e
no algoritmo de path-finding da tarefa D.
Ao longo do trabalho encontramos varios obstaculos e desafios, alguns deles
bastante dificeis de superar, como por exemplo, alcancar os 20 pontos na tarefa
D, mas conseguimos fazer tudo a que nos propusemos e consideramos que fizemos
um bom trabalho, certamente acima da media.

Das könnte Ihnen auch gefallen