jueves, 30 de junio de 2022

Números con cifras crecientes o decrecientes (3)

Números con factores primos crecientes

Nos proponemos ahora una cuestión intrascendente con el solo objetivo de practicar algoritmos. Hemos estudiado las cifras de los números y los tipos de los mismos  (triangulares, cubos, de Fibonacci), y ahora nos dedicaremos a sus factores primos. La idea es construir un arreglo de factores en el que todas las cifras formen un conjunto creciente (o decreciente en su caso). Por ejemplo, 282=2*3*47.

Nos dedicaremos a los factores primos sin contar repeticiones, para simplificar la tarea. El orden que exigiremos será creciente en sentido amplio.

Para conseguir el conjunto creciente podemos dar los siguientes pasos:

  1. Descomponer el número en factores primos y usarlos ignorando sus exponentes
  2. Exigir que todos los factores tengan cifras crecientes (o decrecientes)
  3. Ordenar dichos factores según su primera cifra, porque si esto falla, no se puede seguir.
  4. Una vez todo ordenado, exigir también que la primera cifra de cada factor sea mayor o igual que la última del anterior.

1.- Los primos deben tener cifras crecientes

En Excel y Calc disponemos de la función sacaprimos, para obtener tanto los primos como sus exponentes. La salida de esa función es el número de primos distintos. Si la deseas reproducir, debes comenzar con la declaración de variables globales:

Global primo(50), expo(50)

Global numomega

Esta declaración te permite usar los primos en cualquier otra función. El vector primo(50) recoge los primos y expo(50) sus exponentes (máximo 50). La variable numomega cuenta los primos.

La función sacaprimos está diseñada así:

Public Function sacaprimos(n)

Dim f, a, e

a = n

f = 2: i = 0: numomega = 0

While f * f <= a

e = 0

While a / f = Int(a / f) ‘Busca primos y sus repeticiones

e = e + 1 ‘Se va formando el exponente

a = a / f

Wend

If e > 0 Then

numomega = numomega + 1 ‘Hay un primo más

primo(numomega) = f ‘Se guarda el primo

expo(numomega) = e ‘Se guarda el exponente

End If

If f = 2 Then f = 3 Else f = f + 2

Wend

If a > 1 Then

numomega = numomega + 1

primo(numomega) = a

expo(numomega) = 1

End If

sacaprimos = numomega

End Function

Con esta función obtenemos los vectores primo y expo para recoger los primos y los exponentes, y numomega para contar los primos. Es importante recordar que la salida de la función es esta variable.

Con el uso de esta función podemos responder a la primera cuestión: que todos los primos tengan cifras crecientes (o decrecientes en su caso):

Estudiaremos la función que hemos diseñado, concatpandigi, a trozos:

 

m=numomega

For i = 1 To m

If Not cifras_crecientes(primo(i)) Then concatpandigi = "": Exit Function

Next i

Se lee el número de primos y se almacena en la variable m. Se recorren los primos, y si uno no tiene cifras crecientes, salimos de la función.

2.- Ordenar los factores según su primera cifra:

El siguiente trozo de función ordena los primos según su primera cifra. En realidad es la última, porque nuestras funciones leen las cifras de derecha a izquierda. Puede ser este:

If m > 1 Then  ‘Si m=1, no se ordena

i = 2

Do Until i > m ‘Usamos una rutina de ordenación

j = i

‘Lo que sigue es complicado por tener que ordenar mediante la última cifra, que para nosotros es la primera

While j > 1 And cifra(primo(j), numcifras(primo(j))) < cifra(primo(j - 1), numcifras(primo(j - 1)))

v = primo(j): primo(j) = primo(j - 1): primo(j - 1) = v

j = j - 1

Wend

i = i + 1

Loop

End If

3.- Exigir  que la primera cifra de cada factor sea mayor o igual que la última del anterior.

vale = True

i = 1

While i < m And vale

If cifra(primo(i), 1) > cifra(primo(i + 1), numcifras(primo(i + 1))) Then vale = False

i = i + 1

Wend

4.- Si todo va bien, se recogen los primos en un string:

If vale Then For i = 1 To m: s$ = s$ + Str$(primo(i)): Next i

concatpandigi = s

En el Anexo de esta entrada incluimos la función completa.

 

Números que cumplen lo exigido

Con la función concatpandigi ya podemos discriminar los números que cumplen lo exigido y los que no lo cumplen. Estos son los primeros cuyos primos forman una escala creciente (en sentido amplio), en los que hemos eliminado los de un solo factor primo, como 4, 8 o 9:

En forma de lista:

6, 10, 12, 14, 15, 18, 20, 21, 22, 24, 28, 30, 33, 35, 36, 39, 40, 42, 44, 45, 46, 48, 50, 54, 55, 56, 58, 60, 63, 65, 66, 69, 70, 72, 74, 75, 77, 80, 84, 88, 90, 91, 92, 94, 96, 98, 99, 100, 105, 108, 110, 111, 112, 115, 116, 117, 118, 119, 120,...

Observamos que aparecen muchos ejemplos, más de los esperados.

Si restringimos, por ejemplo, a los que poseen cuatro divisores primos, nos quedan:


Como curiosidad, estos son los de más de cuatro primos:

 


Un ejercicio divertido es imaginar números con más factores, como 11*2*3*5*67*7*89=13774530

 ¿Podrá existir un ejemplo pandigital? Si prescidimos del 0 y el 1, podemos usar 2438778=2*3*4567*89, o bien 0+1*2*3*4567*89

Dejamos abiertas las variantes de cifras estrictamente crecientes o las de cifras decrecientes. Se manejarían de igual forma, adaptando los algoritmos. Queda como reto o ejercicio.

 Con esta entrada finalizamos el curso 2021-22. Después del verano, en septiembre, volveremos a buscar temas de interés. Saludos.

 

 

Anexo

 

Function concatpandigi$(n)

Dim s$

Dim v, m, i, j

Dim vale As Boolean

 

'Devuelve cadena vacía o un string con los primos

 

s$ = ""

m = sacaprimos(n)

'Todos los primos han de tener cifras crecientes

For i = 1 To m

If Not cifras_crecientes(primo(i)) Then concatpandigi = "": Exit Function

Next i

'Ordena los primos según su primera cifra

If m > 1 Then

i = 2

Do Until i > m

j = i

While j > 1 And cifra(primo(j), numcifras(primo(j))) < cifra(primo(j - 1), numcifras(primo(j - 1)))

v = primo(j): primo(j) = primo(j - 1): primo(j - 1) = v

j = j - 1

Wend

i = i + 1

Loop

End If

 

'Ve si la primera cifra es menor que la última anterior

vale = True

i = 1

While i < m And vale

If cifra(primo(i), 1) > cifra(primo(i + 1), numcifras(primo(i + 1))) Then vale = False

i = i + 1

Wend

If vale Then For i = 1 To m: s$ = s$ + Str$(primo(i)): Next i

concatpandigi = s

End Function

No hay comentarios: