El contenido de esta entrada no tendrá valor teórico destacable. Su objetivo es analizar el procedimiento para encontrar sumas de números alternados que generen uno dado N. Por alternados entenderemos consecutivos de cierto tipo en los que se suprime uno de cada dos. También podríamos afirmar que “se salta” un elemento y se elige el siguiente.
Por ejemplo, 84=1+9+25+49, y esa
suma es alternada de cuadrados, porque hemos elegido una suma de consecutivos y
le hemos ido suprimiendo un término de cada dos. Los representamos entre
paréntesis:
84=1+(4)+9+(16)+25+(36)+49
Otro ejemplo es el publicado en https://oeis.org/A300395, que contiene
todos los números que se forman con una suma de nueve primos alternados. Por
ejemplo:
521 = 23+31+41+47+59+67+73+83+97
En este conjunto se han ido
suprimiendo los primos 29, 37, 43, 53,…
Queda claro, pues, lo que
entenderemos por alternados.
Un número N puede ser equivalente a
varias sumas de este tipo. Por eso, los algoritmos que busquen dichas sumas
necesitarán dos bucles, pues primero hay que analizar el inicio de la suma y
luego su longitud. Para cada inicio existirán varias posibles sumas, lo que
exige los dos bucles. En este blog hemos usado la función PROXIMO en la entrada
“En el punto medio de dispares” (https://hojaynumeros.blogspot.com/2023/06/en-el-punto-medio-de-dispares.html) para ir
encontrando sumandos del tipo dado si conocemos el primero.
El siguiente listado es el usado
para encontrar el próximo primo, ya que usa la función ESPRIMO, pero se adapta
fácilmente al la búsqueda de otros tipos de números, usando las funciones
ESTRIANGULAR, ESCUBO, ESOBLONGO,…todas usadas en este blog y accesibles con el
comando Buscar.
Function proximo(a) As Long
Dim
p, prim As Long
Dim
sale As Boolean
p = a
+ 1: sale = False: prim = 0
While
Not sale ‘Reitera hasta que aparezca el próximo
If
escuad(p) Then prim = p: sale = True
p = p
+ 1
Wend
proximo
= prim
End
Function
La función PROXIMO puede resultar lenta, por lo que si buscamos una suma alternada para un número N, es muy conveniente guardar en un vector todos los números comprendidos entre 1 y N y que sean del tipo dado. También tiene el peligro de no parar nunca, pero en los casos habituales esto no sucede.
Estructura de un algoritmo
Según las consideraciones
anteriores, para encontrar las sumas deseadas deberemos recorrer tres etapas:
1) Hay que encontrar todos los
posibles sumandos del tipo dado entre 1 y N. Lo explicamos con un ejemplo, el
de encontrar una suma de triangulares consecutivos alternados cuyo resultado
sea 200.
En primer lugar, usando la función
PROXIMO, creamos un vector que contenga todos los triangulares comprendidos entre
1 y 200. Si llamamos s al vector,
tendríamos que s(1)=1, s(2)=3, s(3)=6, …s(18)=171 y s(19)=190. Tomamos nota de
que existen 19 triangulares que pueden ser sumandos.
El uso de un vector nos facilita el
“saltar” un elemento, pues se pasará de s(k) a s(k+2) en cada paso.
2) Se establece un bucle de búsqueda del primer sumando, que comenzará en el 1 y se avanzará hasta 190. En el ejemplo tendríamos que llegar, como veremos, hasta un inicio de 10.
3) Para cada posible inicio de la suma se construirá un segundo bucle que vaya añadiendo un sumando alternado en cada paso. Para ello se irá incrementado el índice en dos unidades cada vez. Si en uno de ellos se alcanza el resultado de N, se habrá conseguido el objetivo. Para el número 200 la solución sería
10+21+36+55+78=200. Habríamos
saltado los triangulares 15, 28, 45, y 66.
Estas fases se pueden implementar en una subrutina para VBasic con objeto de usarla en Excel o Calc.
Rutina en VBasic
El listado que sigue ha sido
diseñado para Excel, pero con un pequeño cambio se adapta a LibreOffice Calc.
fila = 14 ‘O cualquier otro valor
‘Se lee el valor de N y el tipo de
sumando
n =
ActiveWorkbook.Sheets(1).Cells(9, 4).Value
tipo
= ActiveWorkbook.Sheets(1).Cells(29, 8).Value
‘Con el uso de la función PROXIMO se carga un vector con candidatos a sumandos, para acelerar el proceso
i = 0
k = 0
While
a <= n
a =
proximo(a, tipo)
If a
<= n Then i = i + 1: s(i) = a: k = i
Wend
‘Se ha construido el vector s
For i
= 1 To k ‘Bucle para elegir el inicio de la suma
j = i
a =
s(i)
suma
= a
st$ =
Str$(a)
While
suma <= n And j <= k – 2 ‘Bucle para construir una suma
j = j
+ 2 ‘Es importante añadir un 2, para alternar
a =
s(j)
suma
= suma + a ‘Se construye la suma
st$ =
st$ + ", " + Str$(a) ‘Modo texto para la suma
If
suma = n Then
st =
st + " # " + Str$((j - i) / 2 + 1)
‘Se presenta la solución en modo texto
ActiveWorkbook.Sheets(1).Cells(fila,
10).Value = st$
ActiveWorkbook.Sheets(1).Cells(fila,
12).Value = rotulo(tipo)
End
If
Wend
Next
i
End
Sub
En la imagen vemos la forma en la que aparecería la solución en Excel:
Se leerían los sumandos, el número de ellos, 5 en este caso, y el tipo, “Triangulares”. Lo del este último rótulo no lo hemos explicado aquí.
Este algoritmo se podría haber
construido como una función, pero esta vez hemos optado por una rutina, pues
usamos una similar en una de nuestras herramientas.
Uno de los últimos usos, por si
deseas reproducirlo, es comprobar que el número 5623 equivale a la suma de
nueve números primos alternados y que, por tanto, pertenece a la sucesión https://oeis.org/A300395
5623=577+593+601+613+619+641+647+659+673
Si se dispone de varios tipos de números (en mis trabajos uso 17), se podría construir una gran rutina que recorriera varios tipos para buscar sumas. En la siguiente imagen lo hemos aplicado al número 200 con un resultado sorprendente por el número de soluciones:
Entre ellos figura el que hemos usado de ejemplo con triangulares.
Con esta idea finalizamos la entrada, ya que el objetivo era diseñar y explicar un algoritmo.
No hay comentarios:
Publicar un comentario