relatorio de haskell

10
 Relat´ orio do Trabalho Pr´ atico Jo˜ ao Pereira Francisco Mendes 3 de Janeiro de 2015 Conte´ udo 1 In tr odu¸ ao 1 2 Desenvolvimento do Projeto 1 2.1 T arefa A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 2.2 T arefa B . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 2.3 T arefa C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2.4 T arefa D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 2.5 T arefa E . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 2.6 Makele e runtests.sh . . . . . . . . . . . . . . . . . . . . . . . . 8 3 Conclus˜ ao 9 1 Introdu¸ c˜ ao Este relat´ orio descreve o processo de desenvolvimento do trabalho pr´atico reali- zado no ˆ ambito da unidade curricular  Laborat´ orios de Inform´ atica I . Neste pro-  jeto, aplicamos os conhecimentos adquiridos ao longo do semestre, e evolu´ ımos as nossas capacidades de programa¸ ao, gest˜ ao de projetos, uso de comandos UNIX, uso de sistemas de controle de vers˜ oes e capacidades de trabalho em grupo. Quan to ao projeto em si, este ´ e inspi rado no jogo LightBo t facil mente acess´ ıvel on line e que consist e em criar sequˆ encias de co mandos que p ossibil item ao robot ligar todas as luzes de um tabuleiro. 2 Desenvol vimento do Pr ojeto Neste cap ´ ıtulo, passamo s ent˜ ao a expor a forma como o nosso trabalho funciona. 2.1 Tarefa A Nesta fase do projeto foi-nos pedido que zessemos um programa que validasse o  input  fornecido. Para tal, criamos a fun¸ ao  tarefa. 1

description

Realtorio sobre desenvolvimento do light bot em haskell

