Archives par mot-clé : software

Opérations sur les vecteurs en c# en utilisant l’expression Lambda -2-

Opérations sur les vecteurs en c#  en utilisant l’expression Lambda

Par Ettougourti Mohamed Ali

Nous pouvons aller encore plus loin dans notre exploitation du nouvel outil de programmation que le c# nous offre à savoir l’expression lambda.

(voir article précédent).

L’on peut par exemple ajouter une valeur unique aux différentes valeurs d’un vecteur

x = x.Select(b => b += 0.3).ToArray();

Ou en soustraire une valeur donnée

x = x.Select(b => b -= 0.3).ToArray();

Vous l’avez deviné toutes les opérations arithmétiques sont possibles :

La multiplication:

x = x.Select(b => b *= 0.3).ToArray();

La division:

x = x.Select(b => b /= 0.3).ToArray();

Les précautions d’usage restent de mise pour la division par zéro qui nous donne « infinity » comme résultat.

Les valeurs absolues:

x = x.Select(b => Math.Abs(b)).ToArray();

l’élevation à puissance :

x2 = k2.Select(b => Math.Pow(b, 2)).ToArray();

Pour élever les valeurs de k2, un tableau de type int, à la puissance de 2 nous avons toutefois utilisé un tableau de type double x2 en tant que tableau de destination : Math.pow renvoie en effet une valeur double.

Ces précautions d’usage prises en compte il est possible avec l’expression Lambda d’effectuer toutes les opérations mathématiques sur un vecteur une seule fois et sans recourir à des boucles d’itération.

L’appétit vient en mangeant rien ne peut plus désormais freiner notre élan et l’on est en droit de se demander si d’autres opérations plus fines ne puissent être menées à bien sur des vecteurs.

Le c#  nous offre en matière de tableaux plusieurs instructions de nature à nous faciliter encore plus la tâche.

Ainsi il est possible d’éliminer les doublons d’un vecteur.

Pour ce faire on utilise la fonction ou la méthode « distinct ».

Si l’on initialise un tableau d’entiers avec plusieurs doublons exemple :

int[]k={2,1,2,3,5,3,4,1,6,7,8,2,1,0,8} ;

et si l’on fait appel à distinct() l’on verra qu’une seule valeur des doublons 2,3, 8 ,etc. est retenue et le tableau de rétrécir de 15 éléments à tout juste neuf éléments.

k2 = {2,1,3,5,4,6,7,8,0} ;

Je vois venir votre objection : dans distinct il n’y a pas de signe lambda qui vaille, pourquoi l’invoquer ?

Vous avez raison.  C’est pourquoi je me rattrape sur une autre méthode fort utile qui exige cette fois l’emploi de l’expression lambda.

La méthode sert à trier le tableau par ordre ascendant:

k2 = k2.OrderBy (b=>b).ToArray ();

En inspectant le tableau k2 l’on constate que le zéro initié à la fin du tableau prend désormais la première place et que toutes les valeurs sont bien ordonnées du plus petit au plus grand.

k2 = {0,2,1,3,5,4,6,7,8} ;

Vous ne voulez pas d’un ordre ascendant ?  La même expression lambda nous permet de trier le tableau dans l’ordre descendant du plus grand au plus petit

k2 = k2.OrderByDescending (b => b).ToArray();

Et le tour est joué:

k2 = {8,7,6,5,4,3,2,1,0} ;

Pour faire compliqué alors qu’on peut faire simple on peut évidemment ordonner les valeurs d’un tableau par ordre décroissant ou ascendant puis simplement inverser le tableau grâce à la fonction ou la méthode reverse.

k2.Reverse();

Mais comme vous le constatez l’expression lambda ne figure pas dans l’instruction reverse.

Si vous tenez à employer l’expression lambda dans reverse vous serez vite remis à l’ordre par le compilateur une erreur survient de type « cannot convert lambda expression to type array because it is not a delegate type ».

Ceci n’est pas très clair mais en gros le compilateur refuse d’y aller : ses désirs, comme chacun sait, sont des ordres.

Le plus intéressant reste évidemment de pouvoir travailler sur plusieurs vecteurs.

Pour ce faire nous allons initier un deuxième vecteur baptisé x2 de type double avec des valeurs aléatoire grâce au générateur de nombre aléatoires t précédemment créé.

