jueves, 25 de febrero de 2010

Función cifras_distintas

En la entrada del 24 de Febrero de su blog “Números” , Claudio nos planteaba esta propuesta:

¿Cuál es el mayor número que entre él y su doble, no tienen dígitos repetidos?

Cuando quise emprender la búsqueda me di cuenta de que tenía que comenzar con el 49000 y después ir descendiendo en los ensayos hasta dar con el número pedido. Era una tarea para encargársela al ordenador y que él trabajara por mí.

Cuando planifiqué esta búsqueda vi que sería muy útil disponer de una función que me devolviera un 1 si su argumento no tuviese cifras repetidas o un 0 en caso contrario (preferí  1 y 0 porque es más cómodo que VERDADERO o FALSO). Pues bien, el estudio de esta función es el objetivo de esta entrada.

Función cifras_distintas


Para construir esta función sobre un argumento N son necesarios tres cálculos al menos:

  • Encontrar el número de cifras de N
  • Saber encontrar la cifra de N que ocupe el lugar K
  • Comprobar si las cifras son distintas o existe alguna repetición.
Número de cifras

Un número entero tiene K cifras si está comprendido entre 10K-1 y 10K por lo que tomando logaritmos decimales, K-1 <= log (N) < K

Public function numero_cifras(n)
numero_cifras=int(log(n)/log(10))+1
end function

En esta entrada del presente blog se explica el modo de implementarlas en OpenOffice.org Calc

Se declara Public para que se pueda usar como una función más de Excel o Calc y el dividir entre log(10) se justifica porque LOG se corresponde con el logaritmo natural.

Selección de cifras

Para extraer una cifra de un número entero podemos acudir a calcular su cociente entero respecto a 10K-1, y nos resultará el mismo número pero escrito sólo hasta la cifra K. Así INT(23543/100) se nos convierte en 235. Si ahora lo dividimos entre 10, desaparecerá la cifra K: INT(235/10)=23. Con algún pequeño detalle más llegamos a la función deseada. Si el número no posee tantas cifras nos devolverá un cero.

Public function cifra(m,n)
dim v

v=int(m/10^(n-1))
v=v-10*int(v/10)
cifra=v
end function

Función cifras_distintas

Ya sabemos contar las cifras de un número y separarlas unas de otras. Ahora hay que recorrerlas y detectar si alguna se repite.

Para ello crearemos diez memorias C, que se rellenarán con un 1 si la cifra existe en el número, y con un 0 si no existe. Así, cuando se recorre el número, se va marcando con un 1 cada cifra encontrada, pero si posteriormente nos encontramos con un 1 al marcar, es que existe una repetición. En la imagen vemos cómo se rellenarían las memorias con el número 27653:

Con esto ya tenemos preparado todo para la función. Se transcribe a continuación un posible listado en Basic con comentarios en cursiva:

Public function cifras_distintas(n)
dim nc,i,d
dim c(10)
dim vale

nc=numero_cifras(n)          Se cuentan las cifras y se almacenan en la memoria nc
for i=0 to 9:c(i)=0:next i    Ponemos todas a cero
vale=1                                  Provisionalmente damos el número como con cifras distintas
i=1                                        Iniciamos el recorrido
while vale=1 and i<=nc      Mantenemos el recorrido mientras no haya repetición
d=cifra(n,i)                          Leemos la cifra
if c(d)=0 then                      Si no está ya marcada, la marcamos
c(d)=1
else
vale=0                                  Si está marcada hay repetición y hacemos vale=0
end if
i=i+1
wend                                    Fin del recorrido
cifras_distintas=vale
end function

No hay comentarios: