Mostrando entradas con la etiqueta Algoritmos. Mostrar todas las entradas
Mostrando entradas con la etiqueta Algoritmos. Mostrar todas las entradas

lunes, 29 de junio de 2026

Números de pastel

Estos números constituyen una extensión natural de los traducidos como “Catering perezoso” (o también como “Cortador perezoso”), que ya se han estudiado en este blog. Si aquellos contaban el máximo de cortes rectilíneos sobre una tarta o pizza, considerados en dos dimensiones (todos frontales a la superficie mayor de la tarta), aquí se trata de cortar un cubo o una tarta mediante cortes planos que actúan sobre tres dimensiones. Buscaremos siempre el número máximo de partes, por lo que no se consideran planos paralelos, ni cortes paralelos, ni varios planos incidentes en el mismo punto.

Siguiendo las ideas de Peter C. Heinig en https://oeis.org/A000125, podemos contemplar tres escalas de complejidad en estos cortes:

Una dimensión, cortes sobre una recta. Es evidente que el número máximo de regiones para n cortes es

C1(n)=binomial(n,0)+binomial(n,1)=1+n

En el caso de un plano, vimos, en la sucesión de catering perezoso, https://hojaynumeros.blogspot.com/2026/02/el-catering-perezoso.html, que el número era: n(n+1)/2+1, que también se puede escribir como

C2(n)= binomial(n,0)+binomial(n,1)+binomial(n,2)

En nuestro caso actual, sobre tres dimensiones, es fácil razonar que su expresión es C(n+1,3)+n+1=(n+1)n(n-1)/6+n+1, lo que nos llevaría a

C3(n) = binomial(n,0) + binomial(n,1) + binomial(n,2) + binomial(n,3)

Lo vemos:

Una tarta, con el corte mediante un solo plano se divide en dos partes, y se cumple C(1)=0+1+1=2

Para dos cortes obtenemos cuatro partes como máximo, y se cumple:

C(2)=3*2*1/6+2+1=4

Aquí podemos seguir por inducción: Supongamos efectuados los n-1 cortes primeros. Al cortarlos con un nuevo plano, si ese número es máximo, se formarán en el nuevo plano el máximo de cortes posible, que sabemos que es C2(n-1), y serían elementos de la sucesión del catering perezoso, luego C3(n)= C3(n-1)+C2(n-1), y quedaría:

C3(n)= C3(n-1)+(n-1)n/2+1=n(n-1)(n-2)/6+n+(n-1)n/2+1

Mediante el programa wxMaxima comprobamos la identidad entre este resultado y el propuesto. En el recorte de pantalla observamos además que las expresiones se pueden simplificar bastante:

Por una parte, hemos obtenido una fórmula manejable:

Por otra, se ha comprobado en el razonamiento que C3(n)= C3(n-1)+C2(n-1) y, por tanto, que es válida la sugerencia de:

C3(n) = binomial(n,0) + binomial(n,1) + binomial(n,2) + binomial(n,3)

Con esta comprobación se ha descubierto también que estos números son la suma de los cuatro primeros elementos de la fila n del triángulo de Pascal:

Esta propiedad nos permite identificar los números de pastel con el número de subconjuntos de un conjunto de n elementos cuyo cardinal no supere los tres elementos. Expresado de otra forma, la suma del número de combinaciones de n elementos tomados de 0, 1, 2 o 3 elementos.

Al igual que ocurría con la sucesión del catering perezoso, la existencia de una fórmula tan directa hace inútil la búsqueda de otro algoritmo o función. Basta organizar una tabla con esa fórmula:



Coinciden los valores extraídos del triángulo de Pascal y con los publicados en https://oeis.org/A000125,

 Recurrencia

Con la fórmula básica se puede llegar a números de orden grande, pero quizás se prefiera una recurrencia por la rapidez de cálculo. En la página de OEIS citada se propone la siguiente:

a(n) = 4*a(n-1) - 6*a(n-2) + 4*a(n-3) - a(n-4).

Bastará, pues, crear una columna con los cuatro primeros en una hoja de cálculo y después aplicar la fórmula a esos cuatro y rellenar hacia abajo hasta el punto que deseemos.

Comienzo:



Escribimos los cuatro primeros, y al quinto le aplicamos la fórmula de recurrencia.

Segundo paso

Rellenamos hacia bajo la fórmula:

De esta forma, en segundos, llegamos al orden que deseemos:

Las recurrencias lineales son muy útiles para construir tablas de forma casi instantánea.

 

jueves, 18 de junio de 2026

Triángulo trinomial

Al igual que construíamos el triángulo de Pascal para binomiales sumando cada dos consecutivos, podemos definir el triángulo trinomial si cada coeficiente es la suma de los tres situados en la fila anterior y sobre él. Los coeficientes de los extremos serán suma de dos o de uno, como si a izquierda y derecha del triángulo existieran ceros. Así quedaría con una hoja de cálculo.

 


A diferencia de los binomiales, estos coeficientes del triángulo forman filas de longitud impar, 2n+1, por lo que se puede hablar siempre de términos centrales, que en la imagen son 1, 1, 3, 7 y 19.

Este proceso equivale a la siguiente recurrencia:

Como curiosidad, John D. Cook relaciona estos números con los pasos del rey en el ajedrez para llegar a las distintas posiciones


 (ver
https://www.johndcook.com/blog/2025/05/16/trinomial-coefficients-and-kings/)

Este triángulo posee diversas propiedades, tal como ocurría con el binomial. Por ejemplo, la primera diagonal de la izquierda contiene los números naturales, 1, 2, 3, 4, … y la segunda los triangulares, 1, 3, 6, 10, 15, …Igualmente, si en los binomiales la suma por filas era 2n, aquí es 3n. Por ejemplo, 1+3+6+7+6+3+1=27=33

Estos números se pueden interpretar también como los coeficientes de la potencia (1+x+x2)n

Por ejemplo, para n=4 nos queda, en wxMaxima:

Los coeficientes coinciden con los de la fila 4 del triángulo.

Para distinguir estos coeficientes de los binomiales, se suele añadir un 2 a la derecha de su símbolo. El resto queda igual porque vemos que dependen de solo dos parámetros. Así que, a partir de ahora, los representaremos así:

En ese símbolo k es un entero que cumple -n ≤ k ≤ n, por lo que puede tomar valores negativos. Lo podemos interpretar como la diferencia entre el lugar central de la fila y el del término definido.

Cálculo directo

Según la Wikipedia, existe una fórmula para el cálculo directo:



Usa un sumatorio algo complicado, por lo que es más directo y formativo el seguir la recurrencia definida.

Por recurrencia

El esquema de recurrencia ya presentado se puede traducir a una función directa, en la que dados n y k nos devuelva el coeficiente correspondiente en el triángulo trinomial. Para ello, traducimos las filas de hoja de cálculo a dos vectores u(i) y v(i) que comiencen y terminen con ceros, y con ellos ir construyendo la recurrencia hasta llegar al coeficiente deseado:

Function trinomial2(n, k)

Dim u(50), v(50), i, j, h, t

 

 

For i = 1 To 2 * n + 3: u(i) = 0: v(i) = 0:  Next I ‘Se rellenan los vectores con ceros

u(n + 3) = 1 ‘Primer coeficiente

For i = 1 To n ‘Se trabaja hasta la fila n

For j = 3 To 2 * n + 3 ‘Longitud de la fila contando con ceros iniciales

v(j) = u(j - 1) + u(j) + u(j + 1) ‘Recurrencia

Next j

For h = 3 To 2 * n + 3: u(h) = v(h: Next h ‘Se copia v(i) en u(i)

For h = 1 To 2 * n + 1: v(h) = 0: Next h ‘Y se rellena con ceros

Next i

t = u(n + k + 3) ‘Se localiza el coeficiente pedido

trinomial2 = t

End Function

 

Aunque parece algo complejo, funciona con rapidez. En la imagen se recogen los coeficientes correspondientes a n=5 y n=6:

Coeficientes centrales

Los números centrales de cada fila poseen importancia propia. Por eso, en OEIS, se les dedican muchas referencias y descripciones de propiedades. Aquí sólo se darán algunos detalles, remitiendo para un estudio completo a la página https://oeis.org/A002426.

Su cálculo no es difícil. En la página mencionada se usa la definición como coeficientes de  (1+x+x2)n, pero eligiendo el coeficiente número n. Se propone este código PARI de fácil comprensión, extendido aquí con un bucle FOR:

a(n) = if( n<0, 0, polcoeff( (1 + x + x^2)^n, n))

for(k=0,20,print1(a(k),", "))

Su resultado, en la página oficial de PARI es:


Coincide con lo publicado.

Con nuestra función trinomial2(n,k) basta dar a k el valor 0. Así se ha efectuado para crear esta columna de Excel:

Una interpretación interesante de estos números es la de David Callan, que los identifica con el número de sucesiones de n elementos tomados del conjunto (1, 2, 3, … n), crecientes en sentido amplio, en las que ningún elemento se repite más de dos veces. Propone como ejemplo si n = 3, las sucesiones son 112, 113, 122, 123, 133, 223, 233, es decir, son siete como indica su coeficiente central.

He añadido la condición FMAX a mi herramienta Cartesius (https://www.hojamat.es/sindecimales/combinatoria/herramientas/herrcomb.htm#cartesius) y, aunque aún no está publicada, la he usado para comprobar esta propiedad. He concretado las condiciones siguientes:

xtotal=5

xt=1..5

FMAX<3

Creciente


Con ellas se combinan en arreglos crecientes los números del 1 al 5, con la condición de que la frecuencia máxima sea 2, tal como plantea David Callan, y se han obtenido 51 posibilidades, como corresponde al coeficiente central de orden 5. Este recorte contiene los primeros y su total:

 

 


 

jueves, 28 de mayo de 2026

Funciones definidas para tipos de números (3)

 Esta entrada cierra el estudio de funciones definidas para ciertos tipos de números, así como de sus funciones inversas. En esta tercera se estudiarán las definidas por recurrencia.

Funciones sobre recurrencias

 

Son aquellas que se definen mediante los términos iniciales, y además, expresan a(n+1) en función de los anteriores términos. Por ejemplo, la sucesión de Fibonacci se define como a(1)=1, a(2)=1, y para el resto, a(n+1)=a(n)+a(n-1). Si esta última relación sólo usa el término a(n) se llama de primer orden, y así, se pueden plantear de segundo, tercero o más órdenes.

 

Recurrencias de primer orden

 

Cada función de este tipo deberá estar definida por dos parámetros, a(1) y otro según la definición, que puede ser DIFERENCIA en las progresiones aritméticas, RAZÓN en las geométricas, o bien cualquier otra relación entre a(n+1) y a(n). No existen ejemplos populares concretos para definir funciones.

 

Recurrencias de segundo orden

 

Existen muchas recurrencias de segundo orden, como la ya citada de Fibonacci. Las más simples son las llamadas Horadam, y se caracterizan porque la relación de recurrencia es lineal. Vemos las más importantes.

 

Caso particular: sucesiones Horadam

 

Son aquellas que están definidas por cuatro parámetros, a1, a2, c1 y c2, de la forma a(1) = a1, a(2) =a2, a(n) = a(n-2)*c1+a(n*1)*c2. Así, tenemos muchos ejemplos concretos de este tipo de sucesiones recurrentes de segundo grado:

 

Horadam(1,1,1,1): Números de Fibonacci: 1, 1, 2, 3, 5

Horadam(2,1,1,1): Números de Lucas: 2, 1, 3, 4, 7, 11, 18, 29, 47, …

Horadam(1,2,1,2): Potencias de 2:1, 2, 4, 8, 16, 32, …

Horadam(0,1,2,1): Números de Pell: 0, 1, 2, 5, 12, 29, 70, …

Horadam(1,1,2,1): Números de Pell-Lucas: 1, 1, 3, 7, 17, 41, 99, …

Horadam(2,3,3,-2): Sucesión de Pisot (2n+1): 2, 3, 5, 9, 17, 33, …

Horadam(0,1,1,2): Sucesión de Jacobsthal: 2, 3, 5, 9, 17, 33, …

 

Son muy sencillas de programar, y su búsqueda suele ser rápida. Para encontrar un término general hay que usar los cuatro parámetros citados más el número de orden n.

  

En lenguaje PARI

 

horadam(n,a1, a2, c1, c2) = {my(i,f,t,v,u); if(n==1,f=a1); if(n==2,f=a2);if(n>2,v=a1;t=a2;for(i=3,n,u=c1*t+c2*v;v=t;t=u);f=u);f}

 

En Vbasic

 

Function horadam(n, a1, a2, c1, c2)

Dim i, f, v, u

If n = 1 Then horadam = a1: Exit Function

If n = 2 Then horadam = a2: Exit Function

v = a1: t = a2

For i = 3 To n

u = c1 * t + c2 * v: v = t: t = u

Next i

horadam = u

End Function

 

Si se dispone de estas dos funciones, podemos definir las funciones FIBONACCI(N), PELL(N), LUCAS(N) y demás, igualando su definición a la de Horadam. Por ejemplo, LUCAS(N) se definirá así:

 

Lucas(n)=horadam(n, 2,1,1,1)

 

Así tendremos que lucas(10)=horadam(10,2,1,1,1)=76, como puedes ver en cualquier descripción de estos números. Imagina que puedes definir así todas estas sucesiones.

El autor lleva años usando FIBONACCI(N) en sus cálculos.

 

La función ORDEN se puede construir de similar a la que usamos para Primos o capicúas. Puede ser esta:

 

Function eshoradam(n, a1, a2, c1, c2) As Long

Dim v, u, k, t As Long

Dim es As Long

 

If n = a1 Then eshoradam = 1: Exit Function

If n = a2 Then eshoradam = 2: Exit Function

v = a1: t = a2: k = 2

While t <= n

If t = n Then

es = k

ElseIf t > n Then

es = 0

End If

u = c1 * t + c2 * v: v = t: t = u: k = k + 1

Wend

eshoradam = es

End Function

 

Nos devuelve el orden k si es un término de la sucesión, o un cero si no lo es.

 

El autor usa en su hoja de cálculos diarios esta versión, que le permite averiguar si un número dado es de uno de los tipos populares de esta sección:

 

Function estipohoradam$(n)

Dim s$

Dim es As Long

s = ""

es = eshoradam(n, 1, 1, 1, 1): If es <> 0 Then s = s + " Fibonacci " + " & " + ajusta(es)

es = eshoradam(n, 2, 1, 1, 1): If es <> 0 Then s = s + " Lucas " + " & " + ajusta(es)

es = eshoradam(n, 0, 1, 2, 1): If es <> 0 Then s = s + " Pell " + " & " + ajusta(es)

es = eshoradam(n, 1, 1, 2, 1): If es <> 0 Then s = s + " Pell-Lucas " + " & " + ajusta(es)

es = eshoradam(n, 2, 3, 3, -2): If es <> 0 Then s = s + " Pisot " + " & " + ajusta(es)

es = eshoradam(n, 0, 1, 1, 2): If es <> 0 Then s = s + " Jacobsthal " + " & " + ajusta(es)

es = eshoradam(n, 2, 1, 1, 2): If es <> 0 Then s = s + " Jacobsthal-Lucas " + " & " + ajusta(es)

 

If s = "" Then s = "No es de ningún tipo"

estipohoradam = s

End Function

 

Así, por ejemplo, estipohoradam(76) nos devuelve Lucas  & 10, y estipohoradam(81), No es de ningún tipo.

 

Podemos seguir recorriendo tipos de sucesiones recurrentes, como las de Perrin y otras, pero no suelen demandar nuestros trabajos unas funciones directas como las que aquí se han presentado.

 

Otras recurrencias

 

El contenido de esta entrada nos ayuda si necesitamos definir una función para sucesiones que no sean de Horadam, pero el procedimiento para encontrar funciones de este tipo es el mismo, salvo la fórmula de recurrencia.

 

jueves, 21 de mayo de 2026

Funciones definidas para tipos de números (2)

En la anterior entrada de esta serie se estudiaron funciones del tipo TRIANGULAR(N) o OBLONGO(N), que se caracterizan por poseer una fórmula, y sólo hay que buscar la función inversa u ORDEN, En esta segunda entrada se incluirán funciones sin fórmula, que necesitan la ayuda de una búsqueda.

Funciones basadas en búsqueda

 

Es el caso de la función PRIMO(N). Se necesita otra función, llamemos ESPRIMO, que indique si un número es del tipo dado o no, y después habrá que contar los casos que indique su orden N para llegar a a su valor. Lo vemos según el tipo, tomando los números primos como ejemplo para los siguientes:

 

Función PRIMO(N)

 

Necesitaremos la función ESPRIMO, descargable desde este blog, por ejemplo, en https://hojaynumeros.blogspot.com/2009/03/primos-reversibles-primo-omirp.html

 

El siguiente código, adaptable a cualquier lenguaje de programación, encuentra el primo de orden n. Servirá de modelo para otros ejemplos, cambiando la línea que se señala.

 

Function primo(n)

Dim p, c, i

'encuentra el primo cuyo número de orden es n

c = 0: i = 1

While c < n

If esprimo(i) Then c = c + 1: p = i ‘Esta línea se cambiará en otros ejemplos

i = i + 1

Wend

primo = p

End Function

 

Por ejemplo, ¿cuál es el número primo de orden 1000? La respuesta sería 7919. Lo comprobamos con PARI, que ya tiene implementada la función PRIME:

? print(prime(1000))

7919

Volveremos a esta estructura de función.

 

Función inversa, ORDENPRIMO

 

También aquí nos servirá de modelo para otros casos.

 

Function ordenprimo(a) As Long

Dim p, c As Long

 

If not esprimo(a) Then ordenprimo = 0: Exit Function

c = 0

For p = 1 To a

If esprimo(p) Then c = c + 1 ‘línea que cambiará según ejemplos

Next p

ordenprimo = c

End Function

 

Se entiende bien. Se van recorriendo los números del mismo tipo hasta llegar al que nos interesa. Por experiencia se sabe que es útil que, si el número no es primo, la función devuelva un cero. De ahí la inclusión de la primera línea.

 

Así, ordenprimo(100)=0 y ordenprimo(101)=27, ya que primo(27)=103

 

En PARI no están implementados órdenes, pero esta sencilla línea lo resuelve:

 

ordenprimo(a)=my(c=0,p);for(p=1,a,if(isprime(p),c+=1));c*isprime(a)

 

Aquí, la solución para que dé un cero si no es primo se encuentra al final. Al multiplicar por isprime(a), anula el resultado si no es primo, porque vale cero. En este recorte se observa la aplicación de esta función al 100 y al 103:

 

 


Este modelo se usará más adelante si se ve conveniente.

 

Una función similar es PRIMOSOPHIE(N), que devuelve el enésimo primo de Sophie Germain. Basta añadir a esprimo(n) la función esprimo(2*n+1)

 

Así, cambiaríamos la línea a If esprimo(p) and esprimo(2*n+1) Then c = c + 1

 

Lo dejo como ejercicio. Debe dar, por ejemplo:

primosophie(7)= 41, y ordenprimosophie(233)=16

 

 

Función SEMIPRIMO(N)

 

Los semiprimos son aquellos números compuestos que equivalen al producto de dos primos. Como 4=2*2 y 62=2*31. La función SEMIPRIMO es sencilla si se posee la BIGOMEGA, que es el número de factores primos de un número. En PARI sí existe, con lo que los semiprimos son aquellos en los que bigomega vale 2.

 

Sería essemiprimo(n)=bigomega(n)==2

 

En la imagen observamos dos resultados.


En el caso de VBASIC es preferible dedicarle un código especial. Consiste en buscar dos primos tales que su producto sea el número dado. Puede ser este:

 

Public Function essemiprimo(n) As Boolean

Dim a, r

Dim es As Boolean

 

es = False 'Al principio suponemos que no es semiprimo

a = 2 'La variable a recorrerá los números primos

r = Sqr(n) ‘Tope de búsqueda

While a <= r And Not es

If n / a = n \ a And esprimo(a) And esprimo(n / a) Then es = True

‘La variable a debe ser divisor, primo, y su cociente con N también primo

If a = 2 Then a = a + 1 Else a = a + 2 'Se busca el próximo primo

Wend

essemiprimo = es

End Function

 

Ahora basta sustituir, en la función PRIMO(N), la línea

If esprimo(i) Then c = c + 1: p = I por

If essemiprimo(i) Then c = c + 1: p = i

Tendremos así formada la función SEMIPRIMO(N)

 

Como comprobación se dan algunos valores: SEMIPRIMO(13)=35, SEMIPRIMO(100)=314 y SEMIPRIMO(1000)=3595

 

Igualmente podemos adaptar la función ORDENPRIMO a ORDENSEMIPRIMO. Se deja como ejercicio. Esta es la comprobación de los semiprimos del párrafo anterior:

 


 

Función CAPICUA(N)

 

Los números capicúas (o palindrómicos) son los que presentan simetría en sus cifras (nos limitaremos a base 10), y tienen un orden predecible, pero es más cómodo considerar que aparecen de forma aleatoria. Por eso se incluyen aquí. Como en anteriores tipos, necesitamos una función ESCAPICUA. En VBASIC de Excel y Calc ya está resuelta en este blog

(ver https://hojaynumeros.blogspot.com/2017/10/suma-de-cuadrado-y-capicua.html)

No tiene en cuenta los números de una cifra.

 

En PARI  es sencilla:

ispal(n)=n==eval(concat(Vecrev(Str(n))))

 

Ya se ha explicado en este blog que significa “convertir en texto, invertir sus cifras como vector, reunirlas y calcular su valor”. Es bastante ingenioso.

 

Como en los otros casos, se cambia la línea adecuada en el código y resulta la función.

 

Un ejemplo de búsqueda sería, por ejemplo: Encontrar dos capicúas consecutivos cuya suma sea un número primo. Introduciremos en un Buscador esta condición:

 

If ESPRIMO(CAPICUA(N)+CAPICUA(N+1))

 

Las primeras soluciones son:



 

Dos de las sumas son “palprimos”, primo y capicúa, pero la central es número primo, pero no palindrómico. Si les adjuntamos sus órdenes, observamos tres situaciones distintas:




En la primera, al sumar capicúas se suman también sus órdenes, porque no hay arrastre de cifras. En la segunda hay un cero porque no es capicúa, y en la tercera no se suman los órdenes.

 

Este tipo de funciones nos proporciona más posibilidades en las búsquedas.

 

Otras funciones

 

Podíamos seguir con el tema de funciones que necesitan una búsqueda previa. Algunas posibles serían:

 

INTERPRIMO(N): buscaría números que son promedio entre dos primos consecutivos.

 

ESFENICO(N): para números que son producto de tres primos distintos.

 

LIBREDECUADRADOS(N): cuando ningún factor primo posee un exponente mayor que uno.

 

CUADPRIMO(N): cuadrado de un primo.

 

Con los estudiados ya se puede tener una idea.