Lumen
Table of Contents
1. Présentation du puzzle
Il y a une pièce de forme carrée, de côtés N.
Des bougies sont placés dans la pièce avec une certaine intensité.
Chaque bougie fait L “lumière” à l’endroit où elle se trouve, et chaque carré autour de la lumière reçoit une “lumière” de moins que les suivantes. Si un point est touché par deux bougies, il aura la plus grande “lumière” qu’il peut avoir. Chaque spot a une lumière de base de 0.
Le but est de compter le nombre de spot noir au final.
Il y a un plan de la pièce, avec les emplacements vides (X) et les Bougies (C) en N rangées, chaque point séparé par un espace.
Exemple avec N=5 et L=3:
X X X X X X C X X X X X X X X X X X X X X X X X X
Doit donner une chambre:
2 2 2 1 0 2 3 2 1 0 2 2 2 1 0 1 1 1 1 0 0 0 0 0 0
Il y a donc 9 spots noir.
2. Présentation de ma méthode de résolution
2.1. Description
Pour réaliser ce codingame:
Je recupere N et L dans des variables. Grâce à la fonction malloc j’alloue un tableau 2d de taille N x N. Puis dans ce tableau j’initialise chaque élément à 0. Ensuite je fais une boucle pour récupérer chaque position des lumières que je stocke dans un tableau (candle[]). Au préalable j’ai créée une structure nommée struct position pour attribuer un couple(x,y) pour la position de chaque lumière. Je vérifie ensuite si le compteur de lumière (candlecount) est plus grand que 0. Si oui alors je boucle sur chaque lumière. Pour chaque lumière je boucle sur chaque élément du tableau 2d. Pour remplir les cases je m’intéresse à la distance entre la position de mon élément du tableau 2d et la position de la lumière en question. J’utilise la formule de la distance de l’échiquier que nous avons vu lors du cours “Introduction à l’imagerie”. Cette formule permet de garder la diagonale à la meme distance qu’un côté adjacent.
Formule: d(p,q)=max(|xp-xq|,|yp-yq|)
La formule L-d(poselement,poslumiere) me donne donc la puissance de la lumiere à la position de l’element. Cette formule est utilisé uniquement si a cette position la formule est plus grande que l’element à cette case.
A la fin de ces boucles on obtient donc le tableau 2d representant la pièce. Le programme va donc reboucler sur chaque élément du tableau 2d pour compter le nombre de 0 pour afficher combien il y a de spots 0.
Finalement je boucle sur chaque ligne du tableau 2d pour libérer l’espace allouer grâce à malloc.
2.2. Code
#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> int max(int a,int b){ // Fonction maximum entre deux entiers int max; if (a>b){ max=a; }else{ max=b; } return max; // Retourne le maximum } int abs(int a){ //Fonction valeur absolue int abs; if (a>=0){ abs=a; }else{ abs=-a; } return abs; //Retourne la valeur absolue d'un entier } struct position{ //Structure position pour la position des bougies int x; int y; }; int main() { int N, i, j,k; struct position candle[1000]; //Tableau de type struct position pour stocker toutes les positions des bougies int candlecount=0,zerocount=0; int **tab; //Déclaration du tableau 2D scanf("%d", &N); //Recuperation de la longueurs des côtés de la piece int L; scanf("%d", &L); //Recuperation de la puissance d'une bougie tab = malloc((N+18)*sizeof(int)); //Allocation de la longueur de la chambre for (i = 0; i < N; i++) { tab[i] = (int *)malloc(N * sizeof(int)); //Allocation de la largeur de la chambre, chaque element du tableau est initialisé à 0 } for (i=0;i < N;i++){ //boucle sur chaque ligne du tableau for (j = 0; j < N; j++) { //boucle sur chaque élément de la ligne i char cell[4]; //str pour la diffusion des bougies scanf("%s", cell); //Recuperation ou non d'une bougie if (cell[0]=='C'){ //Si c'est une bougie candle[candlecount].x=i; //On place la position de cette bougie dans le tableau candle candle[candlecount].y=j; candlecount++; //Il y a donc une bougie de plus tab[i][j]=L; //On remplace dans le tableau de la chambre la puissance de la bougie sur la bonne position } } } if (candlecount>0){ //Si il y a au moins une bougie on rentre dans la boucle: for(k=0;k<candlecount;k++){ //Pour chaque bougie on va modifier ou non les valeurs du tableau for (i=0;i<N;i++){ //boucle sur chaque ligne du tableau for(j=0;j<N;j++){ //boucle sur chaque element de la ligne i if (L-max(abs(candle[k].x-i),abs(candle[k].y-j))>tab[i][j]){ //Condition : Si la puissance de la lumière moins la distance entre la position de la lumière et (i,j) est plus grande que tab[i][j] tab[i][j]=L-max(abs(candle[k].x-i),abs(candle[k].y-j)); //Alors cette valeur est assignée a tab[i][j] } } } } } for (i = 0; i < N; i++){ //boucle pour chaque ligne du tableau for (j = 0; j < N; j++){ //boucle sur chaque element de la ligne i if(tab[i][j]==0){ //Si tab[i][j]=0 alors on ajoute 1 au nombre de zero de la chambre zerocount++; } } } printf("%d",zerocount); //affichage du nombre de 0 final free(tab); return 0; }
2.3. Test
2.3.1. Test 1:
Entrée:
5 3 X X X X X X C X X X X X X X X X X X X X X X X X X
Résultat valide : 9:
9
2.3.2. Test 2:
Entrée:
25 2 X X C C C C X X X X C C X X X C X X X X X C X X X C X X X X X X X X X X X X X X C X X X X X X X X X X X X X X X X X X X X X C X X X X C X X X C C X X C X X X X C X X X X X X X X X X X X X C X X X X X X X C X C X X X X X X X X X C X X C X X X C X X X X X X X X C X X X X X X X C X C X X X X X X X X X C X X X X C C X X X X X X X X X C X X X X X X C X C X C C X X C X X C X X C C X X C X X X X X X X X X X X X X X X X X X X X X X X X X C X X X X X C X X C X X X X X X X X X X X X X X X X X C C X X X X C X X X X X X C X C X X X X C X X X X X C X X X X X C X X C X X X X X X X X X C X X X X X C X X X C X X X X X X X X X C X X C X X X X X X X X X C X X X X C X C X X X X X C X X X X X X C C X X X C X C C X C C X X X X X X X X X X C X X X X X C X X X X C X X C X C X X C C X X X C C X X X X X X X C C X C X X X X X X X X X X X X X X X X X X C X X X X X X X X X X X X C X X X X X X C X X X X X X X C X X X C X C X X C X X X X X C X X X X X X X C C X C X X X X C X X C C C X X C X X X X X C X X X X X X X X C X X X X X X X X X X X C X X X X X X X X X X X X X X C C X X C X C X X X X X X X X X C C X X X X X X C X X X X C X C C X X X X X C X X X X C C X X X X X X C X X X X X C X X X X X C X X X C X X C X X X X C X X C X X X X X X X X X X X C X X X X X X
Résultat valide: 90
90
2.3.3. Test 3
3 3 X X X X X X X X X
Résultat valide: 9
9
3. Description d’une autre méthode
3.1. Code de Alain-Delpuch
J’ai trouvé ce code très beau car il utilise parfaitement la notion de récursivité. Il est extrement court et plutot simple à comprendre. La seule difficulté est de comprendre la fonction récursive: cette fonction permet de modifier la map pour créer la propagation de la lumière. La fonction F prend trois arguments : les indices de ligne et de colonne (i, j) de la cellule en cours d’exploration, et la valeur actuelle de la lumière (l). La fonction vérifie d’abord si les indices sont valides et si la valeur de la lumière est inférieure ou égale à la valeur stockée dans la cellule correspondante de la grille (map[i][j]). Si l’une de ces conditions n’est pas satisfaite, la fonction se termine immédiatement. Sinon, elle met à jour la valeur stockée dans la cellule correspondante de la grille avec la valeur actuelle de la lumière, et diminue la valeur de la lumière de 1. Ensuite, elle appelle récursivement la fonction F pour les cellules adjacentes, en passant la nouvelle valeur de la lumière comme argument.
L’algorithme parcourt chaque cellule de la grille une fois, en appelant la fonction F pour chaque cellule contenant une valeur “X” ou une valeur initiale de la lumière différente de 0. Ensuite, il compte le nombre de cellules avec une valeur de la lumière de 0, qui représentent les cellules éclairées à la fin de l’algorithme. Cette méthode est intéressante car elle ne parcourt que très peu la map. C’est un code optimisée en termes de longueur, de temps et de mémoire.
// ------------------------------------------------------------------ // Lumen // ------------------------------------------------------------------ #include <stdio.h> // ------------------------------------------------------------------ int map[25][25]; int N,L; // ------------------------------------------------------------------ void F(unsigned int i, unsigned int j, int l){ if ( i >= N || j >= N || l < map[i][j] ) return; map[i][j] = l--; F( i-1 , j-1 , l) ; F( i-1 , j , l) ; F( i-1 , j+1 , l) ; F( i , j-1 , l) ; ; F( i , j+1 , l) ; F( i+1 , j-1 , l) ; F( i+1 , j , l) ; F( i+1 , j+1 , l) ; } // ------------------------------------------------------------------ main() { scanf("%d %d\n", &N, &L); for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { char buf[2]; scanf("%s",buf); F( i , j , *buf=='X' ? 0 : L); } } int result = 0; for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { result += map[i][j] == 0; } } printf("%d",result); }
4. Apprentissage
Pour ce puzzle, j’ai appris à utiliser la fonction malloc pour des tableaux à deux dimensions. J’ai compris l’importance d’utiliser des structure pour mieux comprendre le code. J’ai trouvé mon code intéressant car il utilise la notion de distance de l’échiquier. Cependant lire la condition de la distance peut être un peu illisible. Une autre fonction nommée distance aurait pu aider à une meilleure compréhension du code par autrui. Pour réaliser ce puzzle, plusieurs méthode existe, chacune avec ses spécificités mais toutes intéressante.