double[] x2 = new double[100];

x2 = x2.Select(b => b = t.NextDouble()).ToArray();

Pour additionner les valeurs des deux vecteurs nous retrouvons donc notre variable d’itération, next ou index ou de  tout autre nom fantaisiste.(voir article précédent)

Si nous choisissons le vecteur x2 comme vecteur de destination la ligne de code doit s’écrire comme suit :

x2 = x.Select((b,next) => b + x2.ElementAt(next)).ToArray ();

Remarquez que nous pouvons référencer l’élément dans x2 directement à l’aide de deux accolades en reprenant le code sous cette forme:

x2 = x.Select((b, next) => b + x2[next]).ToArray();

C’est aussi avec la même insolite facilité que nous pourrons soustraire un vecteur d’un autre, multiplier deux vecteurs ou diviser l’un par l’autre.

x2 = x.Select((b, next) => b – x2[next]).ToArray();

x2 = x.Select((b, next) => b * x2[next]).ToArray();

x2 = x.Select((b, next) => b / x2[next]).ToArray();

il est tout aussi possible d’effectuer des opérations sur plusieurs tableaux:

x2 = x.Select((b, next) => b + x2[next]* k2[next]).ToArray();

Vous avez testé cette dernière ligne de code et vous avez constaté que ça ne marche pas ?

Autant  pour moi, j’ai oublié de vous parler d’ un détail important:  les tableaux doivent être de même taille d’où l’exception soulevée par le programme : « out of range » ou limites du tableau atteintes.

(164)

USING THE LAMBDA EXPRESSION IN TRANSACTIONS VECTORS IN C#

 

USING THE LAMBDA EXPRESSION IN TRANSACTIONS VECTORS IN C SHARP

By Mohamed Ali Ettougourti

 

Operations on vectors or arrays  occupy the largest share of time spent on the execution of computer programs.

In sharp c # and other languages the term « lambda » is used to « standardize » some vector operations.

We give in these article basic examples:

We start by creating a vector or an array of double values

double [] x = new double [100];

To create random values we initiated a generator of random values « t » that we will use to fill the array « x » of random values.

System.Random t = new Random ();

To do this we will use the lambda expression illustrated by « => »

x = x.Select(b => b = t.NextDouble()).ToArray();

This simple line of code allows us to avoid for next loop, or do while loop or any other loops.

former code example:

for (int i = 0; i <x.length; i ++)

{

x [i] = t.NextDouble ();

}

The lambda expression also can perform some basic operations on the vector.

Thus we are able to calculate the sum of the values contained in the vector:

double sum = x.Sum();

Or to calculate the arithmetic mean:

double average = x.Average();

The same lambda expression allows us to find the maximum value in the vector:

double max = x.Max();

Or the minimum value of vector:

double min = x.Min();

we may even turning the vector on « List » to search and find the position in the vector  of the both values « min » and « max » ;

int position = x.ToList () .IndexOf (min.);

position = x.ToList () .IndexOf (max.);

The term « lambda » also helps manage elegantly and mass conversion of the values contained in the vector from one type to another.

We can easily convert double values in the vector « x »  to values of type « float » or « int » or « short » ..

We can calculate the sum of the values contained in the vector as if they were of type int32 , operating conversion and performing the addition with the lambda expression

int  int_sum = x.Select (b => System.Convert.ToInt32 (b)) Sum ();

A line of code using the command « Cast » will not work generating aerror  of type « system invalid cast exception. »

int  int_sum = x.Cast () Sum ();

with the lambda expression more advanced arithmetic  operations can be done on the values of the vector.

One can for example raise the values of the vector to the second power, determining the amount, and then divide the number by  the vector length.

All these operations take place in a single line of code

double y= x.Select(b => b * b).Sum() / x.Length;

Other uses of the lambda expression make use of words such as « next » and « index ».

This is the case if one wants to operate an accumulation on a sequence of values in the vector by using the « aggregate » function.

double yy1 = x.Where(b=> b> 0.5).Aggregate((b, next) => next + b);

When you start the program you would notice that the variable « yy » is equal to the variable « sum » and we have done nothing more than to calculate the sum of values in a different way.

But the aggregate function can regain its usefulness when using it with another statement such as « where » for example.

It will be possible soon when we calculate the sum of certain values chosen according to a specific criterion.

Code Sample:

