Para la solución de este problema no se usará recursión; a razón de que puede resultar lento y podría ocasionar un desbordamiento de memoria.
Se recurre al uso de la técnica de memorización: almacenamiento externo para guardar cálculos, y que éstos sirvan para las siguientes iteraciones (Mukherjee, 2014).
Esto quiere decir que va a buscar el Item1 que cumpla la condición (filaActual - 1): fila anterior; y además, el Item2 que cumpla condición (filaActual - 1): columna anterior.
De forma análoga para el ítem que suma el siguiente valor de la fila anterior y de la columna actual:
v => v.Item1 == (filaActual - 1) && v.Item2 == j
Nótese que la expresión v.Item2 == j hace referencia al valor (Item3) que está enseguida de la columna anteriormente encontrada.
Prueba de ejecución:
Figura 1. Triángulo de Pascal con 12 filas.
4. Literatura & Enlaces
Mukherjee, S (2014). Thinking in LINQ Harnessing the Power of Functional Programming in .NET Applications. United States: Apress.
Un número suma-producto es un entero que se obtiene a partir del producto entre la sumatoria y la productoria de los dígitos. Esta definición se puede expresar así:
La variable l indica la cantidad de dígitos en el número; y las variables d con índice i o j indican el enésimo dígito del número n.
En las líneas 14-26 se define el método de extensión Digitos(); este método se usa para obtener cada uno de los dígitos de un número como una secuencia.
Entre las líneas 1-9 está definido el método Main(); aquí ocurren las siguientes operaciones:
Línea 3: Se genera una secuencia con valores enteros entre 0 y 1000.
Línea 4: Se aplica la aplicación filtro Where.
Línea 5: Para el k número de la secuencia se obtienen sus dígitos.
Línea 7: Se comprueba el predicado que define un número suma-producto; es decir:
digitos.Sum() * digitos.Aggregate((x, y) => x * y) == k
Si el producto entre la sumatoria y la productoria de los l dígitos del k número es igual k, entonces k es un número suma-producto.
Prueba de ejecución:
Figura 1. Números suma-producto entre 0 y 1000.
4. Literatura & Enlaces
Mukherjee, S (2014). Thinking in LINQ Harnessing the Power of Functional Programming in .NET Applications. United States: Apress.
Generar números de Dudeney usando programación funcional.
2. Solución
El cubo perfecto de un número entero positivo se conoce como número de Dudeney: consiste en sumar cada uno de los dígitos y luego elevarlo al cubo; el resultado será el número original (Mukherjee, 2014).
El método de extensión Digitos() (líneas 12-24) permite descomponer un número en sus dígitos.
En el bloque de código del método Main() (líneas 1-6) se lleva a cabo las siguientes operaciones:
Línea 3: a través de la función generadora Range() se crea una secuencia de números entre 0 y 1000.
Línea 4: Se aplica la función filtro Where() para obtener sólo los números que cumplan con el predicado que define un número de Dudeney representando pore:
La suma de los dígitos de e al cubo es igual al número e; en otras palabras:
Math.pow(e.Digitos().Sum(), 3) == e
Prueba de ejecución:
Figura 1. Números de Dudeney entre 0 y 1000.
4. Literatura & Enlaces
Mukherjee, S (2014). Thinking in LINQ Harnessing the Power of Functional Programming in .NET Applications. United States: Apress.
El método de extensión Digitos() (líneas 4-16) es el que permite descomponer un número dado en sus dígitos.
En el método Main() (líneas 19-24) se realizan las siguientes operaciones:
Se genera el rango 0-1000: Enumerable.Range(0, 1000)
Se utiliza la función filtro Where para comprobar que la suma de los dígitos (cada uno elevado al cubo) es igual al número actual k.
Por cada número k del rango (0-1000) se realiza la proyección de elevar al cubo cada dígito (obtenidos con la método de extensión Digitos()); y finalmente aplicar la función estadística de Sum() para sumar todos los cubos.
Prueba de ejecución:
Figura 1. Números de Armstrong entre 0 y 1000.
4. Literatura & Enlaces
Mukherjee, S (2014). Thinking in LINQ Harnessing the Power of Functional Programming in .NET Applications. United States: Apress.
Encontrar el valor mínimo y máximo por índice en distintas sequencias.
2. Solución
El operador Zip se aplica a una sequencia que recibe como argumento otra secuencia, y luego, como segundo argumento los valores de los índices 0, 1, etc. de cada una de las secuencias. Estos valores son comparados con los métodos Math.Min(val1, val2) yMath.Max(val1, val2)(Mukherjee, 2014).
En este vídeotutorial se exploran los delegados estándar y genéricos con los que es posible definir métodos funcionales. Se demuestra a través de ejemplos las diferencias entre estos dos tipos de delegados; por otra parte, también se implementa la composición gof=g(f(x)) usando delegados Func.
1. Introduction 2. Keywords 3. Problema 4. Solution 5. Discussion 5.1 Zip() standard query operator 6. Pratice: Denoting Bidding Values 7. Conclusions 8. Literature & Links
1. Introduction
With this new LINQ recipe the programmer will learn how to find the larger or smaller value from several given sequences. These sequences have the same length and are composed of numeral values. Particularly, the programmer is going to use, once again, the Zip() standard query operator from LINQ to accomplish this computation. In the practice section, the reader will know how to find the maximum and minimum bid values from the given sequences. LINQ is amazing!
2. Keywords
Collection
LINQ
Sequence
Standard query operator
Zip()
3. Problem
Find the minimum or maximum value of several sequences at each element index.
4. Solution
In LINQ we find the Zip() standard query operator to apply some specified function to a sequence of elements; the function uses each index as input values.
5. Discussion
5.1 Zip() standard query operator
Zip() is a standard query operator; it's useful to apply some specified function to each element index of a sequence. Visually, it can viewed as
Illustration 1. Zip() visual operation schema.
Notice that each index from seq1 has its corresponding index on seq2: the function operates over each index.
To exemplify it, this code concatenates the symbol and literal representations for numbers:
int[] numbers = { 1, 2, 3 };
string[] words = { "One", "Two", "Three"};
var numbersAndWords = numbers.Zip(words, (n, w) =>
String.Format("{0} - {1}", n, w));
numbersAndWords.Dump("Numbers and Words");
Once executed in LINQPad, this is the result:
Illustration 2. Zip() example.
6. Practice: Denoting Bidding Values
Suppose we have two collections to represent the bidding values for different items.
The purpose with this recipe is to learn how, by means of LINQ, to find the smaller and larger of bidding values.
Lines 2 and 3 define two list of bid values as integer elements. Next, lines 6-8, we call Zip() function to find the maximum bids from sequence's indexes. Observe how the Math.Max() function is used to find the maximum between the two parameters bid1 and bid2.
Analogally, lines 11-13, compute the Math.Min() function to find the minimum of the two parameters -bid1 and bid2.
The output in LINQPad:
Illustration 1. Minimum and maximum bids.
An extended version of this solution consists on multiple bid sequences (it's a generalized approach):
Four sequences are defined to contain bid values (lines 2-5). All these sequences are added to a list of lists (lines 8-12). Its purpose is to find the smaller and larger bid values using the Aggregate("Enumerable.Aggregate(TSource) Method", 2016); basically, what this method does is apply an accumulator over a sequence.
Once executed, this is the resultant output in LINQPad:
Illustration 3. Minimum and maximum bids (general approach).
Video tutorial:
7. Conclusions
We have used the Zip() as programmatic mechanism to find the smaller or larger values from two sequences. This knowledge is useful for many applications which require this kind of computation for some type of values.
Next LINQ recipe is going to explain how to generate Armstrong Numbers and similar number sequences.
1. Introduction 2. Keywords 3. Problem 4. Solution 5. Discussion 5.1 Range(int, int) method 5.2 Skip() method 6. Practice: Picking Every nth Element from a Collection 7. Conclusions 8. Literature & Links
1. Introduction
A task like element selection, or more particularly pick every nth element, from a collection is a common problem that frequently appears in other problems such as randomizing, listing, or load distribution. In this LINQ recipe will demonstrate to the programmer how to write an idiomatic LINQ program to query a collection for finding every nth element.
2. Keywords
Collection
LINQ
List
Load distribution
Query
3. Problem
Pick every nth element from a given sequence (without dividing the index to determine whether to include an element from the collection).
4. Solution
First, it's possible to divide the sequence's count property by the nth element, and then use Skip() method to bypass a specified number of elements in the sequence.
5. Discussion
5.1 Range(int, int) method
Range() method generates a sequence of number for a range. ("Enumerable.Range Method", 2016). For example:
IEnumerable<int> cubes = Enumerable.Range(1, 10).Select( x => x * x * x);
Here, Range generates the range of numbers from 1 to 10 as counting, i.e., 10 numbers. Then Select() produces the 3rd power for each number from 1 to 10.
5.2 Skip() method
This method is used to bypass a given number of elements, and it returns the remaining elements of the sequence ("Enumerable.Skip(TSource)", 2016).
What we get with this expression is lower grades: in the first place, the sequence is sorted in descending order, then with Skip(3) the higher grades -97, 91, and 89- are skipped.
6. Practice: Picking Every nth Element from a Collection
Now it's time to write an idiomatic LINQ query in LINQPad to pick every nth element in a sequence.
With int n = 10; (line 2) we specify the nth element: in this case we will pick every 10th element. In line 5 we request a list of 100 numbers -range 1 to 100.
It's required a data structure, in this case a list, to store the nth elements; that is define in line 8: List<int> nthElements = new List<int>();.
With this in mind, we got lines 11-13: here the expression Enumerable.Range(0, numbers.Count()/n) produces a range from 0 to 9; its purpose is allow the iteration of each nth element in the numbers list.
Now the code numbers.Skip(k*n).First() skips the k*n elements in numbers, and chooses the first element of the remaining elements generated by Skip(k*n).
Let's play an execution for this amazing LINQ code:
7. Conclusions
An operation like pick an element from a collection is a common task; this recipe has showed us how to pick every nth element from a sequence by using the Skip() and First()methods.
The next recipe, the LINQ programmer will learn how to find the larger or smaller of several sequences at each index.