Sei sulla pagina 1di 23

Universidade Federal de So Joo Del Rei Cincia da Computao

Trabalho Prtico 2: Algoritmos para Resoluo de Sudokus

Fernando H. C. Tavares de Lima Walkiria K. Resende Professor Leonardo Rocha

SO JOO DEL REI MG 01/05/2010


1-23

SUMRIO Introduo............................................................................... Proposta de trabalho.............................................................. Formatos de entrada/sada.................................................... Soluo apresentada............................................................. Fluxograma do Algoritmo...................................................... O Algoritmo............................................................................. Listagem de rotina e anlise de suas complexidades........ Testes e resultados................................................................ Concluso............................................................................... Como executar o programa................................................... Bibliografia.............................................................................. 3 4 6 7 9 10 12 15 23 23 23

2-23

INTRODUO
O Sudoku, como conhecido hoje, teve origem nos EUA em meados de 1970, e atingiu um enorme sucesso no Japo, onde a palavra Sudoku significa manter os dgitos nicos. No ocidente o jogo demorou a tornar-se popular, e s passou a ser publicado, em Londres, em 2004, chegando efetivamente ao Brasil, apenas em 2005. Como prova do sucesso alcanado pelo jogo, atualmente, existem revistas que publicam apenas Sudokus, jornais que trazem o jogo como passa tempo, e so realizados, tambm, campeonatos mundiais de Sudoku, nos quais os vencedores recebem prmios em dinheiro. Outra prova do sucesso foi a criao do Al Escargot, Sudoku mais difcil de ser resolvido em seu tempo de criao; obra de um matemtico finlands que levou 3 meses e milhes de combinaes para concluir o trabalho. O objetivo do jogo preencher todos os quadrados com nmeros de 1 a 9, onde eles devem ser diferentes nas colunas, nas linhas e nos grids, que so quadrados 3x3 dentro da matriz maior 9x9. At o momento, sabe-se que o mnimo de casas preenchidas para gerar um Sudoku com soluo nica 17, e, o mximo que casas possvel preenchidas para no garantir uma soluo nica 77. Existem diversas maneiras de solucionar o problema, assim como existem variaes nos nveis de dificuldade. Como inmeros jogos podem possuir softwares para resoluo, o trabalho aqui documentado apresenta duas formas de solucionar o jogo atravs de um programa de computador escrito em linguagem C. Observe que no um programa para jogar Sudoku, mas sim um programa que recebe qualquer Sudoku e apresenta a soluo. Uma das formas a partir da fora bruta, ou seja, o algoritmo deve trabalhar testando um grande nmero de possibilidades at encontrar a soluo correta. Esta uma soluo invivel, e foi aqui implementada, apenas, para fins didticos. A outra forma uma heurstica, que deve trabalhar o menos possvel para encontrar a soluo correta.

3-23

PROPOSTA DE TRABALHO
Este trabalho tem, por objetivo, exercitar os conceitos relacionados a problemas NP-Completos e aos paradigmas de projetos de algoritmos. Voc trabalha na Ximguiling Entertainment Games Inc., uma importante empresa multinacional da rea de jogos eletrnicos. O presidente da Ximguiling, senhor Michiu, com a inteno de motivar e avaliar seus funcionrios lanou um desa_o na empresa, um concurso de algoritmos para resolver probleminhas de Sudoku. Segundo Michiu, o funcionrio que conseguir desenvolver o algoritmo mais rpido, ou seja, aquele que obtm a soluo de um Sudoku em menor tempo, ter um aumento salarial de 300% e se tornar o vice-presidente da empresa. A palavra Sudoku significa nmero sozinho em japons, o que mostra exatamente o objetivo do jogo. O Sudoku existe desde a dcada de 1970, mas comeou a ganhar popularidade no final de 2004 quando comeou a ser publicado diariamente na sesso de puzzles do jornal The Times. Entre abril e maio de 2005 o puzzle comeou a ganhar um espao na publicao de outros jornais britnicos e, poucos meses depois, ganhou popularidade mundial. O objetivo do Sudoku preencher todos os espaos em branco do quadrado maior, que est dividido em nove grids, com os nmeros de 1 a 9. Os algarismos no podem se repetir na mesma coluna, linha ou grid.

Figura 1: Exemplo Sudoku Assim, para esse trabalho, elabore duas estratgicas para solucionar problemas de Sudoku: 1. Utilizando um algoritmo fora bruta; 2. Utilizando alguma heurstica prpria. O programa deve receber dois parmetros pela linha de comando, utilizando a primitiva getopt: 1. arquivo contendo as configuraes inicial do Sudoku a ser resolvido; 2. arquivo onde o resultado do Sudoku do arquivo de entrada dever ser gravado; Para o exemplo da figura acima, o arquivo de entrada seria como apresentado abaixo: onde o v representa uma casa vazia. 4-23