Transcript of relatorio de haskell

  • Relatorio do Trabalho Pratico

    Joao PereiraFrancisco Mendes

    3 de Janeiro de 2015

    Conteudo

    1 Introducao 1

    2 Desenvolvimento do Projeto 12.1 Tarefa A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.2 Tarefa B . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22.3 Tarefa C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32.4 Tarefa D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52.5 Tarefa E . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72.6 Makefile e runtests.sh . . . . . . . . . . . . . . . . . . . . . . . . 8

    3 Conclusao 9

    1 Introducao

    Este relatorio descreve o processo de desenvolvimento do trabalho pratico reali-zado no ambito da unidade curricular Laboratorios de Informatica I. Neste pro-jeto, aplicamos os conhecimentos adquiridos ao longo do semestre, e evolumosas nossas capacidades de programacao, gestao de projetos, uso de comandosUNIX, uso de sistemas de controle de versoes e capacidades de trabalho emgrupo. Quanto ao projeto em si, este e inspirado no jogo LightBot facilmenteacessvel online e que consiste em criar sequencias de comandos que possibilitemao robot ligar todas as luzes de um tabuleiro.

    2 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 validasseo input fornecido. Para tal, criamos a funcao tarefa.

    1

  • Caso o input passado fosse uma lista vazia, era devolvido 1, ou seja, haviaum erro na primeira linha. Caso contrario, se o tabuleiro fosse uma lista va-zia, ou seja, se nao houvesse nenhuma linha constituda apenas por caracteresalfabeticos, entao daria erro na primeira linha. Se houvesse uma parte validacorrespondente ao tabuleiro, i.e. uma ou mais linhas com caracteres alfabeticos,entao a funcao verificaLength iria verificar se as linhas do tabuleiro tinhamtodas o mesmo tamanho e se nao tivessem, devolvia o Int correspondente a`primeira linha com comprimento diferente. Senao, esta funcao devolvia 0 e afuncao validaTab prosseguia.

    A seguir, ia correr a funcao ver posInicial que verifica se linha da posicaoinicial e valida da seguinte forma: se o char que corresponde a` orientacao inicialfor ou N ou S ou E ou O e se os dois primeiros elementos do resultado dewords(posic~aoInicial) aplicada ao tabuleiro em questao correspondem a duascoordenadas validas, (i.e. se forem dois numeros inteiros e a posicao correspon-dente estiver dentro do tabuleiro) entao a linha correspondente a` posicao iniciale valida e vai passar para a verificacao da proxima condicao. Caso contrario,da o numero da linha da posicao inicial.

    A seguir, os comandos sao verificados pela funcao valida linhaCom aplicadaao tabuleiro. Esta funcao verifica se todos os elementos da linha de comandossao ou A ou S ou D ou E ou L. Se nao forem, entao e devolvido o Intque corresponde a` linha dos comandos. Caso contrario, esta funcao devolve 0 echegamos a` ultima avaliacao que verifica se ha mais linhas depois dos comandos.Se houver, entao e devolvido o Int que corresponde a` primeira linha imediatam-nete a seguir a` lista de comandos. Caso contrario, e devolvido 0 e o tabuleiro econsiderado valido.

    2.2 Tarefa B

    Nesta fase, tinhamos de criar um programa que dado um input valido, eradevolvida a proxima posicao do robot se o primeiro comando fosse valido e ERROcaso contrario. Este programa e constitudo pelas seguintes funcoes principais:

    estadoInicial que dado um tabuleiro, cria um tuplo com as coordenadase a orientacao com que o Robot comeca o jogo;

    verPosicao que dado um tabuleiro e um estado, i.e., um tuplo constitudopela posicao em que o Robot se encontra e a orientacao do mesmo, devolvea letra correspondente a` posicao;

    converteEstado que dado um estado, converte-o para uma string da se-guinte forma:

    >>> converteEstado (1,1,N)

    "1 1 N"

    proxPosicao que dado um tabuleiro e o estado atual do Robot, devolvea proxima posicao dependendo da orientacao;

    2

  • Entao, a funcao tarefa funciona da seguinte forma:

    1. Se o primeiro comando for um L e se a letra correspondente a` posicaoinicial for maiuscula, entao estamos perante uma luz que vai ser ligada e aposicao e orientacao do robot vao-se manter inalteradas, pelo que vai serdevolvida 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 tabuleiroe se altura do tabuleiro no estado inicial for superior a` da proxima posicaoou se for igual a` altura da proxima posicao subtrada 1 entao e possvel orobot saltar e e mostrada a string correspondente a` proxima posicao.Casocontrario, passa-se a` proxima condicao;

    3. Caso o primeiro comando seja A, se a proxima posicao estiver dentrodo tabuleiro e a altura da posicao atual for igual a` da proxima, entaoe possvel que o robot avance e e devolvida a string correspondente aoproximo estado. Caso contrario, continua para o passo 4;

    4. No caso do primeiro comando ser E, e aplicada uma rotacao no estadoinicial (a posicao mantem-se, mudando apenas a orientacao) e e imprimidaa string correspondente ao segundo estado. Caso contrario passa-se paraa ultima verificacao;

    5. Se o primeiro comando passado ao robot for D entao aplica-se umarotacao 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 inputconstitudo pelo tabuleiro, pela posicao inicial e pelos comandos, verificasse seestes comandos ligavam as luzes todas do tabuleiro. Para tal, criamos a funcaotarefa que chama a funcao aux aplicada ao input, a` lista de comandos, aonumero de jogadas corretas (acumulador que comeca em 0), a` lista de luzes dotabuleiro e ao resultado da tarefa B aplicada ao tabuleiro e ao primeiro elementoda lista de comandos. A funcao tB faz o mesmo que faz a funcao tarefa naparte B mas sofreu algumas alteracoes para que quando fosse ligada uma luz, astring devolvida contivesse um L no nicio e depois o estado do robot.

    Antes de passar a` descricao geral do programa, devem ser explicadas duasfuncoes muitos importantes ao funcionamento do mesmo:

    funcao lampadas que dado um tabuleiro, calcula uma lista de strings cujoselementos correpondem a`s posicoes onde existem luzes. Esta funcao funci-ona recursivamente e nao faz mais do que varrer o tabuleiro a` procura deletras maiusculas e, caso as encontre, guarda as coordenadas da posicaocorrespondente.

    3

  • funcao proxTab que dado uma lista de strings com o tabuleiro, estadoinicial e lista de comandos, calcula a lista neste formato para o proximoestado, i.e. se a lista de comandos for vazia entao o resultado e igual a` listapassada a` funcao. Se o primeiro comando for aplicavel entao da a listaconstituda pelo tabuleiro, pelo proximo estado e pela tail da lista decomandos. Caso contrario, devolve a lista com o tabuleiro, estado iniciale a tail da lista de comandos.

    A funcao aux aplicada aos parametros descritos acima funciona da seguinteforma:

    1. Se a lista de luzes for vazia, entao e devolvida a palavra FIM juntamentecom o numero de jogadas corretas efetuadas.

    2. Caso contrario, se a lista de comandos for vazia, ou seja, se todos oscomandos tiverem sido executados, entao significa que as luzes nao foramtodas ligadas e por isso e imprimido INCOMPLETO.

    3. Se o primeiro elemento da string resultante da aplicacao da funcao tB aoconjunto formado pelo tabuleiro e estado atual do robot e ao primeirocomando da lista de comandos for um L (relembrando a alteracao quefizemos a` funcao da tarefa B referida acima) entao:

    Se essa luz estiver na lista de luzes entao ainda nao foi ligada e porisso e devolvida a string correspondente a` posicao onde esta o robotusando a funcao limpa que remove o L e a orientacao do resultado dafuncao tB e de seguida calcula-se o resultado da funcao aux aplicadaao resultado de proxTab , a` tail da lista de comandos, ao numerode jogadas corretas mais 1, a` lista de luzes sem a luz que foi agoraligada e ao resultado de tB aplicada ao resultado da funcao proxTabt em que t e o input.

    Se essa luz nao estiver na lista de luzes significa que ja foi ligada eque agora vai ser desligada. Entao e imprimida uma string com ascoordenadas da luz e calcula-se o resultado da funcao aux aplicadaao resultado de proxTab, a` tail da lista de comandos, ao numero dejogadas corretas mais 1, a` lista de luzes com a luz que foi agora des-ligada e ao resultado de tB aplicada ao resultado da funcao proxTabt em que t e o input.

    4. Se a condicao referida no ponto 3 nao for cumprida, verifica-se se a aplicacaodo primeiro comando da lista de comandos e possvel e se for, chama-serecursivamente a funcao aux aplicada ao proxTab da lista com o tabuleiro,estado atual e lista de comandos, a` tail da lista de comandos, ao numerode jogadas corretas mais um, a` lista de luzes por ligar e a` tB aplicada aoresultado de proxTab.

    5. Se nenhuma das condicoes anteriores e verificada, entao chama-se a funcaoaux com os mesmos argumentos com que foi chamada mudando apenas alista de comandos que passa a ser a tail dessa lista.

    4

  • Esta funcao vai correr recursivamente ate ligar todas as luzes ou ate esgotaros comandos.

    2.4 Tarefa D

    O objetivo desta tarefa era criar um programa que dado um input constitudopelo tabuleiro e pelo estado inicial, cria uma lista de comandos que liga todas asluzes. Com esse fim em vista, procuramos utilizar um algoritmo que funcionassepara todos os casos possveis, i.e. em que todas as lampadas sao acessveis aorobot e acabamos por implementar uma solucao inspirada no algoritmo A*.

    Entao, a nossa tarefa funciona da seguinte forma:

    1. Dado o input, a funcao tarefa chama a funcao lista comandos aplicadaaos parametos tabuleiro, posicao inicial (passada como um par de inteiros),orientacao inicial e a lista de luzes do tabuleiro calculada pela funcaolista luzes, parecida com a que utilizamos anteriromente.

    2. E entao calculado o resultado de lista comandos que e uma funcao re-cursiva que calcula os comandos necessarios para chegar da posicao inicialate a` posicao que e o primeiro elemento da lista de luzes e depois chama-serecursivamente para calcular os comandos a partir da primeira luz ate a`segunda e assim sucessivamente ate percorrer todas as luzes. Note-se queo ultimo elemento da lista de comandos necessarios para passar de umaposicao a` outra e um L, ou seja, quando chega aos destinos que sao asluzes, estas sao ligadas.

    Esses comandos sao calculados atraves de caminhos, i.e. uma lista de paresde posicoes em que a primeira posicao do par e a origem e a segunda e a proximaposicao. Note-se que a distancia do ponto de origem ao ponto seguinte e sempre1 e o movimento entre os dois e sempre possvel. A funcao responsavel por con-verter um caminho numa lista de comandos e a converte comandos que dadoum caminho (do tipo [(Pos,Pos)]) e a orientacao inicial e o tabuleiro, converteem lista de comandos necessarios a percorrer esse caminho.

    Entao, dadas duas posicoes como conseguimos obter um caminhovalido entre as duas?Os caminhos sao criados a partir de listas de posicoes consecutivas e acessveis aorobot atraves da funcao converte caminhos. E nesta parte que entra em acaoa funcao a est inspirada no algoritmo A* que calcula a lista de posicoes queformarao o caminho. Esta funcao nao faz mais que chamar a funcao a est auxcom um parametro predefinido que vai ser explicada depois de explicar o funci-onamento da funcao a est (nao confundir com a est).

    A funcao a est, dado um tabuleiro, uma posicao inicial, uma posicao pre-tendida, uma lista de posicoes percorridas pelo robot (que devera ser [ ] naprimeira iteracao da funcao), doravante conhecida como lista aberta, a lista deposicoes que o robot tem de percorrer para chegar a` posicao atual, doravanteconhecida como lista fechada e que tambem devera ser [ ] na primeira iteracao,

    5

  • esta funcao calcula as posicoes que o robot deve percorrer para chegar a` posicaopretendida a partir da inicial da seguinte forma:

    1. Se a posicao pretendida estiver na lista fechada, entao significa que ja sealcancou a posicao pretendida e o algoritmo termina. Senao, passa-se parao passo 2.

    2. Se nao existirem movimentos possveis a partir da posicao atual que naoestejam na lista aberta e na lista fechada, i.e. se nao existirem posicoesacessveis que ainda nao tenham sido percorridas, entao devolve a listacom as posicoes que o robot percorreu ate chegar a` poiscao onde esta(esta ultima posicao esta includa na lista). Note-se que nestes casos, oresultado nao e valido mas sera util para o caculo de um caminho validoatraves de outra funcao explicada mais a` frente.

    3. Caso hajam posicoes possveis que ainda nao tenham sido percorridas,adiciona-se a posicao atual a` lista aberta e e escolhida a posicao possvelque tem menor distancia (valor absoluto da diferenca dos valores das co-ordenadas) a` posicao objetivo para a nova posicao e adiciona-se a` lista fe-chada. E entao chamada recursivamente a funcao aplicada ao tabuleiro, a`nova posicao, a` posicao objetivo e a`s listas aberta e fechada alteradas. Estafuncao vai correr recursivamente ate ser encontrado um caminho possvelou 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 caminhopossvel. Ja no segundo, o resultado tera de ser tratado por uma funcao diferentepara que um caminho valido seja obtido.

    Passo agora a explicar a funcao a est aux que dado um tabuleiro, a posicaoinicial, a posicao pretendida e uma lista que corresponde a` lista aberta:

    Se a funcao a est encontrou um caminho da posicao inicial ate a` preten-dida (i.e. se a posicao pretendida faz parte da lista de posicoes calculadas),insere a posicao inicial na primeira posicao da lista de posicoes resultanteda funcao a est e o algoritmo acaba, sendo que o resultado pode ser agoratrabalhado pela funcao converte caminhos;

    Caso contrario, vai ser calculado recursivamente, ate obter uma solucao,o resultado da funcao a est aplicada aos mesmos pontos e tabuleiro masem que a lista aberta contem a ultima posicao do resultado anterior, fun-cionando como uma restricao sobre os movimentos possveis na proximavez que executar a funcao.

    6

  • Usando o algoritmo descrito em acima conseguimos resolver todos os casosde teste que concebemos e conseguimos tambem obter 20 pontos na avaliacaodo mooshak.

    2.5 Tarefa E

    Nesta tarefa, foi-nos proposto criar um programa que dado um input (cons-titudo pelo tabuleiro, estado inicial e lista de comandos), gera o codigo de umdocumento html onde e possvel visualizar o tabuleiro em 3D usando a fra-mework X3DOM.

    Para tal, definimos 3 listas de Strings que vao ser comuns a todos os docu-mentos html:

    cabecalho - Esta parte do codigo e responsavel pela importacao das bibli-otecas necessarias ao funcionamento do X3DOM e a` definicao de outrascaractersticas da pagina html;

    pontos - Parte do codigo responsavel pela definicao das shapes que vaoformar o tabuleiro e da forma do robot;

    fim - parte burocraticanecessaria ao documento para que a estrutura dapagina esteja correta;

    Dado um input, a funcao tarefa vai juntar estas listas de strings comuns atodos os documentos com as partes varaveis. Estas partes variaveis sao geradaspela funcao geraHtml, que cria o codigo referente ao tabuleiro, e pela gerAnim,que cria o codigo responsavel pela animacao do robot.

    A funcao geraHtml recebe uma lista de triplos em que os dois primeiroselementos sao do tipo Int e o terceiro e um Char. O formato desta lista coincidecom o resultado da funcao processa que dado um tabuleiro , devolve uma listade triplos em que os dois primeiros elementos sao uma posicao do tabuleiroe o terceiro e a letra correspondente a` posicao. Na funcao tarefa, a funcaogeraHtml e passada com o argumento que e o resultado da funcao processaaplicada ao tabuleiro que esta no input.

    A funcao geraHtml aplicada a uma lista do tipo [(Int, Int, Char)] aplicaa todos os elementos da lista a funcao aux que funciona da seguinte forma:

    1. Se a altura da posicao atual for 0, se houver uma luz naquela posicao entaogera o codigo html responsavel por criar um paralelpipedo amarelo, quesimboliza a existencia de luz. Se nao houver uma luz, entao gera o codigohtml responsavel por criar um paralelpipedo azul, que indica que naoexiste uma luz naquela posicao. Depois a funcao termina.

    2. Caso contrario, se a posicao que queremos gerar corresponde a uma luz eesta no topo do tabuleiro, i.e. nao existem paralelippedos gerados acimado atual entao e gerado um paralelpipedo amarelo e chama-se a funcaoaux para gerar as shapes que deverao ficar abaixo da que foi gerada agora.

    7

  • 3. Se nenhuma das condicoes anteriores se verificar, entao gera-se a shapecorrespondente a` posicao sem luz para a altura atual e calcula-se as res-tantes shapes que deverao ficar abaixo chamando recursivamente a funcaoaux.

    Desta forma, e criado o tabuleiro todo. Para gerar o robot e as animacoescorrespondentes, usamos a funcao gerAnim. Esta funcao recebe o input dafuncao tarefa e devolve o codigo html com a estrutura necessaria ao funciona-mento das animacoes e define a duracao da animacao, as posicoes por onde devepassar o robot, os tempos em que devem ser executadas animacoes e rotacoes ede quantos graus devem ser essas rotacoes.

    A duracao da animacao e diretamente proporcional ao numero de comandospassados ao robot e os valores da key da PositionInterpolator (mecanismoresponavel por gerar as translacoes do robot) sao obtidos adicionando sempre1 dividido pelo comprimento da lista de comandos ao valor anterior, enquantoque este e menor que 1. As posicoes para a keyValue sao obtidas atravesda funcao posicoes que dado o estado inicial, a lista de comandos a execu-tar e o tabuleiro cria uma string com todas as posicoes por onde o robot devepassar. Os valores para a key da orientationInterpolator (mecanismo res-ponsavel pelas rotacoes do robot) sao obtidos filtrando os valores da key daPositionInterpolator em que ocorre uma rotacao, i.e. e executado um co-mando D ou E e os valores para a keyValue sao obtidos atraves da aplicacaodas rotacoes a` orientacao original atraves da funcao lista angulos.

    Desta forma, a funcao tarefa gera-se a representacao visual do tabuleiro.Note-se que o mooshak atribui Presentation Error a` nossa tarefa E, no en-

    tanto a estrutura do html e valida e a representacao grafica do tabuleiro funcionacorretamente.

    2.6 Makefile e runtests.sh

    Quando e executado o programa make, os programas das diferentes tarefa vaoser compilados e vao ser corridos varios testes atraves do script runtests.shque esta na pasta tests. Depois e gerada a documentacao haddock na pasta doce o relatorio e convertido para pdf.

    O script runtests.sh verifica se existe um ficheiro com extensao .out e sehouver, compara o conteudo desse ficheiro com o output da tarefa a ser testadae se forem iguais, e imprimida uma string que confirma que o teste teve umresultado correto. Caso contrario, e imprimida uma mensagem de erro.

    Se nao existir um ficheiro com extensao .out entao, se o ficheiro correspondera um ficheiro de testes da tarefa E, e gerado o ficheiro html com a visualizacaodo tabuleiro. Se o ficheiro for um teste da tarefa D entao e criado um ficheirocom extensao .res que contem os dados do ficheiro original mais o resultadoda tarefa D e calcula-se o output desse ficheiro pela tarefa C e guarda-se numficheiro com extensao .out. Se existir a palavra FIMno ficheiro devolvidoentao o teste e bem sucedido. Caso contrario da erro. No fim, os ficheiros comextensao .out e .res sao eliminados.

    8

  • Se o ficheiro de teste nao for nem da tarefa D nem da E entao o teste eignorado.

    3 Conclusao

    Este projeto foi uma experiencia verdadeiramente enriquecedora uma vez quefoi a primeira ves que fomos expostos ao desenvolvimento de um projeto desoftware do incio ao fim.

    Durante o desenvolvimento deste projeto utilizamos maioritariamente aquiloque nos foi lecionado nas aulas de Laboratorios de Informatica e ProgramacaoFuncional mas por vezes tivemos de recorrer a outras tecnicas e conhecimentosnao lecionados principalmente na implementacao das animacoes na tarefa E eno algoritmo de path-finding da tarefa D.

    Ao longo do trabalho encontramos varios obstaculos e desafios, alguns delesbastante dificeis de superar, como por exemplo, alcancar os 20 pontos na tarefaD, mas conseguimos fazer tudo a que nos propusemos e consideramos que fizemosum bom trabalho, certamente acima da media.

    9