-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
132 lines (101 loc) · 3.6 KB
/
main.cpp
File metadata and controls
132 lines (101 loc) · 3.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include <iostream>
#include <utility>
#include <vector>
#include <string.h>
using namespace std;
const char GRID_SIZE = 3;
const unsigned DIGITS = GRID_SIZE * GRID_SIZE;
bool visited[9];
enum MOV_TYPE {DIRECT, REQUIRES_INTERMIDIATE, INVALID};
pair<int, int> getCoords(int number) {
return make_pair<int,int>(number/GRID_SIZE, number%GRID_SIZE);
}
int getNode(pair<int,int> coords) {
int node = 0;
node += coords.first * GRID_SIZE;
node += coords.second;
return node;
}
//Subtração entre pairs
pair<int,int> operator-(pair<int,int> a, pair<int,int> b) {
return make_pair(a.first - b.first, a.second - b.second);
}
//Divisão inteira de pairs por ints
pair<int,int> operator/(pair<int,int> a, int b) {
return make_pair(a.first/b, a.second/b);
}
//Soma de pairs
pair<int,int>operator+(pair<int,int> a, pair<int,int> b) {
return make_pair(a.first + b.first, a.second + b.second);
}
MOV_TYPE classifyMovement(pair<int,int> diff) {
int absFirst = abs(diff.first);
int absSecond = abs(diff.second);
int absDiff = abs(absSecond - absFirst);
if (absDiff == 1) //Casos: 01 10 21 12
return DIRECT;
if (absFirst == 1 and absSecond == 1) //11
return DIRECT;
if (absFirst == 2 and absSecond == 2) //22
return REQUIRES_INTERMIDIATE;
if (absFirst == 0 and absSecond == 0) //00
return INVALID;
if (absDiff == 2) //02 ou 20
return REQUIRES_INTERMIDIATE;
return INVALID;
}
int soma = 0;
void nextNode(int digitos, int atual) {
if (digitos == 0) {
++soma;
return;
}
//Define o nó atual como visitado (até o fim desse nível recursivo)
visited[atual] = true;
//Calcula as coordenadas e distâncias dos nós atual e prox
pair<int, int> atualCoords = getCoords(atual);
pair<int, int> proxCoords;
pair<int, int> diff;
for (int prox = 0; prox < 9; prox++)
{
//Se o prox já foi visitado, não tem mágica
if (visited[prox]) continue;
//Calcula as coords e diff para cada prox
proxCoords = getCoords(prox);
diff = proxCoords - atualCoords;
//Checa se o movimento é válido, inválido ou requer visita prévia ao nó intermediário
MOV_TYPE movType = classifyMovement(diff);
if (movType == INVALID) continue;
if (movType == REQUIRES_INTERMIDIATE) { //Se o movimento precisar de um nó intermediário:
//Obtém as coordenadas do ponto que precisa ter sido visitado (nó intermediário)
auto requiredNodeCoords = atualCoords + (diff / 2);
int requiredNode = getNode(requiredNodeCoords);
//Se não tiver sido visitado, o movimento é inválido
if (!visited[requiredNode]) continue;
//Senão ele executa a linha abaixo fora do if
}
nextNode(digitos - 1, prox);
}
//Saindo do nível atual de recursão, ainda não foi visitado
visited[atual] = false;
}
int main(int argc, char const *argv[])
{
// memset(visited, false, sizeof(bool) * DIGITS);
int somaTotal = 0;
//Determina o tamanho da senha
for (int digitos = 4; digitos <= 9; digitos++)
{
//Escolhe o primeiro nó
for (int inicio = 0; inicio <= 8; inicio++)
{
//Calcula o numero de senhas com o inicio definido e soma na var global soma
nextNode(digitos-1, inicio);
}
cout << "Senhas com " << digitos << " dígitos: " << soma << endl;
somaTotal += soma;
soma = 0;
}
cout << "Total de senhas: " << somaTotal << endl;
return 0;
}