Comparando os comandos de input
em 14 de Julho de 2014
Nas nossas duas últimas não muito emocionante aventuras, nós vimos como resolver o sudoku e como lemos um arquivo de sudoku.
Agora, vamos finalmente resolver o sudoku!
Se você se lembra de como resolver o sudoku, nós vamos, basicamente, chutar os números! Então, precisamos de um jeito para ver se o número chutado pode ficar no quadrado onde a gente o colocou ou não.
Para isso, precisamos ver se não há o mesmo número na linha, na coluna ou no "sub-quadrado" em que o colocamos, ou seja, sem repetir o mesmo número.
Vamos fazer isso por partes. Primeiro, vamos checar a linha. Cada elemento da tabela que representa o sudoku tem dois índices, i e j, certo? O índice i é a linha e o j é a coluna. Logo, a linha da posição ij é a linha i! Vamos fazer uma função que olha todos os elementos da linha i e comparamos com o número que a gente chutou para o elemento ij. Se algum for igual, nós vamos retornar true, ou seja, achamos um conflito!
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Nessa função, nós olhamos todos os elementos da linha i, usando a variável coluna para marcar cada um. Só temos que ter cuidado para não olhar a coluna j, já que sempre teríamos um conflito!
Agora, vamos fazer o mesmo para checar se há um conflito na mesma coluna de ij. Como j é a coluna, basta olharmos todas as linhas!
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Agora precisamos olhar o subquadrado! Isso é um pouco mais chato, já que dependendo da posição ij do elemento, o subquadrado varia!
O jeito que eu acho mais fácil para olhar o subquadrado é assim: nós identificamos cada um deles pela posição do primeiro elemento da primeira linha de cada um: (0,0) para o primeiro, (0,3) para o segundo da primeira linha, (0,6) para o terceiro e, depois, (3,0) para o primeiro da segunda linha até chegarmos no quadrado (6,6).
Como fazemos para identificar esse elemento? É simples! Nós, primeiro, dividimos i e j por 3. Depois, nós multiplicamos por 3!
Você tem que lembrar que, em C++, divisão funciona como a divisão da quarta série: 7 dividido por 3 dá 2 e sobra 1, certo? Logo, 7 dividido por 3, e depois vezes 3, dá 6! Fazendo isso, a gente sempre acha o quadrado certo!
O que nós vamos fazer então é, dada nossa posição ij, encontrar qual o primeiro elemento do subquadrado que o ij está. Depois, nós olhamos os 9 elementos desse subquadrado (com cuidado para ignorar o ij!) e vemos se achamos o erro.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
Agora, só precisamos juntar essas 3 funções de verificar para ver se o número que chutamos pode ou não ficar no lugar que o colocamos! Como um conflito (dentre os 3 possíveis) já ferra tudo, podemos simplesmente ver se algum deles retornou verdadeiro:
1 2 3 4 5 |
|
Pronto!
Nós precisamos mudar um pouco a função que lê nosso sudoku, porque precisamos guardar uma lista das posições ij da tabela que não são fixas, ou seja, que devemos preencher.
Para isso, vamos usar um vector do C++. Ela vai guardar pares, também do C++, que vão ter dois números, o i e o j (eu não vou usar listas porque não quero usar iteradores XD).
A única coisa que precisamos mudar na nossa função de leitura é que, toda vez que acharmos um 0, que representa um buraco, nós guardamos o par ij na nossa lista de vazios.
1 2 3 4 5 6 7 8 9 10 11 |
|
Como eu disse, a única diferença é que quando lemos um 0 na posição ij nós colocamos na nossa lista de vazios o par ij.
Agora nós temos tudo que precisamos, finalmente, para resolver o sudoku!
Para resolver, vamos fazer assim: nós pegamos o primeiro par ij na nossa lista de vazios e colocamos o número 1 nele. Depois checamos se aconteceu algum conflito: se estiver tudo bem, nós pegamos o próximo cara da lista e colocamos 2 e assim por diante. Se tivermos um conflito, somamos 1 no cara ij. Caso nós sejamos muito azarados, algum par ij não vai poder ser preenchido com nenhum número até 9. Mas não se desespere! Basta nós voltarmos para o cara anterior e aumentarmos ele em um! Nós repetimos isso até conseguir colocar algum número no último cara da lista de vazios!
Finalmente, nossa função resolve!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
Só falta escrevermos nossa função main:
1 2 3 4 5 6 7 8 9 10 11 |
|
E pronto! Espero que você tenha gostado e aprendido que, às vezes, a solução mais porca é suficiente!
Mais uma vez, o código está aqui.