vv1 8vv 3vv v49 716 v8v v2v v9v vvv vv4 vvv v2v v56 vv1 8vv v1v vvv 5v9 vvv vvv 43v vvv 16v vv8 7vv vv2 vv1 O arquivo de sada dever ser como o arquivo de entrada, obviamente substituindo os v pela solues. OBS.: Com o objetivo de facilitar a manipulao de dados foi definido que os v do arquivo de entrada ser substitudo por 0.

5-23

FORMATOS DE ENTRADA/SADA
Conforme a proposta de trabalho, a entrada de dados ocorre atravs de um arquivo que contm um Sudoku a ser resolvido e a sada de dados feita pela impresso na tela e gravao da soluo do Sudoku no arquivo. Foram desenvolvidas funes de leitura e escrita em arquivo, as quais dependem da funo getopt() para ler o arquivo. Por motivos de organizao do projeto, foi estabelecida uma condio que impe a utilizao de um parmetro de leitura do arquivo do Sudoku (-a) e outro parmetro de leitura para o arquivo que ser gravada a soluo(-b). Caso estas imposies no sejam atendidas, sero impressos na tela os parmetros a serem utilizados e quais os devidos tipos de arquivos referentes a cada parmetro. A organizao do arquivo de entrada do Sudoku deve conter a seguinte representao: 070 003 028 009 600 100 010 029 063 084 700 006 167 000 584 900 006 210 830 260 070 001 004 800 740 300 050 Obs.: Os nmero so separados por espao e os grids por um Tab ou, ento, um Enter. Solucao: --------------------------| 4 7 6| 1 5 3| 9 2 8 | | 3 2 9| 6 8 7| 1 4 5 | | 5 1 8| 4 2 9| 7 6 3 | --------------------------| 2 8 4| 7 1 5| 3 9 6 | | 1 6 7| 9 3 2| 5 8 4 | | 9 5 3| 8 4 6| 2 1 7 | --------------------------| 8 3 5| 2 6 1| 4 7 9 | | 6 9 1| 5 7 4| 8 3 2 | | 7 4 2| 3 9 8| 6 5 1 | ---------------------------

6-23

SOLUO APRESENTADA
1. Tipos abstratos de dados
Foi implementada uma matriz por alocao dinmica, a qual possui 9 linhas e 9 colunas, cujos ndices variam de 0 a 8.

2. Mtodos de resoluo do Sudoku


Para melhor compreender o funcionamento do algoritmo utilizaremos a noo de casas vizinhas, onde, se uma casa est ao lado da outra, ento, estas so vizinhas, e, se uma casa est na ultima coluna, ento, esta vizinha da primeira casa da linha seguinte. Alm disso, o algoritmo utiliza duas matrizes, sendo que, uma matriz a que armazena o Sudoku original e a outra a matriz de testes. importante ressaltar que a matriz de testes, na primeira execuo, ser igual ao Sudoku original.

2. 1 Resolvendo o Sudoku pela heurstica


Com o objetivo de resolver o Sudoku rapidamente, o mtodo de backtracking foi o escolhido pela dupla, visto que, este muito referenciado como a melhor forma de solucionar este problema. Para implementar o backtracking, foi necessrio desenvolver funes para verificar se, ao inserir um elemento em uma devida posio na matriz, o mesmo causaria uma quebra das regras do jogo. O algoritmo do backtracking se baseia em verificar se um valor - iniciando de 1 (um) - pode ser inserido em uma posio cujo Sudoku original contm 0; caso esse valor seja vlido, ento a posio de teste receber esse valor e o teste se repetir de forma recursiva para o elemento vizinho posterior. Se no for possvel inserir um valor em uma posio, este valor ser incrementado e o teste ser refeito sobre o novo valor. E esse processo se repete at que se encontre um valor possvel ou at testar todos os valores de 1 a 9. Se ao chegar a 9 e, mesmo assim, no encontrar um valor possvel, o algoritmo faz um retorno da funo at chegar ao vizinho anterior e, ento, incrementa-o e continua os processos descritos anteriormente, at que se chegue ltima posio do Sudoku. E, ento, finalmente, a soluo encontrada, impressa e gravada em um arquivo, e o programa fechado. Esse mtodo de resoluo do Sudoku apesar de simples extremamente rpido e garante 100% de preciso no resultado.

2.2 Resolvendo o Sudoku pela fora bruta


Para resolver o Sudoku por fora bruta, foi desenvolvido um algoritmo recursivo que testa todas as possibilidades de preenchimento das casas vazias de um Sudoku. A funo forcabruta() chamar a funo recursiva testaFB() na casa (0,0). A funo testaFB() far as seguintes verificaes: 1) Se o elemento da casa em anlise for diferente de zero (0) no Sudoku original, ser feita uma verificao para saber se foi encontrada uma soluo. Se isto acontecer, esta ser impressa e salva e, aps isto, o programa terminar. 7-23

Caso contrrio, ser feita uma chamada da funo testaFB() no vizinho posterior. Se a funo retornar da recurso, ento, essa recurso terminar. 2) Se o elemento da casa em anlise for igual zero (0) no Sudoku original, ser executado um lao aninhado que vai da casa em teste at a ltima casa do Sudoku. Dentro do lao aninhado, a posio em teste ser incrementada e, ento, ser feita uma verificao para saber se foi encontrada uma soluo. Se isto acontecer, esta ser impressa e salva e, aps isto, o programa terminar. Caso contrrio, ser feita uma chamada da funo testaFB() no vizinho posterior. Se a funo retornar da recurso, ento, verificar se a posio em teste tem valor igual a 9 (nove). Se for, esta passar a ser 1 (um) e a funo retornar. Caso contrrio, a funo finalizar o lao interno e, ento, retornar. Estes processos terminaro, apenas, quando a soluo for encontrada. Na prtica, a funo preencher todas as casas vazias com 1 (um) e, partindo do canto inferior direita, ir incrementar as casas que, na matriz original, possuem 0. Este processo acontecer at que a soluo seja encontrada. importante ressaltar que esse algoritmo excessivamente devagar e, portanto, invivel para resolver um Sudoku, mas, ainda assim, um algoritmo que SEMPRE chega a uma soluo tima.

8-23

9-23

O ALGORITMO
Uma das formas mais comuns de resolver um Sudoku utilizar backtracking. Esta tcnica consiste em percorrer, sistematicamente, o Sudoku, da esquerda para a direita e de cima para baixo, at encontrar a soluo ou at encontrar um deadlock. Em caso de deadlock, a funo comea o backtracking (voltar atrs), que um procedimento que retorna pelo mesmo caminho percorrido, at encontrar um novo ponto de partida para continuar a sua execuo. Neste caso, a funo chegar a um ponto que pode ser incrementado e, a partir deste, ser possvel fazer novos testes e, ento, repetir o processo de procura pela soluo ou achar um deadlock para tentar outra vez. Fazendo uma observao importante, utilizamos o comando exit(0), este conhecido como sada aps obteno de sucesso e foi utilizado para agilizar o processo de finalizao do programa, visto que, com esse, o algoritmo diminui o tempo de processamento em at 5x, j que no precisa realizar o retorno das funes aps encontrar a soluo do Sudoku. Trecho do cdigo: void fazerTestes(int i, int j, int **matriz, int **copia, int k, char *b){ int possivel; if(copia[i][j]!=0){ if(j<8) fazerTestes(i, j+1, matriz, copia, 1, b); else if(i<8) fazerTestes(i+1, 0, matriz, copia, 1, b); else { imprimirMatriz(matriz); printf("\n"); gravarSolucao(b, matriz); matriz = desalocaMatriz(9, 9, matriz); /* Desaloca a Matriz */ copia = desalocaMatriz(9, 9, copia); /* Desaloca a Copia */ printf("\nContagem de Operaes: %d\n", cont); imprimirTempo(); exit(0); } } else{ possivel= verificarValidade(i, j, matriz, k); if(possivel ==1){ matriz[i][j] = k; if(j<8) fazerTestes(i, j+1, matriz, copia, 1, b); else if(i<8) fazerTestes(i+1, 0, matriz, copia, 1, b); else { imprimirMatriz(matriz); printf("\n"); gravarSolucao(b, matriz); matriz = desalocaMatriz(9, 9, matriz); /* Desaloca a Matriz */ copia = desalocaMatriz(9, 9, copia); /* Desaloca a Copia */ printf("\nContagem de Operaes: %d\n", cont); imprimirTempo(); exit(0); } } k++; if(k<=9) fazerTestes(i, j, matriz, copia, k, b); if(k==10) matriz[i][j]=0; } } 10-23

O algoritmo trata tambm do mtodo de fora bruta, o qual consiste em testar todas as possibilidades de valores para as casas at que se encontre uma soluo. Trecho do cdigo: void testaFB(int i, int j, int **matriz, int **copia, char *b){ int x, y, impossivel; if(copia[i][j] !=0){ impossivel= verificaImpossibilidade(matriz); if(impossivel ==0){ imprimirMatriz(matriz); printf("\n"); gravarSolucao(b, matriz); matriz = desalocaMatriz(9, 9, matriz); /* Desaloca a Matriz */ copia = desalocaMatriz(9, 9, copia); /* Desaloca a Copia */ printf("\nContagem de Operaes: %d\n", cont); imprimirTempo(); exit(0); } if(j<8) testa(i,j+1, matriz, copia,b); else if (i<8) testaFB(i+1,0, matriz, copia,b); } else{ for(x=i; x<9; i++){ for(y=j; y<9; j++){ matriz[x][y]++; impossivel= verificaImpossibilidade(matriz); if(impossivel ==0){ imprimirMatriz(matriz); printf("\n"); gravarSolucao(b, matriz); matriz = desalocaMatriz(9, 9, matriz); copia = desalocaMatriz(9, 9, copia); printf("\nContagem de Operaes: %d\n", cont); imprimirTempo(); exit(0); } if(y<8) testaFB(x,y+1, matriz, copia,b); else if (x<8) testaFB(x+1,0, matriz, copia,b); if(matriz[x][y]==9) { matriz[x][y] =1; return; } } } } }

11-23

LISTAGEM DE ROTINAS E ANLISE DE SUAS COMPLEXIDADES


void criarMatriz(int **matriz): uma funo que cria uma matriz de zeros. Esta funo possui dois laos aninhados e um comando interno de atribuio. Se os laos forem analisados como uma nica estrutura de repetio, esta ser executada n*n vezes, onde n o nmero de linhas e colunas. Portanto, possui a complexidade definida por n*n*O(1) = O(n). Complexidade: O(n). int **alocaMatriz(int m, int n): uma funo que faz a alocao dinmica da matriz. Esta funo possui um lao, uma chamada a funo criarMatriz() e uma sequncia de comandos com complexidades constante. Como o lao executado n vezes, onde n o nmero de linhas, e o restante das funes possui complexidade constante, temos que a complexidade dessa funo definida por: n*O(1); Complexidade: O(n). while((opt = getopt (argc, argv, "a:b:")) != -1): uma estrutura de repetio que tem como condio de parada a funo getopt() a qual receber dois parmetros: 1 (um) arquivo de entrada e 1 (um) arquivo de sada. Como as funes internas desta funo possuem complexidade O(1), sua complexidade [ 2*O(1)]. Complexidade: O(1). void carregarMatriz(char *arqMatriz, int **a): uma funo que carrega os dados do arquivo do Sudoku para a matriz. Esta funo possui 2 (dois) laos, sendo que, o externo executado apenas uma vez e o interno n vezes, onde n o nmero de linhas. E como os comandos internos possuem complexidade constante, a complexidade desta funo dada por: n*O(1). Complexidade: O(n). void imprimirMatriz(int **matriz): uma funo que imprime a matriz. Esta funo possui dois laos aninhados e um comando interno de atribuio. Se os laos forem analisados como uma nica estrutura de repetio, esta ser executada n*n vezes, onde n o nmero de linhas e colunas. Portanto, possui a complexidade definida por n*n*O(1) = O(n). Complexidade: O(n). void gravarSolucao(char *solucao, int **matriz): uma funo que grava o resultado do Sudoku em um arquivo. Esta funo possui 2 (dois) laos, sendo que o externo executado apenas uma vez e o interno n vezes, onde n o nmero de linhas. E como os comandos internos possuem complexidade constante, a complexidade desta funo dada por: n*O(1). Complexidade: O(n).

12-23

