martes, 25 de febrero de 2020

Suma y producto de cubo y otro tipo (1)



Muchas de las entradas de este blog surgen de los cálculos diarios que publico en Twitter (@Connumeros). El que sigue nos va a dar materia para más de una entrada.

El día 21/5/19 obtuve esta propiedad:

El número de fecha de hoy, 21519 se descompone en un producto de un cubo por un capicúa y también en una suma del mismo tipo:
21519=3^3×797
21519=12^3+19791

No sabía en ese momento si existirían muchos números que compartieran las dos expresiones N=p^3*q y N=r^3+s, y parece que sí, que son abundantes.

Para acotar la búsqueda, exigiremos que los cuatro números p, q, r y s sean enteros positivos. La exclusión del 0 evita casos triviales.

Al iniciar el estudio he pensado que el número que acompaña al cubo puede ser cuadrado o triangular, por ejemplo, en lugar de capicúa. Esto amplía el estudio y por eso es posible que se necesiten varias entradas.

Suma y producto de cubo y capicúa

La primera condición, N=p^3*q, permite desechar aquellos números N que no sean múltiplos de un cubo. Esto se logra fácilmente con la descomposición factorial y el estudio de los exponentes de los factores primos. El inconveniente es que en un blog como este se alargaría mucho la explicación del procedimiento para crear nuestra función FACTORES y la rutina SACAPRIMOS. Por eso, y no es nuevo en estas entradas, emprenderemos la búsqueda con medios más sencillos. El peligro estribaría en la lentitud, pero no es inconveniente en este caso. Con Excel se consiguen listas con una rapidez aceptable.

Comenzamos, como es usual en estas búsquedas, con la creación de una función, a la que llamaré CUBOYOTRO, que nos indique si un número N cumple los dos requisitos N=p^3*q y N=r^3+s. Su estructura nos va a permitir adaptarla a todos los casos que estudiemos, pues bastará sustituir la función ESCAPICUA (para el caso inicial) por ESCUAD, ESTRIANGULAR u otra. En cada tipo explicaremos estas funciones auxiliares. Comenzamos con los capicúas. La función recomendada es la siguiente:

Public Function cuboyotro$(n, k) ‘Añadimos un parámetro k por si deseamos cambiar cubo por otra potencia
Dim x, a, y, b, c
Dim s$


s$ = "" ‘Usamos un string para presentar bien los cuatro números p, q, r y s
a = n ^ (1 / k) ‘En este primer caso k valdrá 3. La variable a es el tope de búsqueda
For x = 1 To a
c = n - x ^ k ‘Se resta del número la potencia (en el primer ejemplo, un cubo)
If escapicua(c) And c > 10 Then ‘Más adelante se cambiará ESCAPICUA
For y = 2 To a ‘En esta parte ya se ha cumplido la segunda condición N=r^3+s
If n Mod y ^ k = 0 Then ‘Para la primera condición p^3 ha de ser un divisor de n
b = n / y ^ k
If escapicua(b) and b>10 Then ‘Si el cociente es capicúa, se publica la solución
s$ = " C1 " + Str$(x) + " O1 " + Str$(c) + " C2 " + Str$(y) + " O2 " + Str$(b)
‘El string nos presenta los cubos C1 y C2 y sus compañeros O1 y O2.Puede haber más soluciones.
End If
End If
Next y
End If
Next x
If s$ = "" Then s$ = "NO" ‘Asignamos un “NO” al caso sin solución
cuboyotro = s$
End Function

Hay que advertir algún detalle sobre esta función.

La decisión de evaluar en primer lugar la segunda condición y después la primera no ha sido deliberada, y de hecho, poco eficiente, pues si se  cambia el orden se incrementa la velocidad de respuesta de la función. Como resulta rápida así, no se ha corregido y lo dejamos como ejercicio.

Este esquema es la base para otras búsquedas. Ya se ha destacado que con un cambio de ESCAPICUA por otra función se podrían abordar otros casos. Igualmente, aunque en lo que sigue haremos k=3 para buscar cubos, se deja abierta la posibilidad de aumentar el exponente.

La función ESCAPICUA se inserta en el Anexo del final de esta entrada. La costumbre es considerar capicúas los números de una cifra, pero aquí no nos interesa esta posibilidad, pues aparecen casos sin interés. Exigiremos que sean mayores que 10, como puedes comprobar en el listado de la función.

Los primeros números con esta propiedad son


Junto a cada uno se presentan los cubos C1 y C2 y el otro componente, en este caso capicúa, en O1 y O2.

Por ejemplo, 2176=4^3+2112=2^3*272, dos cubos y dos capicúas.

En PARI

Al tener que cumplir varias condiciones, el listado para PARI resulta algo extenso, pero es bastante rápido en su ejecución.

maxexpo(n) = s=1; f=factor(n); for(i=1, matsize(f)[1], t=f[i,2]; if(t>>s, s=t)); s
palind(n)=n==eval(concat(Vecrev(Str(n))))
condi1(n)= c=0; if(maxexpo(n)>=3,  a=n^(1/3); for(x=2, a, if(n%x^3==0,b=n/x^3;if(palind(b)&&b>=10,c=x))));c
condi2(n)= c=0; a=n^(1/3); for(x=2, a, b=n-x^3;if(palind(b)&&b>=10,c=x));c
for(y=2,20000, if(condi1(y)&&condi2(y),print1(y,", ")))

Con él podemos reproducir y ampliar la lista de arriba:

528, 704, 888, 1128, 1208, 1375, 1408, 1616, 1696, 1856, 2176, 2424, 2727, 2904, 2984, 3064, 3552, 3632, 3773, 3952, 4280, 4347, 4440, 4520, 4752, 5488, 5568, 5736, 5994, 6296, 6336, 6464, 6784, 7352, 7752, 8181, 8384, 8888, 10071, 10944, 11000, 11264, 11319, 12224, 12798, 13635, 13875, 14168, 14641, 15928, 16128, 16362, 16375, 17172, 18048, 18656, 19008, 19536, 19629, 19899,…

Hay que recordar que todos ellos son múltiplos de un cubo con base no trivial  y, por tanto, todos son compuestos. Entre ellos aparecen casos particulares interesantes. Por ejemplo:

Números del tipo p^3*11 o p^3*101. En estos dos casos y otros similares, el capicúa correspondiente al producto es un número primo, como ocurre en 704=4^3*11=2^3+696.

Caso del 14641: Como equivale a 11^4, su desarrollo sería 11^3*11. Hay que esperar que pertenezcan a este listado potencias de primos, aunque sin buscarlos no se puede asegurar. Por ejemplo, 101^4 cumple la primera condición (producto), pero no es suma de cubo y capicúa. El siguiente es 40353607, que es potencia de primo (40353607=7^9) y se descompone en producto de cubo y capicúa (40353607=49^3*343) y en suma de cubo y capicúa (40353607=334^3+3093903). Hasta una cota de 8*10^7 ya no hay más casos.

El número 14641 es capicúa. Podríamos preguntarnos si existen más capicúas en la sucesión. En la primera tabla hemos visto algún capicúa. Los primeros son: 888, 3773, 6336, 8888, 14641, 80008, 88088,…

Por ejemplo, 3773 es capicúa, y equivale a 11^3+2442 y a 7^3*11.
Igualmente, el capicúa 6336 es igual a 11^3+5005 y a 4^3*99.

Finalmente, destacamos el número 74088, que es el cubo de 42, y también coincide con la suma de otro cubo y un capicúa, 35^3+31213, y también con un producto similar, 6^3*343. Esto es posible por ser 343 capicúa y cubo de 7.
Se podría buscar más casos particulares, pero es preferible pasar a otras estructuras, que dejaremos para la siguiente entrada.

