En la anterior entrada se desarrolló un ejemplo de particiones condicionadas con Cartesius y un Buscador. Consistía en descomponer el número 50 en sumandos cuadrados, sin importar el número de ellos que usemos, pero que no pasara de 3. Las soluciones resultaron ser 50=25+16+9=25+25=49+1
Ahora repetiremos el ejemplo con
las herramientas del lenguaje PARI.
En PARI se cuenta con la función
FORPART, que recorre una partición cualquiera, en la que se pueden integrar
condicionantes. Para el ejemplo actual valdría este código:
a(n) = {nb = 0; forpart(p=n, if (#p &&
(#select(x->issquare(x), Vec(p)) == #p), nb+=1;print(p)), , 3);nb; }
print(a(50))
Cuesta entender todo lo escrito,
pero consiste en iniciar un contador nb, recorrer todas las particiones
con forpart y condicionarlas con x->issquare(x). El 3
que aparece es el tope para el número de elementos de la partición. Finaliza
incrementando el contador e imprimiendo resultados. Así queda en la página
oficial de PARI:
Coincide con las anteriores herramientas
Segundo ejemplo
Encontrar el número de
particiones de un número en números primos sin otro condicionamiento. Por
ejemplo, con el número 20:
Utilizamos el código PARI
siguiente:
a(n) = {nb = 0; forpart(p=n, if (#p &&
(#select(x->isprime(x), Vec(p)) == #p), nb+=1), , ); nb; }
print(a(20))
Lo probamos y resulta que son 26:
Si deseamos ver las 26 particiones, le añadimos un print(p) detrás de nb+=1. Observa la imagen:
Con el Buscador se puede comprobar. Basta corregir las líneas de filtro, usando ESPRIMO en lugar de ESCUAD. Se omiten los detalles, ya explicados en la anterior entrada.
Se ha usado como tope el 10, que es máximo número posible de sumandos primos.
Nos puede interesar aplicar otra
condición. En el ejemplo anterior se podría exigir que los primos fueran
pitagóricos, del tipo 4k+1. Resultaría:
Se ha añadido la condición x%4==1 (el signo % significa MÓDULO)
Partición con sumandos
coprimos
He encontrado este ejemplo en https://oeis.org/A000837,
y lo uso para resaltar la economía de medios del lenguaje PARI. He adaptado el
código a este documento:
s=0;forpart(X=20, s+=(gcd(X)==1);print(s))
Con esta simple línea encontramos
que existen 582 particiones en las que el conjunto de sumandos posee MCD igual
a 1 (no se afirma que sean primos dos a dos). Aquí, la condición fundamental es
gcd(X)==1
Función Q(n)
Se denomina así al número de
particiones de un número en elementos distintos. Recordamos aquí que estas
particiones son sencillas de encontrar con Cartesius. Basta usar la condición
NO REPITE.
Estas son las condiciones para
las particiones del número 10 en sumandos distintos:
xrango=10
xt=1..10
no repite
suma=10
creciente
Su solución es
Son diez en total, pero el proceso resulta lento e inestable.
En OEIS (https://oeis.org/A000009)
se incluye este código PARI:
{a(n) = my(c); forpart(p=n, if( n<1 ||
p[1]<2, c++; for(i=1, #p-1, if( p[i+1] > p[i]+1, c--; break)))); c}; /* Michael Somos, Aug 13 2017 */
Es algo oscuro a la hora de
entenderlo, pero funciona:
En el elemento correspondiente al
10 observamos que Q(10)=10, tal como resultó en Cartesius.
Con el Buscador
Anulamos los filtros o
restricciones, pero en el momento de llegar a la suma de la partición añadimos
esta condición:
vale =
True
If pp
> 1 Then
For j =
2 To pp
For k =
1 To j - 1
If
su(e(j)) = su(e(k)) Then vale = False
Next k
Next j
End If
If vale Then
De esa forma, sólo nos devolverá las particiones con elementos distintos:
Según un importante teorema ya
visto en este blog, el número de estas particiones coincide con las conseguidas
si se restringen los sumandos a ser impares.
En el ejemplo del 10 nos
resultarían, como era de esperar, 10 particiones con este código:
a(n) = {nb = 0; forpart(p=n, if (#p &&
(#select(x->x%2==1, Vec(p)) == #p), nb+=1;print(p)), , 3);nb; }
print(a(10))
Con Cartesius bastarían las condiciones
xrango=10
xt=1..10
xt=filtro(impar)
suma=10
creciente
No es recomendable por su
lentitud.
Sin más explicaciones, este sería
el resultado si eliminamos los sumandos pares:
Particiones con un número par o impar de sumandos
En estos ejemplos usaré PARI:
Con un número par:
Es importante la parte #p%2==0,nb+=1,
pues % es la operación MODULO y nos indica que la partición tiene un número par
de elementos #p.
a(n) = {nb = 0; forpart(p=n, if(#p%2==0,nb+=1),
, ); nb; }
print(a(20))
Nos resulta que existen 317
particiones con un número par de elementos. Si deseamos datos de los primeros
números obtendremos:
Coinciden con los publicados en https://oeis.org/A027187
Particiones con número impar
de elementos:
Bastaría cambiar #p%2==0
por #p%2==1:
Publicados en https://oeis.org/A027193
Podemos usar ambas situaciones en
funciones separadas, y experimentar algo con ellas. Por ejemplo, que las de
número par sean dos más que las de impar:
a(n)
= {nb = 0; forpart(p=n, if(#p%2==0,nb+=1), , ); nb; }
b(n)
= {nb = 0; forpart(p=n, if(#p%2==1,nb+=1), , ); nb; }
for(i=1,100,
if(a(i)==b(i)+2,print1(i,”, “)))
No tiene mucho interés, porque en
los primeros números solo se cumple en el 8 y el 10.
También se pueden contar por
separado las particiones de cardinal par y las de impar en la misma función. La
siguiente busca si el número de particiones de orden par es dos unidades mayor
que las de impar en un mismo número n.
c(n) = {my(nb = 0,na=0);forpart(p=n,
if(#p%2==0,nb+=1,na+=1,), , ); nb==na+2 }
for(i=1,30, if(c(i)==1,print1(i,”, “)))
Escasean también los resultados.
Lo dejamos aquí. Ya se ha abierto
una puerta a más experimentaciones.
Unos detalles para finalizar
PARI posee la función numbpart,
que cuenta el número de elementos de una partición. Este código elabora un
listado de los números con un número par de particiones distintas:
a(n)={my(c);c=numbpart(n);if(c%2==0,return(c))}
for(i=1,50,if(a(i)>0,print1(i,",
")))
Particiones con producto acotado
En la primera parte de la
instrucción forpart se puede incluir toda una línea de código.
Esto permite calcular productos en las particiones y condicionarlos.
Por ejemplo, lo siguiente
encuentra aquellas particiones de n=5 cuyo producto es mayor que 3. Es
importante destacar la forma en la que hay que usar las distintas partes de una
partición con Vec(p)[k]):
a(n)
= { nn=0; forpart(p=n, pp=1;for(k=1,#p,pp=pp*Vec(p)[k]);if(pp>3,nn+=1;print(p);p));nn
}
print(a(5))
Resultado:
Otro ejemplo: podemos reproducir el contenido de https://oeis.org/A319005
Number
of integer partitions of n whose product of parts is >= n.
Usaremos
a(n)
= {nn=0; forpart(p=n, pp=1;for(k=1,#p,pp=pp*Vec(p)[k]);if(pp>=n,nn+=1));nn }
for(i=1,30,print1(a(i),",
"))
Resultado:
Con estos ejemplos se reconoce la enorme capacidad de PARI
para manejar particiones. Paramos ejemplos por ahora.



