int **desalocaMatriz (int m, int n, int **matriz): uma funo que desaloca a matriz. Esta funo possui um lao e uma sequncia de comandos com complexidade constante. Como o lao executado n vezes, onde n o nmero de linhas, e o restante das funes possui complexidade constante, temos que a complexidade desta funo definida por: n*O(1); Complexidade: O(n). void imprimirTempo(): uma funo que imprime os tempos de usurio, sistema, total e real. Esta funo possui apenas comandos de complexidade constante, portanto, possui complexidade O(1). Complexidade: O(1). int verificarGrid(int i, int j, int **matriz, int valor); uma funo que verifica se uma posio vlida no grid. Esta funo possui 3 (trs) laos, sendo que, 2 (dois) destes so aninhados e juntos so executados n vezes, onde n o nmero de grids, e o outro lao possui apenas comandos constantes e executado n vezes em seu pior caso, onde n o nmero de elementos em um grid. Portanto, a complexidade desta funo dada por O (Max(n*O(1), n*O(1))). Complexidade: O(n). int verificarValidade(int i, int j, int **matriz, int valor); uma funo que verifica se uma posio vlida no Sudoku. Ou seja, se no infringe nenhuma regra do mesmo. Esta funo possui uma chamada para a funo verificarGrid(), comandos constantes e um lao que ser executado n vezes, onde n pode ser considerado o nmero de linhas ou de colunas. Portanto, a complexidade desta funo dada por O(Max(n*O(1),O(n))). Complexidade: O(n). int verificaImpossibilidade(int **matriz); uma funo que verifica se o Sudoku est resolvido. Esta funo possui 2 (dois) laos aninhados que, se analisados como uma nica estrutura, ser executados n*n vezes no seu pior caso. Estes laos contm uma chamada para a funo verificarValidade(). Portanto, a complexidade dessa funo dada por: n*n*O(n). Complexidade: O(n). void fazerTestes(int i, int j, int **matriz, int **copia, int k, char *b); Esta a funo que realiza os testes do backtracking e chega soluo do Sudoku. No conseguimos desenvolver essa anlise de complexidade. Complexidade: O (??). void backtracking(char *a, char *b, int **matriz, int **copia, double iniciotempo); a funo do backtracking. Como no sabemos a complexidade da funo fazerTestes(), no foi possvel definir a complexidade desta funo. Complexidade: O (??).

13-23

void testaFB(int i, int j, int **matriz, int **copia, char *b): uma funo que realiza os testes da forcaBruta e chega soluo do Sudoku. Esta funo possui laos, condies e recurso. Para definir sua complexidade vamos desconsiderar estas estruturas e basear no funcionamento da funo na prtica, a qual j foi explicada anteriormente. possvel perceber que um Sudoku, sem preencher, possui as seguintes possibilidades de preenchimento: 1 linha: 9! possibilidades 2 linha: 9! possibilidades 3 linha: 9! possibilidades 4 linha: 9! possibilidades 5 linha: 9! possibilidades 6 linha: 9! possibilidades 7 linha: 9! possibilidades 8 linha: 9! possibilidades 9 linha: 9! possibilidades Portanto, segue a equao de recorrncia a seguir: T(n) = 9! * T(n-1) T(n-1) = 9! * T(n-2) ... T(2) = 9! * T(1) T(1) = 9! Substituindo temos: 9!n. Portanto, temos que a complexidade desta funo da ordem de (cc)n. Complexidade: O ((cc)n). void forcaBruta(char *a, char *b, int **matriz, int **copia, double iniciotempo); a funo da fora bruta. Esta funo faz duas chamadas funo carregaMatriz() e uma testaFB(). Portanto, sua complexidade dada por: O(max(n,n,(cc)n)); Complexidade: O ((cc)n). int main (int argc, char *argv[]): a funo principal do programa. Esta funo possui uma sequncia de comandos de complexidade constante e uma chama a funo backtracking() ou forcaBruta(). A primeira no conseguimos calcular sua complexidade, porm a segunda possui complexidade O ((cc)n). Como a complexidade da forcaBruta() a maior, ento essa a complexidade da main(). Complexidade: O ((cc)n).

14-23

TESTES E RESULTADOS
Os Sudokus abaixo foram gerados pelo GNOME Sudoku 2.30.0 ou encontrados no site: http://www.fiendishSudoku.com/pt/Sudoku.html. Os testes foram realizados em uma mquina com a seguinte descrio: Hardware/Software Sistema operacional: Processador: Placa de Vdeo: RAM: Modelo Ubuntu 10.04 LTS 32bits Intel Core 2 Duo CPU T5670 1.80GHz Intel GMA X3100 3,00 GB, DDR2, 667MHz

1. Testes utilizando Backtracking


Sudoku Fcil 1: Tempo de usurio: Tempo de Sistema: Tempo Total: Tempo Real: 0.000 ms 0.004 ms 0.004 ms 0.741 ms

Contagem de operaes: 756 Sudoku Fcil 2: Tempo de usurio: Tempo de Sistema: Tempo Total: Tempo Real: 0.000 ms 0.000 ms 0.000 ms 0.809 ms

Contagem de operaes: 340 Sudoku Fcil 3: Tempo de usurio: Tempo de Sistema: Tempo Total: Tempo Real: 0.000 ms 0.004 ms 0.004 ms 0.362 ms