ANEXO

Código de la función ESCAPICUA

Public Function escapicua(n) As Boolean
Dim l, i, k
Dim c As Boolean
Dim auxi$,nn$

nn$ =Str$(n)

auxi= Right(nn$, Len(nn$) - 1)
l = Len(auxi)
c=True
If l >1 Then
c = True
i = 1
k = Int(l / 2)
While i <= k And c
  If Mid(auxi, i, 1) <> Mid(auxi, l - i + 1, 1) Then c = False
  i = i + 1
  Wend
End If
escapicua = c
End Function


jueves, 13 de febrero de 2020

Uso de la fuerza bruta



El día 29/12/19 descubrí este tweet de @d_r_o_n_e:


En él podemos ver un ejemplo que puede reproducirse mediante el uso de la “fuerza bruta”, herramienta que aparece en este blog muchas veces, aunque no se confiesen todas. Consiste en recorrer todas las variantes de un problema sin usar razonamientos ni condiciones complementarias. Es una buena estrategia comenzar con esta forma de buscar para después ir afinando resultados, explicarlos y, si es posible, justificarlos.

Uso de la herramienta Cartesius

Nuestra herramienta Cartesius también ayuda a combinar variables de todas las formas posibles, pero se hace lenta cuando nos acercamos al rango de los números de cuatro cifras. La puedes descargar desde


Con ella hemos intentado este planteo:

XTOTAL=3
XT=1..200
ES X1*X2*X3/1000=X1+X2+X3
CRECIENTE

Es fácil entender su significado: combinaremos tres variables, todas entre 1 y 200, de forma que se cumpla la condición pedida y después nos quedamos con las crecientes. Al cabo de más de media hora se obtuvo esta tabla, completada en sus dos últimas columnas con las dos expresiones que deben coincidir.


Observamos, y lo confirmaremos un poco más abajo, que aparecen repetidas algunas soluciones menores que 444, como son 231 o 240. Con el planteo propuesto se encontraron 32 soluciones, de las que solo hemos reproducido las primeras. Aparecen en orden inverso al natural porque cuando unos factores tienen igual suma, su producto crece cuando sus diferencias son menores. Con este intento descubrimos ya que la técnica de la “fuerza bruta” es muy lenta en producir resultados.

Analizando la búsqueda descubrimos que Cartesius ha tenido que analizar 200*200*200 =8*10^6 números, y en cada uno calcular si una igualdad se verifica o no. Eso es mucho para un portátil normal. Ahí es donde falla la fuerza bruta, en la multiplicación de casos que produce la Combinatoria.

Algoritmos

La “fuerza bruta” se caracteriza casi siempre por el uso de bucles del tipo FOR_NEXT, WHILE o REPEAT, casi siempre anidados en tres o cuatro niveles.
Lo normal, en ejemplos similares al que nos ocupa, es disponer de tres bucles anidados, con la propiedad deseada en el interior de los tres. Comenzaremos exigiendo solo una condición de las propuestas por @d_r_o_n_e

En este caso podíamos comenzar por este código:

Sub fuerzabuta()
Dim i, j, k, a, b, fila

fila = 10   ‘La fila determina la construcción de una tabla en Excel
For i = 1 To 1000  ‘Bucle triple
For j = 1 To i
For k = 1 To j
a = i + j + k  ‘Cálculos previos
b = i * j * k / 1000
If a = b Then  ‘Condición pedida
fila = fila + 1: ‘Construcción de la tabla
ActiveWorkbook.ActiveSheet.Cells(fila, 2).Value = b
ActiveWorkbook.ActiveSheet.Cells(fila, 3).Value = i
ActiveWorkbook.ActiveSheet.Cells(fila, 4).Value = j
ActiveWorkbook.ActiveSheet.Cells(fila, 5).Value = k
End If
Next k
Next j
Next i
End Sub

Hemos ejecutado esta macro de Excel y nos han resultado muchas soluciones. Lo que nos interesa es que salgan repetidas. Por la forma de plantear el problema, aparecerán desordenadas. Las primeras han sido:



Coinciden con las obtenidas en Cartesius. Observamos su falta de orden y la existencia de un repetido, el 189. Según la tabla:

189=84+75+30=84*75*30/1000
189=100+54+35=100*54*35/1000

Es una solución también más pequeña que la propuesta de 444.

Para verlas todas ordenaremos la columna y así se verán mejor los repetidos. Con este método hemos descubierto los siguientes: 189, 207, 231, 240, 255, 273, 297, 420, 444, 480, 504, 741, 759, 768, 810, 891,… De ellos presentan soluciones triples 231, 504 y 891.


Más fuerza bruta (o menos)

Podíamos intentar descubrir tan solo los números en los que se da más de una solución. El problema es que para esto se necesitaría un bucle más, con el consiguiente aumento de tiempo de proceso. Es el coste de utilización de bucles múltiples sin apenas condicionamientos. Hay una forma de evitar un nuevo bucle, y es considerar que en el algoritmo anterior hemos hecho variar el valor de k cuando en realidad está condicionado por la igualdad que se pide a=i+j+k. Considerándolo así, lo único que ha de cumplir k es que su valor sea a-i-j y, por cuestión de unicidad, que no sea mayor que j. Esto es lo que hemos implementado en PARI:

for(n=1,500,m=0;b=0;for(i=1,n,for(j=1,i,c=i+j;if(c<=n&&n-c<=j,b=i*j*(n-c)/1000;if(b==n,m+=1))));if(m>1,print1(n,", ")))

Mantenemos los bucles con las variables i y j. Eliminamos el bucle de k sustituyéndolo por la expresión b=i*j*(n-c)/1000 y concretamos las condiciones que ha de cumplir. Con la variable m exigimos que haya repetición de casos. Hemos añadido un nuevo bucle, pero con los cambios apenas se resiente la velocidad del proceso. De todas formas, para rangos de números de 1000 más o menos, puede tardar muchos minutos o incluso más de una hora. Cosas de la fuerza bruta.

Los primeros resultados son:

189, 207, 231, 240, 255, 273, 297, 420, 444, 480, 504, 741, 759, 768, 810, 891, 1221, 1320, 2418,…

Con esto damos por terminada la búsqueda, porque la fuerza bruta cansa y no se aprende mucho con ella.

Rebajamos pretensiones

Podíamos exigir productos similares, pero con solo dos variables, es decir, N=i+j=i*j/100. Esto simplifica el problema, y solo lo incluimos como repaso de las técnicas empleadas anteriormente. Las explicaciones para el caso anterior valen también para este.

Con Cartesius

Plantearíamos, por ejemplo:

xtotal=2
xt=1..700
es x1+x2=x1*x2/100
creciente

Obtendríamos:



Las primeras columnas corresponden a los valores de i, j y las siguientes el valor repetido de N.

Así, 120+600=120*600/100=720
125+500=125*500/100=625

En principio, no parece que existan soluciones dobles.

Con una función de Excel:

Function esmultiple2(n)
Dim i, j, k, a, b, m

m = 0
For i = 1 To n
For j = 1 To i
a = i + j
b = i * j / 100
If a = b And a = n Then m = m + 1
Next j
Next i
esmultiple2 = m
End Function

Esta función cuenta las veces en las que se da la igualdad i+j=i*j/100. Organizando una búsqueda nos resulta:



Tampoco se aprecian repetidos

Con PARI

Traducimos la función anterior a PARI y la integramos en un bucle de búsqueda:

for(n=1,10000,m=0;b=0;for(i=1,n/2,b=i*(n-i)/100;if(b==n,m+=1));if(m>0,print1(n,", ")))

Volvemos a obtener los mismos resultados:

400, 405, 450, 490, 625, 720, 841, 1210, 1458, 2205, 2704, 5202,…

Tampoco aquí se detectan repetidos. Lo dejamos como complemento.

lunes, 3 de febrero de 2020

Números de Ulam




Se llaman números de Ulam a los que forman una sucesión construida de la siguiente forma:

Se declara u(1)=1 y u(2)=2 (veremos que esto se puede alterar) y después definiremos u(n+1) como el primer número que se pueda expresar como suma de dos números de Ulam anteriores distintos, de forma única.

Los creó el matemático polaco Stanislaw Ulam y los publicó en SIAM Review en 1964.

Puedes ampliar este concepto en las páginas




El 1 y el 2 se toman de forma arbitraria. El siguiente deberá ser el 3, ya que 3=1+2 de forma única. También está claro que el cuarto debe ser 4=1+3, pues 4=2+2 no sería válido por ser iguales los sumandos.

Deberíamos rechazar el 5, pues 5=1+4=2+3. El 6 sí nos vale, pues 6=2+4, siendo no válida la suma 6=3+3.

Por tanto, los primeros términos de la sucesión de Ulam serán 1, 2, 3, 4, 6. Es sencillo buscar los siguientes: 8, 11, 13, 16, 18, 26,…

Tienes más elementos en http://oeis.org/A002858, junto con una gran cantidad de comentarios sobre estos números. Aquí nos interesarán aspectos algorítmicos. 

Veamos alguno:

Encontrar el número de Ulam de orden N

Siguiendo la costumbre de este blog, resolveremos la cuestión a través de una función que nos devuelva el término enésimo de la sucesión. Esto tiene el inconveniente de que hay que ir tomando nota de los términos anteriores. Los lenguajes avanzados lo resuelven mediante una lista, tal como veremos en PARI. 

En hoja de cálculo se pueden construir fácilmente listas mediante las columnas, usando una variable que recuerde el número de términos de la lista y unos procedimientos para escribir y leer en ella. No es complicado. Ya lo usamos en otra sucesión, la de Mian-Chowla:


Aquí lo implementaremos de forma más simple, dimensionando un vector con 2000 componentes. El inconveniente es que no podremos pasar de esa cantidad, salvo que modifiquemos la dimensión, pero resulta más manejable.

Una vez determinemos la lista, en este caso u(2000), rellenaremos en primer lugar los elementos u(1)=1 y u(2)=2. Después habrá que ir probando los siguientes números hasta ver si proceden de una suma única de elementos distintos o no. Crearemos una variable m que cuente las sumas posibles, y si vale 1, incorporamos un nuevo elemento a la lista. Al llegar a n elementos, paramos el cálculo y devolvemos ese resultado. El código de la función para Excel y Calc es el siguiente, en el que hemos añadido los parámetros a y b por si deseamos iniciar la sucesión en otro par de números que no sean 1, 2:

Public Function ulam(a, b, n)
Dim u(2000) ‘Usamos un vector o matriz, pero puede ser una lista
Dim i, j, k, m, uu
Dim noes As Boolean

u(1) = a: u(2) = b ‘Se rellenan los primeros términos
If n = 1 Or n = 2 Then ulam = u(n): Exit Function ‘Primeros dos casos
For i = 3 To n
noes = True
uu = u(i - 1) + 1 ‘La variable uu recorre los números de Ulam previos
While noes
m = 0
For j = 1 To i - 1
For k = j + 1 To i - 1
If j <> k And u(j) + u(k) = uu Then m = m + 1 ‘Cuenta las sumas distintas
Next k
Next j ‘A continuación actúa cuando la suma es única
If m = 1 Then u(i) = uu: noes = False Else uu = uu + 1
Wend
Next i
ulam = uu
End Function

En la siguiente tabla, mediante esta función, hemos representado los 20 primeros números de Ulam:



Recuerda que solo podremos actuar sobre los 2000 primeros, tal como hemos definido la función. Este inconveniente no existe si usas lista en el lenguaje PARI. En el siguiente listado observarás que se comienza creando la lista v: “my(v=List(),” y, después, para incorporar un elemento a la lista se usa “lisput”. Lo que sigue es difícil de leer, pero se puede comprobar que contiene las mismas ideas que en la función de Excel, con alguna ligera variante. Esta es la función propuesta:


ulam(n)=my(v=List(),i,j,k,o,uu,m);listput(v,1);listput(v,2);for(i=3,n,o=1;uu=v[i-1]+1;while(o==1,m=0;for(j=1,i-1,for(k=j+1,i-1,if(v[j]+v[k]==uu&&j<>k,m+=1)));uu+=1;if(m==1,uu=uu-1;listput(v,uu);o=0)));uu

Por no complicar más (ya es bastante oscuro), no hemos implementado la función para n=1 o n=2, por lo que el listado general comenzará en el 3:



Así que con esta función podemos crear la lista de los números de Ulam, pero nos puede interesar también si un número es de Ulam o no. Por ejemplo, ¿Qué número de Ulam sigue al 200?

Para ello disponemos de otra función basada en la anterior. Se podían refundir ambas en una sola, pero no compensaba el esfuerzo. La orientación que se propone aquí es más lenta, pero más fácil de entender.

Ver si un número es de Ulam

Llamaremos esulam a una función que nos devuelva un 0 si el número propuesto no pertenece a la sucesión de Ulam y que nos dé su número de orden en caso de que pertenezca.

Public Function esulam(a, b, n)
Dim i, uu, k


If n = a Then esulam = 1: Exit Function ‘Caso u(1)
If n = b Then esulam = 2: Exit Function  ’Caso u(2)
i = 3: k = 0: uu = 0
While uu <= n ‘Busca elementos menores que n
uu = ulam(a, b, i)
If uu = n Then k = i  ‘Si se llega a n, es que pertenece, y se toma nota del orden k. Si no, k=0
i = i + 1
Wend
esulam = k
End Function

Con esta función averiguamos que el primer número de Ulam posterior al 200 es el 206:

 
Los primeros números de Ulam que son números primos son:2, 3, 11, 13, 47, 53, 97, 131, 197, 241, 409, 431, 607, 673, 739, 751, 983, 991, 1103, 1433, 1489.

Como ejercicio, puedes comprobar los siguientes listados de números de Ulam que cumplen otras condiciones:

Cuadrados: 1, 4, 16, 36, 324, 400, 441,…
Triangulares: 1, 3, 6, 28, 36, 253,…
Capicúas (contando los de una cifra): 1, 2, 3, 4, 6, 8, 11, 77, 99, 131, 282, 363, 414, 434, 585, 646,…

Otras sucesiones de Ulam

Podemos cambiar los valores iniciales 1 y 2 por otros (por eso se incluyeron los parámetros a y b en nuestras funciones). A continuación se copian algunas, con indicación de su número en OEIS:

(a,b)       Dirección          Sucesión
(1, 2)      A002858              1, 2, 3, 4, 6, 8, 11, 13, 16, 18, ...
(1, 3)      A002859              1, 3, 4, 5, 6, 8, 10, 12, 17, 21, ...
(1, 4)      A003666              1, 4, 5, 6, 7, 8, 10, 16, 18, 19, ...
(15)        A003667              1, 5, 6, 7, 8, 9, 10, 12, 20, 22, ...
(2, 3)      A001857              2, 3, 5, 7, 8, 9, 13, 14, 18, 19, ...
(2, 4)      A048951              2, 4, 6, 8, 12, 16, 22, 26, 32, 36, ...
(2, 5)      A007300              2, 5, 7, 9, 11, 12, 13, 15, 19, 23, ...

Con esto terminamos. No parece que este estudio dé para más.