double yy1 = x.Where(b=> b> 0.5).Aggregate((b, next) => next + b);

Checking result you would notice that only values greater than 0.5 were taken into consideration in calculating the sum.

The word « next » is not a keyword. It can be replaced in the previous line of code with the word « index » without   any results changing.

double yy2 = x.Where(b => b > 0.5).Aggregate((b, index) => index + b);

Truly the word « next » or « index » can be just as easily replaced by any other word such as « suivant » or even « cat » 🙂  without any kind of compiler protestation .

And  here is the source code of the examples given

private void sample ()

{
double []x = new double [100];

System.Random t = new Random();
x = x.Select(b => b = t.NextDouble()).ToArray();
double sum = x.Sum();
double average = x.Average();
double max = x.Max();
double min = x.Min();
int position = x.ToList().IndexOf(min);
position = x.ToList().IndexOf(max);

//generating error invalid cast exception
//int int_sum= x.Cast<int>().Sum();

double y= x.Select(b => b * b).Sum() / x.Length;

double yy1 = x.Where(b=> b> 0.5).Aggregate((b, next) => next + b);
double yy2 = x.Where(b => b > 0.5).Aggregate((b, suivant ) => suivant + b);

double yy2 = x.Where(b => b > 0.5).Aggregate((b, cat) => cat + b);
}

(32)

Sudoku: determiner les chiffres candidats

 

Ecrire programme Sudoku : déterminer les candidats

Par  Ettougourti Mohamed Ali

Chaque case de la grille sudoku est traitée comme une structure.  Les informations relatives à chaque cellule sont sauvegardées sous la forme suivante :

public struct cell

{

public Point p;

public int width;

public int height;

public char c;

public bool iscontrainte;

public char[]candidates;

public int nbcandidates;

}

Un élément de la structure nous intéresse particulièrement il s’agit de ‘iscontrainte ‘. S’il est mis à false ou faux c’est que la case est libre et n’est pas fixée par la grille dès le départ comme étant une contrainte du jeu.

C’est une case qu’on peut remplir par des chiffres candidats potentiels.

Mais une case peut aussi comporter un chiffre unique que le joueur a saisi. Elle n’est pas donc libre et nous devons éviter de la remplir des chiffres candidats au risque d’écraser le chiffre introduit par le joueur. C’est ainsi que nous prenons le soin dès le départ de remplir toutes les cases libres qui ne comportent aucun chiffre saisi par le joueur et qui ne sont pas des contraintes du jeu par la lettre « X » pour inconnu.

Pour chaque case nous devons vérifier s’il s’agirait d’une contrainte ou pas et si une éventuelle saisie du joueur a rempli la case par un chiffre déterminé.

Ces deux précautions prises nous cherchons les candidats possibles pour chaque case libre en faisant appel à une fonction baptisée controlvalid2.

Controlvalid2 doit chercher dans chaque ligne ainsi que dans chaque colonne et dans chaque région ou petit carré ou la case se trouve  si le chiffre proposé comme candidat est déjà utilisé auquel cas elle renvoie un -1 dans le cas contraire elle renvoie un chiffre positif 1.

Une fois l’ok donné par la routine controlvalid2 la fonction SetCandidates affiche le chiffre en tant que chiffre candidat potentiel.

Voici la fonction SetCandidates qui remplit les cellules de chiffres candidats potentiels.

Pour la fonction du contrôle de la validité elle sera expliquée dans un prochain article . la fonction getregion nous permet de déterminer la région (ou petit carré à l’intérieur de la grille) ou se trouve la case à remplir de chiffres candidats. Elle fera elle aussi l’objet du prochain article.

private void SetCandidates()

{

for (int i = 0; i < 81; i++) // 81 case 9*9

{

if (cells[i].iscontrainte == false  && cells[i].c==’X’)

{

effacer(cells[i].p);

cells[i].candidates = new char[9]; // creer le tableau

int j = 0;

cells[i].nbcandidates = 0;

for (char k = ‘1’; k < (char)58; k++) // char(58) = ‘9’ +1

{

                        if (Controlvalid2(i, k) == 1)

{

cells[i].candidates[j++] = k;

cells[i].nbcandidates = j;

}

}

}

}

afficheCandidates();       // appel à une fonction affichant les                                                                               //chiffres candidats pour la case

}




(88)