Contagem de operaes: 1596 Sudoku Fcil 4: Tempo de usurio: Tempo de Sistema: Tempo Total: Tempo Real: 0.004 ms 0.000 ms 0.004 ms 0.493 ms

Contagem de operaes: 975 Sudoku Fcil 5: Tempo de usurio: Tempo de Sistema: Tempo Total: Tempo Real: 0.000 ms 0.004 ms 0.004 ms 0.669 ms 15-23

Contagem de operaes: 729 Sudoku Mdio 1: Tempo de usurio: Tempo de Sistema: Tempo Total: Tempo Real: 0.004 ms 0.000 ms 0.004 ms 0.694 ms

Contagem de operaes: 4151 Sudoku Mdio 2: Tempo de usurio: Tempo de Sistema: Tempo Total: Tempo Real: 0.004 ms 0.000 ms 0.004 ms 0.322 ms

Contagem de operaes: 1433 Sudoku Mdio 3: Tempo de usurio: Tempo de Sistema: Tempo Total: Tempo Real: 0.000 ms 0.004 ms 0.004 ms 0.450 ms

Contagem de operaes: 2108 Sudoku Mdio 4: Tempo de usurio: Tempo de Sistema: Tempo Total: Tempo Real: 0.000 ms 0.000 ms 0.000 ms 0.319 ms

Contagem de operaes: 10373 Sudoku Mdio 5: Tempo de usurio: 0.004 ms Tempo de Sistema: 0.000 ms Tempo Total: 0.004 ms Tempo Real: 0.335 ms Contagem de operaes: 7780 Sudoku Difcil 1: Tempo de usurio: Tempo de Sistema: Tempo Total: Tempo Real: 0.000 ms 0.004 ms 0.004 ms 0.903 ms

Contagem de operaes: 8574

16-23

Sudoku Difcil 2: Tempo de usurio: Tempo de Sistema: Tempo Total: Tempo Real:

0.004 ms 0.000 ms 0.004 ms 0.861 ms

Contagem de operaes: 5928 Sudoku Difcil 3: Tempo de usurio: Tempo de Sistema: Tempo Total: Tempo Real: 0.004 ms 0.000 ms 0.004 ms 0.705 ms

Contagem de operaes: 3838 Sudoku Difcil 4: Tempo de usurio: Tempo de Sistema: Tempo Total: Tempo Real: 0.012 ms 0.000 ms 0.012 ms 0.253 ms

Contagem de operaes: 60549 Sudoku Difcil 5: Tempo de usurio: Tempo de Sistema: Tempo Total: Tempo Real: 0.004 ms 0.000 ms 0.004 ms 0.241 ms

Contagem de operaes: 21080 Sudoku Muito Difcil 1: Tempo de usurio: 0.016 ms Tempo de Sistema: 0.000 ms Tempo Total: 0.016 ms Tempo Real: 0.379 ms Contagem de operaes: 91137 Sudoku Muito Difcil 2: Tempo de usurio: 0.004 ms Tempo de Sistema: 0.000 ms Tempo Total: 0.004 ms Tempo Real: 0.384 ms Contagem de operaes: 59827

17-23

Sudoku Muito Difcil 3: Tempo de usurio: 0.012 ms Tempo de Sistema: 0.000 ms Tempo Total: 0.012 ms Tempo Real: 0.549 ms Contagem de operaes: 40146 Sudoku Muito Difcil 4: Tempo de usurio: 0.036 ms Tempo de Sistema: 0.000 ms Tempo Total: 0.036 ms Tempo Real: 0.338 ms Contagem de operaes: 308000 Sudoku Muito Difcil 5: Tempo de usurio: 0.000 ms Tempo de Sistema: 0.008 ms Tempo Total: 0.008 ms Tempo Real: 0.540 ms Contagem de operaes: 16568 Sudoku Extreme 1: Tempo de usurio: Tempo de Sistema: Tempo Total: Tempo Real: 0.044 ms 0.008 ms 0.052 ms 0.637 ms

Contagem de operaes: 505035 Sudoku Extreme 2: Tempo de usurio: Tempo de Sistema: Tempo Total: Tempo Real: 0.024 ms 0.004 ms 0.028 ms 0.677 ms

Contagem de operaes: 152659 Sudoku Extreme 3: Tempo de usurio: 0.116 ms Tempo de Sistema: 0.000 ms Tempo Total: 0.116 ms Tempo Real: 0.718 ms Contagem de operaes: 1372211

18-23

Sudoku Extreme 4: Tempo de usurio: Tempo de Sistema: Tempo Total: Tempo Real:

0.004 ms 0.000 ms 0.004 ms 0.449 ms

Contagem de operaes: 40945 Sudoku Extreme 5: Tempo de usurio: Tempo de Sistema: Tempo Total: Tempo Real: 0.060 ms 0.000 ms 0.060 ms 0.447 ms

Contagem de operaes: 729021 Sudoku Al Escargot: Tempo de usurio: 0.020 ms Tempo de Sistema: 0.000 ms Tempo Total: 0.020 ms Tempo Real: 0.381 ms Contagem de operaes: 83707 Sudoku O mais difcil: Tempo de usurio: 0.332 ms Tempo de Sistema: 0.004 ms Tempo Total: 0.336 ms Tempo Real: 0.743 ms Contagem de operaes: 4125542

19-23

Com base no grfico acima, conseguimos perceber a grande diferena no n de operaes entre os nveis mais dificis(Extreme e Mais dificil) e os outros nvel, visto que boa parte desses realizam menos que 50.000 operaes e a maioria dos mais difcieis ultrapassam a casa das centenas de milhar. Grfico de tempos de execuo

Atravs do grfico apresentado acima, percebemos que o aumento do nvel de dificuldade proporcional ao tempo total de execuo. Alm disso, vemos que no pior dos casos, o maior tempo atingido foi menor que 0,5 segundos. Nvel de Dificuldade Fcil Mdio Difcil Muito Difcil Extremo Al Escargot Sudoku mais difcil Mdia de Tempo Total 0.0032 ms 0.0032 ms 0.0056 ms 0.0152 ms 0.0520 ms 0.0200 ms 0.3360 ms

Pela tabela acima, possvel perceber que o mtodo de backtracking para resolver o Sudoku possui resposta em tempo real. Portanto, um programa que poderia facilmente ser utilizado em um jogo de Sudoku comercializado se fosse necessrio. Confirmando assim, a importncia de utilizar heursticas para solucionar problemas com complexidade similares a NP-completos. possvel ver que os tempos reais de execuo so bem maiores que o tempo total de execuo do programa, isso se ocorre por que necessrio computar o tempo de resposta do usurio ao menu que escolhe qual o mtodo utilizado para resolver o sudoku. Caso este no existisse, o tempo real seria poquissmo maior ou igual ao tempo total. 20-23

2. Testes utilizando Fora Bruta


Foi realizado um teste com durao de 12hrs para resolver o Sudoku Fcil 5 por fora bruta. Infelizmente, no foi possvel obter a soluo, mais uma vez, provando quo invivel a utilizao desta tcnica. Porm, para fins de anlise, decidimos fazer reduzindo bastante o nmero de casas vazias, para assim, poder demonstrar, explicitamente, a lentido de um mtodo de resoluo por fora bruta. Soluo Sudoku Fcil 5: 4 6 9 2 1 8 7 5 3 I 3 8 1 IV 5 4 7 VII 6 9 2 2 7 5 9 6 3 8 1 4 8 1 3 4 2 9 5 6 7 II 6 9 2 V 7 8 5 VIII 4 3 1 5 4 7 6 3 1 2 8 9 9 2 4 3 5 6 1 7 8 III 1 3 6 VI 8 7 2 IX 9 4 5 7 5 8 1 9 4 3 2 6

Para facilitar a explicao, utilizamos algarismos romanos para representar os grids. O teste da fora bruta consiste em 2 fases: 1) Retira-se o 9 (nove) do grid I e realiza o teste. Em seguida, retira-se o 9 do grid II e realiza o teste. Repete-se esse processo at que o teste seja feito para o grid IX, ou seja, at que o teste seja feito o Sudoku com todos os 9 (nove) faltando para completar o Sudoku. 2) Retira-se o 9 (nove) do grid IX e realiza o teste. Em seguida, retira-se o 9 do grid VIII e realiza o teste. Repete-se esse processo at que o teste seja feito para o grid I, ou seja, at que o teste seja feito o Sudoku com todos os 9 (nove) faltando para completar o Sudoku.

1 Fase:
9 (Nove) faltando 1 2 3 4 5 6 7 8 9 Tempo de Usurio 0.004ms 0.012ms 0.028ms 0.156ms 0.804ms 5.996ms 25.254ms 61.180ms 473.938ms Tempo de Sistema 0.000ms 0.004ms 0.008ms 0.004ms 0.000ms 0.004ms 0.016ms 0.076ms 0.612ms Tempo de Total 0.004ms 0.016ms 0.036ms 0.160ms 0.804ms 0.004ms 25.270ms 61.256ms 474.550ms 21-23

