En este capítulo se resuelven algunos problemas que involucran vectores. Para ese fin se emplean las estructuras for y for-of, así como los métodos iterativos disponibles para matrices estudiados en el capítulo anterior. En general, los problemas que involucran arreglos, se resuelven de forma más sencilla (aunque no necesariamente más eficiente) empleando los métodos disponibles.
Por ejemplo, para calcular el valor de la siguiente expresión:
\[ \sum_{i=1}^{n}{v_i} \]
Es decir, calcular la sumatoria de los elementos de un vector "v", como el siguiente:
var v = [1, 2, 4, 5, 6, 8, 12, 23, 25, 42, 2, 6, 7, 3, 112];
La forma más simple consiste en llamar al método sum:
v.sum()
Igualmente (sobre todo si no se trabaja en la calculadora), se puede recurrir al método reduce:
v.reduce((s,e)=>s+e)
El método reduce asigna, en la primera iteración, el valor del primer elemento (1) al primer parámetro de la función (al acumulador "s") y el valor del segundo elemento (2) al segundo parámetro ("e"). En la función se suma a "s" el valor de "e" (1+2 = 3). En la siguiente iteración, el resultado de la anterior iteración (3) es asignado al acumulador "s" y el valor del siguiente elemento (4) a "e", con lo que se calcula un nuevo resultado (3+4 = 7). El método prosigue de esa manera, asignando el resultado de la iteración anterior a "s" y el valor del nuevo elemento a "e", hasta que se llega al último elemento, añadiendo el mismo a "s". Ahora, como no existen más elementos, el resultado de la función (la sumatoria) es devuelto por el método.
Es posible, también, emplear el método forEach:
var s = 0; v.forEach(e => s+=e); s
En este caso, debido a que la función que se manda a forEach sólo recibe, uno a uno, los elementos del vector (e), el acumulador "s" se inicializa en 0 fuera del método. En el método, en cada iteración, se suma a "s" el valor del elemento "e", con lo que, al terminar la última iteración, "s" tiene el valor de la sumatoria.
Se puede emplear también la estructura for-of, que es una variante de la estructura for y que tiene la siguiente sintaxis:
for (eofarray) instrucciones;
Donde las instrucciones son ejecutadas para cada uno de los elementos e del array. El elemento e está disponible para que sea empleado en las instrucciones del ciclo.
Empleando esta estructura, la solución es similar a la del método forEach:
var s = 0; for (let e of v) s+=e; s
La única diferencia, con relación al método forEach es que, como la estructura for-of no recibe una función, sino que ejecuta instrucciones, en lugar de la función se escribe directamente la instrucción que suma a "s", uno a uno, los elementos "e" del vector. Es decir, en la primera iteración "e" vale 1 y se suma ese valor a "s", en la segunda "e" vale 2 y se suma ese valor a "s" y así sucesivamente.
Cuando no se dispone de un método adecuado para resolver el problema, se debe emplear la estructura for o la estructura for-of.
Como ya se vio previamente, una sumatoria (o productoria) con límites definidos, puede ser traducida directamente en un ciclo for, siendo los límites del ciclo los límites de la sumatoria (o productoria) y la variable de la sumatoria (o productoria) el contador del ciclo. El acumulador (la variable que almacena el resultado) debe iniciar en 0 si es una sumatoria y en 1 si es una productoria.
Así, para calcular la sumatoria, con la estructura for, se escribe:
var s = 0; for (let i=0; i<v.length; i++) s+=v[i]; s
Es importante recordar que, cuando se trabaja con vectores (y objetos en general), las variables son punteros, es decir variables que sólo guardan la dirección de memoria del lugar donde están almacenados los datos, pero no los datos en sí. Por esa razón, para efectivamente copiar un vector, se debe emplear el método slice (o el método copy).
Ejemplos
Promedio de un vector de números
En este ejemplo se programa un método para calcular el promedio de los valores almacenados en un vector "x", programando la expresión:
Al ser un problema sencillo, puede ser codificado directamente (sin necesidad de elaborar un algoritmo): el contador del ciclo "i", debe comenzar en 0 e ir hasta "n-1", incrementando en 1 en cada repetición del ciclo. El acumulador que se emplee, por ejemplo "s", debe comenzar en cero y en cada repetición del ciclo se le debe añadir el valor de x[i].
Sólo para que la lógica resulte aún más clara, se elabora el diagrama de flujo respectivo:
gojsGraph({divi, modelo: {"class":"go.GraphLinksModel","linkFromPortIdProperty":"fromPort","linkToPortIdProperty":"toPort","nodeDataArray":[{"category":"Start","text":"promedio","key":-1,"loc":"172 -460"},{"category":"Input","text":"vector de números: x","key":-3,"loc":"171.99999999999994 -410.4666427612303"},{"category":"Conditional","text":"n==0 ","key":-5,"loc":"171.99999999999994 -301.6332496643064"},{"category":"Output","text":"lanzar error:\n \"vector vacío\"","key":-4,"loc":"319.0000000000004 -142.99999999999994"},{"category":"Process","text":"s = 0","key":-2,"loc":"38.85404968261713 -254.33321380615212"},{"category":"Process","text":"i = i+1","key":-7,"loc":"-44.00000000000014 -145.44982967376689"},{"category":"Start","text":"fin","key":-9,"loc":"171.99999999999986 41.65581652323428"},{"category":"Output","text":"s/n","key":-10,"loc":"38.85404968261713 -11.22199312845845"},{"category":"Process","text":"n = num. de elementos en x","key":-11,"loc":"171.99999999999994 -358.9332855224607"},{"category":"For","text":"i<n","key":-6,"loc":"38.85404968261713 -145.44982967376689"},{"category":"Process","text":"i = 0","key":-12,"loc":"38.85404968261713 -199.7998565673826"},{"category":"Process","text":"s = s+x[i]","key":-13,"loc":"38.85404968261713 -76.09980278015117"}],"linkDataArray":[{"from":-5,"to":-4,"fromPort":"R","toPort":"T","visible":true,"points":[208.15933227539057,-301.6332496643064,218.15933227539057,-301.6332496643064,319.0000000000004,-301.6332496643064,319.0000000000004,-243.42775586446112,319.0000000000004,-185.22226206461585,319.0000000000004,-175.22226206461585],"text":"Si"},{"from":-5,"to":-2,"fromPort":"L","toPort":"T","visible":true,"points":[135.84066772460932,-301.6332496643064,125.84066772460932,-301.6332496643064,38.85404968261713,-301.6332496643064,38.85404968261713,-291.61657104492167,38.85404968261713,-281.5998924255369,38.85404968261713,-271.5998924255369],"text":"No"},{"from":-4,"to":-9,"fromPort":"B","toPort":"R","points":[319.0000000000004,-119.79997131347653,319.0000000000004,-109.79997131347653,319.0000000000004,-108,319.0000000000004,-108,319.0000000000004,41.655816523234265,205.55952284071176,41.655816523234265,195.55952284071176,41.655816523234265]},{"from":-10,"to":-9,"fromPort":"B","toPort":"L","points":[38.85404968261713,1.4580212148032716,38.85404968261713,11.45802121480327,38.85404968261713,12,38.85404968261713,12,38.85404968261713,41.655816523234265,138.44047715928815,41.655816523234265,148.44047715928815,41.655816523234265]},{"from":-1,"to":-3,"fromPort":"B","toPort":"T","points":[171.99999999999994,-444.73332138061505,171.99999999999994,-434.73332138061505,171.99999999999994,-434.73332138061505,171.99999999999994,-434.73332138061505,171.99999999999994,-434.73332138061505,171.99999999999994,-424.73332138061505]},{"from":-3,"to":-11,"fromPort":"B","toPort":"T","points":[171.99999999999994,-396.1999641418455,171.99999999999994,-386.1999641418455,171.99999999999994,-386.1999641418455,171.99999999999994,-386.1999641418455,171.99999999999994,-386.1999641418455,171.99999999999994,-376.1999641418455]},{"from":-11,"to":-5,"fromPort":"B","toPort":"T","points":[171.99999999999994,-341.66660690307594,171.99999999999994,-331.66660690307594,171.99999999999994,-331.66660690307594,171.99999999999994,-331.66660690307594,171.99999999999994,-331.66660690307594,171.99999999999994,-321.66660690307594]},{"from":-2,"to":-12,"fromPort":"B","toPort":"T","points":[38.85404968261713,-237.06653518676737,38.85404968261713,-227.06653518676737,38.85404968261713,-227.06653518676737,38.85404968261713,-227.06653518676737,38.85404968261713,-227.06653518676737,38.85404968261713,-217.06653518676737]},{"from":-12,"to":-6,"fromPort":"B","toPort":"T","points":[38.85404968261713,-182.53317794799784,38.85404968261713,-172.53317794799784,38.85404968261713,-172.53317794799784,38.85404968261713,-172.53317794799784,38.85404968261713,-172.53317794799784,38.85404968261713,-162.53317794799784]},{"from":-6,"to":-13,"fromPort":"B","toPort":"T","visible":true,"points":[38.85404968261713,-128.36648139953593,38.85404968261713,-118.36648139953593,38.85404968261713,-110.86648139953593,38.85404968261713,-110.86648139953593,38.85404968261713,-103.36648139953593,38.85404968261713,-93.36648139953593],"text":"Si"},{"from":-13,"to":-7,"fromPort":"L","toPort":"B","points":[2.690673828124943,-76.09980278015117,-7.309326171875057,-76.09980278015117,-44.00000000000014,-76.09980278015117,-44.00000000000014,-97.14147691726666,-44.00000000000014,-118.18315105438214,-44.00000000000014,-128.18315105438214]},{"from":-7,"to":-6,"fromPort":"R","toPort":"L","points":[-16.1634902954103,-145.44982967376689,-6.163490295410298,-145.44982967376689,-1.506393432617287,-145.44982967376689,-1.506393432617287,-145.44982967376689,3.1507034301757244,-145.44982967376689,13.150703430175724,-145.44982967376689]},{"from":-6,"to":-10,"fromPort":"R","toPort":"T","visible":true,"points":[64.55739593505854,-145.44982967376689,74.55739593505854,-144.72491483688344,106,-144.72491483688344,106,-47,38.85404968261713,-47,38.85404968261713,-38.833124160766396,38.85404968261713,-28.833124160766396],"text":"No"}]} })
La condición del ciclo es "i<n", porque las iteraciones deben repetirse mientras el contador "i" es menor a "n", porque "n" es el número de elementos del vector, pero el último elemento es n-1 (debido a que el primer índice es 0).
El código respectivo, es:
var promedio = function(x) { const n = x.length; if (n===0) throw "vector vacío"; let s = 0; for (let i=0; i<n; i++) s += x[i]; return s/n; };
Llamando a la función con algunos valores de prueba, se obtiene:
var a = [1, 9, 12, 3, 5, 7, 12]; promedio(a)
randseed = 1; var b = [].rand(20, 1, 30).round(); print(b); promedio(b)
var c = [].range(17, 51, 2); print(c); promedio(c)
var d = [].linspace(5, 10, 21); print(d); promedio(d)
El problema resuelto con la estructura for-of, es:
var promedioa = function(x) { const n=x.length; if (n===0) throw "vector vacío"; let s = 0; for (let e of x) s+=e; return s/n; };
promedioa([].range(17, 51, 2))
El problema resuelto con el método forEach, es:
var promediob = function(x) { const n = x.length; if (n===0) throw "vector vacío"; let s = 0; x.forEach(e=>s+=e); return s/n; };
promediob([].range(17, 51, 2))
Como se vio en el anterior capítulo, además del valor del elemento ("e"), forEach manda a la función (en este caso la función flecha: e=>s+=e) el índice (la posición) del elemento actual, así como el array en sí, sin embargo, en este ejemplo, no se reciben esos valores, porque no se utilizan en la función.
El problema resuelto con el método reduce, es:
var promedioc = function(x) { const n = x.length; if (n===0) throw "vector vacío"; return x.reduce((s,e)=>s+e)/n; };
promedioc([].range(17, 51, 2))
En este caso, reduce devuelve la sumatoria, la cual se divide entre el número de elementos para obtener el promedio.
Como sucede con casi todos los métodos iterativos disponibles para arrays, reduce, además del elemento (e), manda el índice y el array, pero como no se emplean en la función, no son recibidos.
Aunque en este caso no es necesario, se puede asignar un valor inicial a reduce (en este caso 0, pues se trata de una sumatoria):
Array.prototype.promedioc = function() { const x = this; const n = x.length; if (n===0) throw "vector vacío"; return x.reduce((s,e)=>s+e, 0)/n; };
[].range(17, 51, 2).promedioc()
Por supuesto, el resultado es el mismo, sólo que ahora el acumulador (s) comienza en 0 (en lugar del valor del primer elemento) y debido a ello, la función es ejecutada una vez más.
El problema resuelto con el método sum, es:
var promediod = function(x) { const n = x.length; if (n===0) throw "vector vacío"; return x.sum()/n; };
promediod([].range(17, 51, 2))
Igualmente, el problema puede ser resuelto con el método map:
var promedioe = function(x) { const n = x.length; if (n===0) throw "vector vacío"; s = 0; x.map(e=>s+=e); return s/n; };
promedioe([].range(17, 51, 2))
Desde el punto de vista de la eficiencia, esta no es la mejor opción, porque map genera un nuevo array con el mismo número de elementos que el array original, sin embargo, en este ejemplo, ese array es simplemente ignorado, porque sólo se requiere la sumatoria (s) de sus elementos.
También se puede emplear el método every:
var promediof = function() { const n = x.length; if (n===0) throw "vector vacío"; s = 0; x.every(e=>(s+=e,true)); return s/n; };
promedio([].range(17, 51, 2))
Como el método every termina cuando el resultado de la función es falso y en este caso es necesario que se itere para todos los elementos, la función debe devolver siempre un valor verdadero (true, 1 o cualquier valor equivalente a verdadero), porque, aunque no es frecuente, el resultado puede ser 0 (cuando se tienen valores positivos y negativos) por lo que, al final, la función debe devolver true (o 1) .
Para ello, dado que la función tiene dos instrucciones, se las encierra entre paréntesis y las instrucciones se separan con comas. No obstante, la función puede ser programada también en la forma tradicional, es decir con llaves y el comando return:
Array.prototype.promediof = function() { const x = this; const n = x.length; if (n===0) throw "vector vacío"; s = 0; x.every(e=>{s+=e; return true}); return s/n; };
[].range(17, 51, 2).promediof()
Igualmente, se puede emplear el método some (que es el complemento de every):
var promediog = function(x) { const n = x.length; if (n===0) throw "vector vacío"; s = 0; x.some(e=>(s+=e,false)); return s/n; };
promediog([].range(17, 51, 2))
En este caso, como some termina cuando el resultado es verdadero, el resultado de la función debe ser siempre falso (false, 0 o cualquier valor equivalente a falso).
De forma similar se pueden emplear los métodos find, findIndex, findLast, findLastIndex y filter. Sin embargo, ninguno de estos métodos es adecuado para resolver este tipo de problemas, porque no han sido creados para ese fin, razón por la cual es necesario forzar la iteración a través de todos sus elementos. Sólo se emplean de esa forma, en estos capítulos, para ayudar a comprender su lógica, pero no deben ser empleados en la práctica, para resolver problemas de este tipo.
Vector de números aleatorios
En este ejemplo se elabora un método que genera un vector con "n" números aleatorios comprendidos entre 1 y 1000.
El problema puede ser resuelto fácilmente con el método rand: simplemente se generan "n" números aleatorios comprendidos entre 1 y 1000 y se redondea el vector resultante, tal como se muestra en la siguiente función:
function rand1000(n) {
if (n%1!==0 || n<0) throw "El número debe ser entero positivo";
return [].rand(n, 1, 1000).round();
};
Llamando a la función con algunos valores de prueba, se obtiene:
randseed = 10;
rand1000(5)
rand1000(10)
rand1000(20)
rand1000(25)
rand1000(-10)
rand1000(5.7)
Si no se tiene acceso al método rand, porque no se está trabajando en la calculadora o no se ha importado la librería array.js, el problema puede ser resuelto empleando la estructura for y la función estándar random.
Para transformar el número aleatorio comprendido entre 0 y 1, que es el resultado devuelto por random, en un número comprendido entre "li" y "ls", se aplica la siguiente expresión:
\[
\begin{aligned}
\text{Nú}&\text{mero aleatorio comprendido entre li y ls}=\\
&(\text{Número aleatorio comprendido entre 0 y 1})\times (\text{ls}-\text{li})+\text{li}
\end{aligned}
\]
Entonces, en cada repetición del ciclo for, que va desde 0 hasta "n-1", se genera y guarda un número aleatorio, como se muestra en el siguiente diagrama de flujo:
gojsGraph({divi, modelo: {"class":"go.GraphLinksModel","linkFromPortIdProperty":"fromPort","linkToPortIdProperty":"toPort","nodeDataArray":[{"category":"Start","text":"rand1000","key":-1,"loc":"172 -460"},{"category":"Input","text":"número de elementos a generar: n","key":-3,"loc":"171.99999999999994 -410.4666427612303"},{"category":"Process","text":"v = []","key":-2,"loc":"171.99999999999997 -359.3332138061521"},{"category":"Process","text":"i = i+1","key":-7,"loc":"57.99999999999987 -250.44982967376689"},{"category":"Start","text":"fin","key":-9,"loc":"172.00000000000009 -63.34418347676573"},{"category":"Output","text":"v","key":-10,"loc":"171.99999999999997 -116.22199312845845"},{"category":"For","text":"i<n","key":-6,"loc":"171.99999999999997 -250.44982967376686"},{"category":"Process","text":"i = 0","key":-12,"loc":"171.99999999999997 -304.79985656738245"},{"category":"Process","text":"v[i] = random()*999+1","key":-13,"loc":"171.99999999999997 -181.09980278015115"}],"linkDataArray":[{"from":-10,"to":-9,"fromPort":"B","toPort":"T","points":[171.99999999999997,-103.5419787851967,171.99999999999997,-93.5419787851967,171.99999999999997,-91.07642044067359,171.99999999999997,-91.07642044067359,171.99999999999997,-88.61086209615047,171.99999999999997,-78.61086209615047]},{"from":-1,"to":-3,"fromPort":"B","toPort":"T","points":[172.00000000000006,-444.73332138061534,172.00000000000006,-434.73332138061534,172.00000000000006,-434.73332138061517,171.99999999999997,-434.73332138061517,171.99999999999997,-434.73332138061505,171.99999999999997,-424.73332138061505]},{"from":-2,"to":-12,"fromPort":"B","toPort":"T","points":[171.99999999999997,-342.06653518676734,171.99999999999997,-332.06653518676734,171.99999999999997,-332.06653518676734,171.99999999999997,-332.0665351867674,171.99999999999997,-332.0665351867674,171.99999999999997,-322.0665351867674]},{"from":-12,"to":-6,"fromPort":"B","toPort":"T","points":[171.99999999999997,-287.53317794799784,171.99999999999997,-277.53317794799784,171.99999999999997,-277.53317794799784,171.99999999999997,-277.53317794799784,171.99999999999997,-277.53317794799784,171.99999999999997,-267.53317794799784]},{"from":-6,"to":-13,"fromPort":"B","toPort":"T","visible":true,"points":[171.99999999999997,-233.36648139953593,171.99999999999997,-223.36648139953593,171.99999999999997,-215.86648139953593,171.99999999999997,-215.86648139953593,171.99999999999997,-208.36648139953593,171.99999999999997,-198.36648139953593],"text":"Si"},{"from":-13,"to":-7,"fromPort":"L","toPort":"B","points":[93.007453918457,-181.09980278015115,83.007453918457,-181.09980278015115,57.99999999999986,-181.09980278015115,57.99999999999986,-202.14147691726663,57.99999999999986,-223.18315105438214,57.99999999999986,-233.18315105438214]},{"from":-7,"to":-6,"fromPort":"R","toPort":"L","points":[85.8365097045897,-250.44982967376689,95.8365097045897,-250.44982967376689,116.06658172607413,-250.44982967376689,116.06658172607413,-250.44982967376689,136.29665374755857,-250.44982967376689,146.29665374755857,-250.44982967376689]},{"from":-6,"to":-10,"fromPort":"R","toPort":"T","visible":true,"points":[197.70334625244138,-250.44982967376689,207.70334625244138,-249.72491483688344,270,-249.72491483688344,270,-152,171.99999999999997,-152,171.99999999999997,-143.83312416076637,171.99999999999997,-133.83312416076637],"text":"No"},{"from":-3,"to":-2,"fromPort":"B","toPort":"T","points":[171.99999999999997,-396.1999641418455,171.99999999999997,-386.1999641418455,171.99999999999997,-386.1999641418455,171.99999999999997,-386.5998924255369,171.99999999999997,-386.5998924255369,171.99999999999997,-376.5998924255369]}]} })
Siendo el código respectivo:
var rand1000 = function(n) { if (n%1!==0 || n<0) throw "El número debe ser entero positivo"; const v= []; for (let i=0; i<n; i++) v[i] = Math.round(Math.random()*999+1); return v; };
randseed = 10;
rand1000(5)
rand1000(10)
rand1000(20)
rand1000(25)
La solución, implementada empleando el método push (en lugar de una asignación directa), es:
var rand1000 = function(n) { if (n%1!==0 || n<0) throw "El número debe ser entero positivo"; const v = []; for (let i=0; i<n; i++) v.push(Math.round(Math.random()*999+1)); return v; };
randseed = 10;
rand1000(5)
rand1000(10)
rand1000(20)
rand1000(25)
El problema puede ser resuelto, también, empleando la estructura for-of:
var rand1000a = function(n) { if (n%1!==0 || n<0) throw "El número debe ser entero positivo"; const v = []; for (const _ of [].zeros(n)) v.push(Math.round(Math.random()*999+1)); return v; };
randseed = 10;
rand1000a(5)
Como el método for-of itera para cada uno de los elementos de un array y en este caso no existe ese array, se crea uno, con Array.from({length:n}). Pero como estos elemento no se emplean en las instrucciones del ciclo, se denota ese hecho empleando la variable "_" para el nombre de los elementos.
Los "n" elementos del array pueden ser generados también con cualquiera de los métodos disponibles: const, range, zeros, etc.
Por ejemplo, con el método forEach y range (para generar el array), la solución es:
var rand1000b = function(n) { if (n%1!==0 || n<0) throw "El número debe ser entero positivo"; const v = []; [].range(n).forEach(()=>v.push(Math.round(Math.random()*999+1))); return v; };
randseed = 10;
rand1000b(5)
Donde, con range, se crea un vector con "n" elementos (del 1 al n) y se llama al método desde ese vector. Como no se emplean los elementos del array, la función no recibe ningún elemento.
El problema resuelto con el método reduce y zeros (para generar el array), es:
var rand1000c = function(n) { if (n%1!==0 || n<0) throw "El número debe ser entero positivo"; return [].zeros(n).reduce(v=>(v.push(Math.round(Math.random()*999+1)),v),[]); };
randseed = 10;
rand1000c(5)
Como no se emplean los elementos del array, la función solo recibe el primer parámetro (el acumulador "v"). En este caso es necesario que el valor inicial del acumulador sea un vector vacío ([]), no el primer elemento del array, para que en cada iteración se le añada un nuevo número aleatorio. La función devuelve el vector "v" (con el valor añadido) para que en la siguiente se le añada otro elemento (hasta que se generan los "n" elementos).
El problema puede ser resuelto, también, con el método some, aunque, como se explicó previamente, no es la opción correcta para este tipo de problemas:
var rand1000d = function(n) { if (n%1!==0 || n<0) throw "El número debe ser entero positivo"; const v = []; [].zeros(n).some(()=>(v.push(Math.round(Math.random()*999+1)),false)); return v; };
randseed = 10;
rand1000d(5)
Igual que en el caso anterior, no se emplean los elementos del array, por lo que la función no recibe nada y para que el método itere para todos los elementos, devuelve siempre false.
De la misma forma, se puede emplear el método every:
var rand1000e = function(n) { if (n%1!==0 || n<0) throw "El número debe ser entero positivo"; const v = []; [].zeros(n).every(()=>(v.push(Math.round(Math.random()*999+1)),true)); return v; };
randseed = 10;
rand1000e(5)
Que es prácticamente igual a la solución anterior, solo que en este ahora (a manera de ejemplo) el array se genera con range y com es every devuelve true.
El problema puede ser resuelto, igualmente, con el método map.
var rand1000f = function(n) { if (n%1!==0 || n<0) throw "El número debe ser entero positivo"; return [].zeros(n).map(()=>Math.round(Math.random()*999+1)); };s
randseed = 10;
rand1000f(5)
Iguamente, como no se emplean los elementos del array, la función no recibe ningún valor, pero en este caso se aprovecha el array generado por map, siendo ese array el resultado de la función.
Como en casi todos los casos, el problema puede ser resuelto también con find, findIndex, findLast, findLastIndex y filter, aunque, como también se dijo, no son los métodos más adecuados para resolver este tipo de problemas.