En el mensaje anterior hemos visto que cada número natural \( n \) está determinado por dos coordenadas, de modo que dos números son iguales si y sólo si lo son sus coordenadas, sy todo par de números son las coordenadas de un (único) número. Ahora bien, también podemos descomponer cada número en ternas de coordenadas si definimos
\( \left<x, y, z\right>_3 = \left<\left<x, y\right>_2,z\right>_2 \)
La aplicación \( (x, y, z) \mapsto \left<x, y, z\right>_3 \) biyecta las ternas ordenadas de números naturales con los números naturales.
Por ejemplo: \( \left<3, 5, 0\right>_3 = \left<\left<3, 5\right>_2, 0\right>_2 = \left<39,0\right>_2=819 \).
Recíprocamente, si partimos de \( 819 \), podemos calcular \( p_2(819)= (39, 0) \) y, a su vez, \( p_2(39)= (3, 5) \), con lo que obtenemos la descomposición \( 389 = \left<3, 5, 0\right>_3 \).
La tabla siguiente contiene la descomposición en ternas de los primeros números naturales:
\( \begin{array}{cccccccccc}
0&1&2&3&4&5&6&7&8&9\\
(0, 0, 0)&(0, 0, 1)&(0, 1, 0)&(0, 0, 2)&(0, 1, 1)&(1, 0, 0)&(0, 0, 3)&(0, 1, 2)&(1, 0, 1)&(0, 2, 0)
\end{array} \)
Más en general, si definimos \( \left<x\right>_1 = x \) y \( \left<x, y\right>_2 \) la aplicación que hemos estudiado en el mensaje anterior, podemos definir \( n \)-tuplas de cualquier longitud:
\( \left<x_1, x_2, x_3\right>_3 = \left<\left<x_1, x_2\right>_2,x_3\right>_2 \), \( \left<x_1, x_2, x_3, x_4\right>_4 = \left<\left<x_1, x_2, x_3\right>_3, x_4\right>_2 \), \( \left<x_1, x_2, x_3, x_4, x_5\right>_5 = \left<\left<x_1, x_2, x_3, x_4\right>_4, x_5\right>_2 \), etc.
y de este modo podemos determinar cada número natural por una única coordenada (él mismo) o por dos coordenadas, o por tres, etc. Más precisamente, tenemos biyecciones que a cada \( n \)-tupla de números naturales le asignan un número natural, y podemos considerar sus inversas: \( p_n:\mathbb N\longrightarrow \mathbb N^n \).
He aquí una implementación en Python:
def tupla(*l):
"""tupla de una sucesión"""
long = len(l)
if long == 1:
u = l[0]
else:
u = par(tupla(*l[:long-1]),l[long-1])
return u
def pn(n,z):
""""Coordenadas de z visto como n-tupla"""
u=[]
for i in range(0,n-1):
p = p2(z)
u.append(p[1])
z = p[0]
u.append(z)
u.reverse()
u = tuple(u)
return uLa primera función calcula recursivamente \( \text{tupla}(x_1,\ldots, x_l) =\text{par}(\text{tupla}(x_1, \ldots, x_{l-1}), x_l) \), mientras que la segunda parte de un número \( z \) y va descomponiendo: \( z = \left<z', x\right> \), va añadiendo los valores \( x \) en una lista \( u \) y pasa a hacer lo mismo con \( z' \), así \( n-1 \) veces, hasta que finalmente añade a la lista \( u \) el último valor \( z \) obtenido, con lo que \( u \) es la \( n \)-tupla asociada a \( z \) salvo que está ordenada al revés, así que hay que darle la vuelta antes de devolver el resultado. (Insisto en que cualquier idea para hacer los algoritmos más eficientes será bienvenida.)
Así, un mismo número natural puede descomponerse —de forma única— en un par, en una terna, en una cuádrupla, etc. Por ejemplo, las descomposiciones del número \( 123\,456\,789 \) son:
\( (123456789),\ (15461, 251),\ (61, 114, 251), \ (6, 4, 114, 251), \ (0, 3, 4, 114, 251),\ (0, 0, 3, 4, 114, 251)\ldots \)
Pero necesitamos refinar estas técnicas para que cada número natural se identifique con una única descomposición de una longitud determinada, es decir, no queremos que el par \( (15461, 251) \) y la terna \( (61, 114, 251) \) se tengan que identificar con un mismo número natural. Más precisamente, vamos a definir una biyección \( s\mapsto \left<s\right>_\infty \) que a cada sucesión finita de números naturales (de cualquier longitud) le asigne un único número natural. La definición es sencilla, pero hay un tecnicismo en ella para hacerle un hueco a la sucesión vacía de longitud \( 0 \), para la que será \( \left<\ \right>_\infty = 0 \).
La definición es:
\( \left<x_1, \ldots, x_n\right>_\infty=\begin{cases}{0}&\text{si}& n=0,\\ \left<n-1,\left<x_1,\ldots, x_n\right>_n\right>_2+1 & \text{si}& n>0.\end{cases} \)
De este modo, a la única sucesión vacía (de longitud \( n=0 \)) le asignamos el número \( 0 \), mientras que a una sucesión no vacía, como \( (3, 0, 4, 4) \), de longitud \( 4 \) le asignamos el par:
\( \left<3, 0, 4, 4\right>_\infty = \left<3,\left<3, 0, 4, 4\right>_4\right>_2+1 = \left<3, 5\,560\right>_2 +1= 15\,476\,269+1 = 15\,476\,270. \)
Así, cada número natural se descompone de forma única en una sucesión finita de números naturales. Por ejemplo, si nos dan el \( 15\,476\,270 \), como no es \( 0 \) ya sabemos que se corresponde con una sucesión no vacía, le restamos \( 1 \) y descomponemos:
\( 15\,476\,270-1 = \left<3, 5\,560\right>_2 \),
y la primera coordenada nos dice que la sucesión que buscamos tiene longitud \( 3+1=4 \). Entonces reinterpretamos la segunda coordenada como \( 5\,560 = \left<3, 0, 4, 4\right>_4 \) y ya tenemos la sucesión buscada. He aquí dos funciones en Python para calcular esta función y su inversa, así como la longitud de la sucesión codificada por un número:
def s(*l):
"""Número correspondiente a una sucesión dada"""
if l == ():
u = 0
else:
u = par(len(l) - 1,tupla(*l)) + 1
return(u)
def long(s):
"""Longitud de una sucesión"""
if s == 0:
u = 0
else:
u = p2(s-1)[0]+1
return(u)
def term(s):
"""Términos de un número"""
if s == 0:
u = ()
else:
z = p2(s-1)
u = pn(z[0] + 1,z[1])
return uLa función s implementa de forma obvia la función \( \left<s\right>_\infty \), la función long(s) distingue si \( s = 0 \), en cuyo caso codifica la sucesión vacía de longitud \( 0 \), o si \( s>0 \), en cuyo caso la longitud de la sucesión que codifica se obtiene sumando 1 a la primera coordenada de \( s-1 \) visto como par. Finalmente, la función term, tras distinguir el caso \( s=0 \), descompone \( s-1 = \left<z_0, z_1\right>_2 \) y luego descompone \( z_1 \) en sucesión de longitud \( z_0+1 \).
Con esto hemos conseguido nuestro primer objetivo: probar que cada número natural puede descomponerse de forma única en una sucesión finita de números naturales. Por ejemplo, \( \left<0, 1, 2, 3, 4, 5\right>_\infty = 3\,374\,956\,582\,776 \). La tabla siguiente muestra las primeras descomposiciones:
\( \begin{array}{cccccccccc}
0&1&2&3&4&5&6&7&8&9\\
()&(0)&(1)&(0, 0)&(2)&(0, 1)&(0, 0, 0)&(3)&(1, 0)&(0, 0, 1)\\
\hline
10&11&12&13&14&15&16&17&18&19\\
(0, 0, 0, 0)&(4)&(0, 2)&(0, 1, 0)&(0, 0, 0, 1)&(0, 0, 0, 0, 0)&(5)&(1, 1)&(0, 0, 2)&(0, 0, 1, 0)\\
\hline
20&21&22&23&24&25&26&27&28&29\\
(0, 0, 0, 0, 1)&(0, 0, 0, 0, 0, 0)&(6)&(2, 0)&(0, 1, 1)&(0, 0, 0, 2)&(0, 0, 0, 1, 0)&(0, 0, 0, 0, 0, 1)&(0, 0, 0, 0, 0, 0, 0)&(7)\\
\hline
\end{array} \)
En lo sucesivo usaremos únicamente las funciones \( \left<x, y\right>_2 \), \( \left<x_1, \ldots, x_n\right>_\infty \) y sus inversas.
En el mensaje anterior hemos probado que \( x, y \leq \left<x, y\right>_2 \), de donde se sigue fácilmente que \( x_i \leq \left<x_1, \ldots, x_n\right>_n \), de donde a su vez,
\( x_i \leq \left<n-1, \left<x_1, \ldots, x_n\right>_n\right>_2<\left<x_1,\ldots, x_n\right>_\infty \).
El lector debería asimilar todo esto hasta que vea natural que digamos, por ejemplo, que \( 28 \) tiene longitud \( 7 \), mientras que \( 29 \) tiene longitud \( 1 \). Así, esta sucesión, que en otro contexto parecería bastante vulgar y caprichosa:
\( 0, \quad 1, \quad 3, \quad 6, \quad 10, \quad 15, \quad 21, \quad 28, \quad 36, \quad 45, \quad 55\ldots \)
aquí resulta bastante natural.
Si algún lector está dispuesto a seguir este hilo programando, se puede plantear cómo determinar si un número natural extiende a otro (en el sentido de que la sucesión que determina extiende a la del otro), como 24, que extiende a 5, y, en caso negativo, cómo determinar el primer término en el que ambos difieren.