2 Fase:
9 (Nove) faltando 1 2 3 4 5 6 7 8 9 Tempo de Usurio 0.004ms 0.008ms 0.028ms 0.108ms 0.676ms 4.748ms 11.561ms 76.709ms 471.645ms Tempo de Sistema 0.000ms 0.000ms 0.000ms 0.004ms 0.008ms 0.012ms 0.020ms 0.096ms 0.528ms Tempo de Total 0.004ms 0.008ms 0.028ms 0.112ms 0.684ms 4.388ms 11.581ms 76.805ms 472.174ms

Analisando as duas fases, conseguimos perceber que os tempos da 1 Fase so relativamente maiores que os 2, com exceo do ltimo (faltando 9) e penltimo (faltando 8). No ltimo, sabemos que o mesmo teste, portanto, o tempo quase o mesmo. No penltimo, os resultados so bem distinto, e, ainda, uma coisa incomum ocorre: o tempo da 1 Fase menor que o da 2. Mas porque isto ocorre? Simples. Pela forma que o algoritmo foi implementado. Como o algoritmo faz a busca de trs para frente e de baixo para cima, o tempo para resolver um Sudoku com elementos sem preencher nos ltimos grids (2 Fase) mais rpido que o tempo de resolver um Sudoku com elementos sem preencher nos primeiros grids (1 Fase). Porm, no caso do penltimo teste isso no ocorre, pois quando apenas o grid IX est preenchido com o 9, o algoritmo faz recurses indo desde o grid IX at o grid I. Mas, no caso de apenas o grid I estar preenchido com 9, o algoritmo faz recurses indo desde o grid XI at o grid II, j que no grid 9 todos os nmeros esto preenchidos. Aps isso, conseguimos definir que o tempo para resolver esse algoritmo depende no apenas no nmero de casas que faltam preencher, mas tambm em qual grid essas casas sem preencher esto.

22-23

CONCLUSO
Neste trabalho aprofundamos ainda mais nossos conhecimentos sobre programao e iniciamos uma nova fase, a qual lida com problemas reais NP-completos, como o famoso jogo japons Sudoku. Por meio deste, conseguimos perceber que para solucionar um problema de tamanha complexidade preciso conhecer tcnicas que realizem o menor nmero de comparaes possveis e cheguem a uma soluo de forma gil. Por isso utilizamos um dos paradigmas de projetos de algoritmos: Backtracking. Conforme proposto, implementamos nesse trabalho um algoritmo de heurstica prpria e um algoritmo de fora bruta. No backtracking, criamos um algoritmo recursivo que analisa os valores possveis de uma casa e, a partir deste, procura uma soluo para o Sudoku, porm, se no meio desta procura encontrar um deadlock, ser preciso realizar o backtracking (voltar atrs) para fazer um novo teste, satisfazendo assim, o mtodo de um algoritmo de backtracking, o qual consiste no princpio da tentativa e erro. Esse algoritmo bastante gil para solucionar um Sudoku, visto que, com base nos testes realizados, no chega a atingir 1 segundo no tempo para encontrar uma soluo. O algoritmo de fora bruta realiza todos os testes possveis para as posies vazias, j que consiste em fazer uma busca cega pela soluo. Infelizmente, no houve tempo para desenvolver uma fora bruta com um filtro de possibilidades bvias, por este motivo, esse algoritmo no considerado vivel para solucionar um Sudoku, mas um mtodo capaz, logicamente, de encontrar a soluo, mesmo que para isso demore alguns anos. Fazemos uma ressalva, na qual dizemos que nosso algoritmo limitado a Sudokus padro (9x9), portanto, no tem utilidade na resoluo de outras verses.

COMO EXECUTAR O PROGRAMA


Com a finalidade de facilitar a execuo, sero disponibilizados na pasta /TP2/Sudokus vrios exemplos de Sudokus. Para juntar os mdulos do projeto e compil-los foi desenvolvido um Makefile. Portanto, para compilar o trabalho preciso entrar na pasta /TP2/codigo/ e digitar o seguinte comando: make Aps a compilao, para executar o programa no terminal, preciso digitar: ./TP2 a arquivo_do_sudoku_original b arquivo_para_grava_a_soluo Para fazer uma limpeza no projeto compilado digite: make clean

Bibliografia
http://www.fiendishSudoku.com/pt/Sudoku.html http://pt.wikipedia.org/wiki/Sudoku http://www2.uol.com.br/sciam/reportagens/a_ciencia_do_sudoku.html

23-23

Potrebbero piacerti anche