I- Présentation du problème
A) Les entrées
En entrée, on a d'abord une première chaine de caractère order qui stocke l'ordre des pliages à effectuer. Ensuite, une seconde chaine de caractère side permet de connaitre quel coté nous intéresse à la fin du processus.
B) Le but du jeu
Une feuille de papier est pliée plusieurs fois. Le but est de déterminer combien de couches de papier sont visibles d'un côté du pliage obtenu.
Les mouvements de pliage sont :
- R pour la droite : prenez le côté droit et pliez-le sur le côté gauche.
- L pour la gauche : prenez le côté gauche et pliez-le sur le côté droit.
- U pour Up : prendre le côté haut et le replier sur le côté bas.
- D pour le Down : prenez le côté bas et repliez-le sur le côté haut.
C) La sortie
Il faut retourner un entier qui représente le nombre de couche de papier que nous voyons du côté indiqué dans la chaine de caractère side.
II- Ma méthode de résolution
A) Approche synoptique
Pour résoudre ce problème, j'ai réfléchi à ce qui se passait lorsqu'on pliait une feuille. Le côté que l'on vient de plier possède une seule couche tandis que le côté opposé est l'addition de son nombre de pli initial avec ceux du côté à plier (avant pliage !!) et les deux autres côtés voient leur couche multipliée par 2. J'ai précisé avant pliage car on verra que cela à une incidence avec l'ordre pour effectuer les opérations dans le programme. Je gardais ces valeurs à chaque itération puis je retournais le nombre de couches du côté voulu après un certain nombre de pliages.
B) Appproche algorithmique et explication de mon programme
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
int main(){
int R=1, L=1, U=1, D=1, i=0, cote;
char order[9];
scanf("%[^\n]", order); fgetc(stdin);
char side[6];
scanf("%[^\n]", side);
while(order[i]!='\0'){
if(order[i]=='R'){
L = R + L;
R = 1;
U *= 2;
D *= 2;
}
else if(order[i]=='L'){
R = L + R;
L = 1;
U *= 2;
D *= 2;
}
else if(order[i]=='U'){
D = D + U;
U = 1;
L *= 2;
R *= 2;
}
else if(order[i]=='D'){
U = D + U;
D = 1;
L *= 2;
R *= 2;
}
i++;
}
cote=side[0];
switch(cote){
case 'U':
printf("%d",U);
break;
case 'L':
printf("%d",L);
break;
case 'D':
printf("%d",D);
break;
case 'R':
printf("%d",R);
break;
}
return 0;
}
Pour ce problème? je n'ai pas eu besoin de créer de fonctions annexes, tout se déroule dans la fonction main. Tout d'abord j'initialise les variables R, L, U, et D à 1 ce qui correspond au nombre couche par coté (U pour up, D pour down, R pour right et L pour left). J'initialise un compteur i à 0 ainsi que'une variable cote sans valeur par défaut. Les quatres lignes suivantes servent à remplir les chaines de caractères order et side qui corresponde respectivement à l'ordre des pliages qui ont été effectué et au coté dont on veut savoir le nombre de couche.
Ensuite je rentre dans une boucle while qui s'arrètera à la fin de la chaine de caractère (élément '\0' dans le tableau représentant la chaine de caractère en C). À chaque itération, on regarde quel coté a été plié, je traite donc les 4 cas possibles qui sont: U, D, L, R avec une boucle if et trois autres boucles else if. Pour chaque boucle, nous allons faire les mêmes calculs, en effet, lors du pliage, le coté qui a été plié vaut donc 1, le coté opposé vaut sa valeur additionné à l'ancienne valeur du coté du pliage (il faut donc déterminer la valeur du coté opposé avant de mettre le coté du pliage à 1), enfin les deux autres cotés voient leur valeur multiplié par 2. Les 4 boucles servent à déterminer quel coté est celui dupliage, le coté opposé et les deux autres, ce qui fait que nous faisons les mêmes calculs dans le même ordre avec des cotés différents suivant si c'est le coté droit qui a été plié, ou le gauche, etc... À chaque itération j'augmente de 1 le compteur pour permettre d'accéder au caractère suivant dans la chaine représenté par un tableau order
Pour terminer et savoir quel est le coté dont il faut retourner le nombre de couche, j'initialise la variable cote à side[0] qui correspond à une lettre, soit U, soit D, soit R soit L. Je crée donc ensuite un switch qui prend comme variable cote et pour valeur, les différents cotés. Chaque case renverra donc le coté associé à la valeur de la variable grâce à un printf. Je retourne enfin 0 car la fonction a été déclaré de type int.
III- Un autre programme
int c2i(char c) {
switch(c) {
case 'R': return 0;
case 'U': return 1;
case 'L': return 2;
default: return 3;
}
}
int main() {
char order[9], side[2];
scanf("%s%s", order, side);
int n[4] = {1, 1, 1, 1};
for(char * p = order; *p; p++) {
int from = c2i(*p);
int side1 = (from + 1) % 4;
int to = (from + 2) % 4;
int side2 = (from + 3) % 4;
n[to ] += n[from];
n[from ] = 1;
n[side1] *= 2;
n[side2] *= 2;
}
printf("%d\n", n[c2i(side[0])]);
return 0;
}
Ce programme est un peu différent du miens, malgrès qu'on doit forcément utilisé les deux structures de tableaux qui nous "forcent" à faire des codes plutôt similaire. Néanmoins il y a des différences. Pour ma part au début j'avais créé une fonction qui renvoyait 4 valeurs sauf que je n'ai jamais réussi à la faire fonctionner, je me suis donc tourné vers la solution de répéter 4 fois les mêmes lignes de code pour les 4 cas de pliage.
Ici le codeur n'a pas procéder comme cela, en effet il est parti dans la même optique que moi qui visaisà ne pas écrire 4 fois le même bout de code. Il utilise une fonction qui va retourner un entier correspondant à la place dans le tableau qu'il a créé dans son main n correspondant à l'indice du coté du pliage. Avec sa boucle for, il parcourt un a un les caractères du tableau et appelle sa fonction annexe pour déterminer l'indice du coté à plier, ce quui lui permet ensuite d'adapter ces calculs, ce qui est mieux optimisé que mon programme. Une fois terminé il va appeller une dernière fois sa fonction annexe pour déterminer quelle valeur dans son tableau n il doit renvoyer pour donner le nombnre de couche possédé par le coté demandé.
IV- Bilan / Retour d'expérience
Etant donné que nous n'avions pas encore eu de CM ni de TD/TP sur les chaines de caracteres et les tableaux en C, j'ai donc appris à itérer sur une chaine de caractère représenté par un tableau, je suis content d'avoir utilisé un switch car je ne l'avais fait qu'une seule fois et la été l'occasion révé pour s'en servir dans une situation concrète hors exercice. Coder et résoudre cette exrcice a été quelque chose que j'ai aimé faire car je commence à mieux me servir du langage C même s'il me reste encore une trés grande marge de progression, il faut bien commencer à un moment pour progresser !!!