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:
- Descomponer el número en factores primos y usarlos ignorando sus exponentes
- Exigir que todos los factores tengan cifras crecientes (o decrecientes)
- Ordenar dichos factores según su primera cifra, porque si esto falla, no se puede seguir.
- 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
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.
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:
Publicar un comentario