1
+ /*
2
+ L'entrée représente une grammaire, un peu comme dans l'algorithme CYK (Cocke-Younger-Kasami)
3
+ À la fin, une chaîne de caractères est fournie sur laquelle nous allons travailler.
4
+
5
+ Dans la Partie 1, l'objectif est de compter le nombre de combinaisons possibles sur la chaîne d'entrée en fonction de
6
+ la grammaire.
7
+ Exemple avec la chaîne "HOH":
8
+
9
+ La grammaire de l'entrée:
10
+ e => H
11
+ e => O
12
+ H => HO
13
+ H => OH
14
+ O => HH
15
+
16
+ Il y a 5 combinaisons possibles après une modification de la chaîne d'origine, dont 4 uniques :
17
+ HOOH (H => HO sur le premier H)
18
+ HOHO (H => HO sur le second H)
19
+ OHOH (H => OH sur le premier H)
20
+ HOOH (H => OH sur le second H)
21
+ HHHH (O => HH sur le premier O)
22
+
23
+ Dans la Partie 2, l'objectif est de compter le nombre d'étapes nécessaires en partant de la chaîne "e" pour arriver à
24
+ la chaîne d'entrée.
25
+
26
+ Par exemple, en reprenant la grammaire d'entrée ci-dessus, il nous faudrait 3 étapes en partant de "e" pour arriver à
27
+ "HOH":
28
+ [e => O] => O
29
+ [O => HH] => HH
30
+ [H => HO] => HOH
31
+ */
32
+ #include < algorithm>
33
+ #include < fstream>
34
+ #include < iostream>
35
+ #include < map>
36
+ #include < set>
37
+ #include < string>
38
+ #include < vector>
39
+
40
+ #include < Utils/MeasureExecutionTime.cpp>
41
+ #include < Utils/SplitString.cpp>
42
+
43
+ using namespace std ;
44
+
45
+ map<string, vector<string>> mapReplacements;
46
+ string input;
47
+
48
+ int parseInput ()
49
+ {
50
+ MEASURE_FUNCTION_EXECUTION_TIME
51
+ string filename = " input.txt" ;
52
+ ifstream file (filename);
53
+
54
+ if (!file.is_open ())
55
+ {
56
+ cerr << " Erreur : impossible d'ouvrir le fichier " << filename;
57
+ return 1 ;
58
+ }
59
+ string line;
60
+ while (getline (file, line))
61
+ {
62
+ if (line == " " )
63
+ {
64
+ getline (file, input);
65
+ continue ;
66
+ }
67
+ vector<string> splitedInput = splitString (line, " => " );
68
+ mapReplacements[splitedInput[0 ]].push_back (splitedInput[1 ]);
69
+ }
70
+ file.close ();
71
+ return 0 ;
72
+ }
73
+
74
+ int processP1 ()
75
+ {
76
+ MEASURE_FUNCTION_EXECUTION_TIME
77
+
78
+ // Utiliser un ensemble pour stocker les chaînes uniques résultant des remplacements
79
+ set<string> uniqueString;
80
+
81
+ // Parcourir les remplacements dans la mapReplacements
82
+ for (auto &it : mapReplacements)
83
+ {
84
+ // Trouver la première occurrence de la clé dans la chaîne d'entrée
85
+ for (string s : it.second )
86
+ {
87
+ // Trouver la première occurrence de la clé dans la chaîne d'entrée
88
+ size_t pos = input.find (it.first );
89
+
90
+ // Effectuer les remplacements dans la chaîne d'entrée
91
+ while (pos != string::npos)
92
+ {
93
+ string newString = input.substr (0 , pos) + s + input.substr (pos + it.first .size ());
94
+
95
+ // Insérer la nouvelle chaîne dans l'ensemble pour garantir l'unicité
96
+ uniqueString.insert (newString);
97
+
98
+ // Trouver la prochaine occurrence de la clé dans la chaîne d'entrée
99
+ pos = input.find (it.first , pos + 1 );
100
+ }
101
+ }
102
+ }
103
+
104
+ return uniqueString.size ();
105
+ }
106
+ vector<string> alreadySee;
107
+
108
+ // Effectue un parcours récursif pour atteindre la molécule cible "e" à partir de la molécule actuelle.
109
+ // Le paramètre 'count' représente le nombre d'étapes effectuées.
110
+ int backtrack (string molecule, int count)
111
+ {
112
+ // Vérifier si la molécule a déjà été traitée pour éviter une boucle infinie
113
+ if (find (alreadySee.begin (), alreadySee.end (), molecule) != alreadySee.end ())
114
+ {
115
+ return -1 ;
116
+ }
117
+ // Vérifier si la molécule est la cible finale "e"
118
+ if (molecule == " e" )
119
+ {
120
+ return count;
121
+ }
122
+
123
+ // Ajouter la molécule actuelle à la liste des molécules déjà vues
124
+ alreadySee.push_back (molecule);
125
+
126
+ // Parcourir les remplacements possibles dans la mapReplacements
127
+ for (auto &it : mapReplacements)
128
+ {
129
+ // Parcourir les chaînes de remplacement associées à la clé actuelle
130
+ for (string s : it.second )
131
+ {
132
+ // Trouver la première occurrence de la chaîne de remplacement dans la molécule
133
+ size_t pos = molecule.find (s);
134
+
135
+ // Effectuer les remplacements dans la molécule
136
+ while (pos != string::npos)
137
+ {
138
+ string newString = molecule.substr (0 , pos) + it.first + molecule.substr (pos + s.size ());
139
+
140
+ // Récursivement appeler backtrack avec la nouvelle molécule et le compte mis à jour
141
+ int value = backtrack (newString, count + 1 );
142
+
143
+ // Si une solution est trouvée, la retourner
144
+ if (value != -1 )
145
+ {
146
+ return value;
147
+ }
148
+
149
+ // Trouver la prochaine occurrence de la chaîne de remplacement dans la molécule
150
+ pos = molecule.find (s, pos + 1 );
151
+ }
152
+ }
153
+ }
154
+
155
+ // Aucune solution trouvée, retourner -1
156
+ return -1 ;
157
+ }
158
+
159
+ int processP2 ()
160
+ {
161
+ MEASURE_FUNCTION_EXECUTION_TIME
162
+
163
+ // Appeler la fonction backtrack pour effectuer le parcours récursif
164
+ return backtrack (input, 0 );
165
+ }
166
+
167
+ int main ()
168
+ {
169
+ if (parseInput () == 1 )
170
+ {
171
+ return 1 ;
172
+ }
173
+
174
+ int part1 = processP1 ();
175
+ int part2 = processP2 ();
176
+
177
+ cout << " \n Part1: " << part1 << ' \n ' ;
178
+ cout << " Part2: " << part2 << ' \n ' ;
179
+
180
+ return 0 ;
181
+ }
0 commit comments