Esta respuesta es una prueba formal de la respuesta de TheNumberOne , Enumerar programas Brainf ** k válidos , donde puede ser un poco difícil entender los puntos finos por los que la enumeración es correcta. No es trivial entender por qué no hay algún programa no válido que se asigne a un número no cubierto por un programa válido.
A lo largo de esta respuesta, las mayúsculas se usan para denotar programas, y las variables en minúsculas se usan para funciones y enteros. ~ es el operador de concatenación.
Proposición 1:
Deje que la función f sea el programa descrito en esa respuesta. Entonces, para cada programa U existe un programa válido V tal que f (U) = f (V)
Definición 1:
Supongamos que g (X) sea el número [
que aparece en el programa X y que h (X) sea el número ]
que aparece.
Definición 2:
Defina P (x) para que sea esta función:
P(x) = "" (the empty program) when x <= 0
P(x) = "]" when x = 1
P(x) = "]]" when x = 2
etcetera
Definición 3:
Dado un programa X, denote que X1 es su prefijo de [
caracteres más grande , X2 su centro y X3 su sufijo de ]
caracteres más grande .
Prueba de proposición 1:
Si g (U) = h (U), entonces U es un programa válido, y podemos tomar V = U. (caso trivial).
Si g (U) <h (U), entonces podemos crear V al anteponer [
símbolos n = h (U) - g (U) . Obviamente f (V) = f (U) ya que todos los [
símbolos en el prefijo se eliminan.
Ahora considere g (U)> h (U). Definir T = U2 ~ U3. si g (T) <= h (T), entonces podemos construir V eliminando los [
símbolos n = g (U) - h (U) .
Entonces podemos suponer que h (T) <g (T). Construir V = T ~ P (g (T) - h (T)).
Necesitamos tres pequeños hechos para proceder:
Reclamación 1: g (U2) = g (T)
U3 no contiene ningún [
símbolo por su definición. Como T = U2 ~ U3, sus [
símbolos están todos en la primera parte.
Reclamación 2: h (U3) <g (T)
Esto se deduce de señalar que h (T) <g (T) y h (U3) <h (U3 ~ U2) = h (T).
Reclamación 3: h (V3) = g (U2) - h (U2)
h(V3) = h(U3) + g(T) - h(T) using the construction of V
h(V3) = h(U3) + g(U2) + g(U3) - h(U2) - h(U3) apply the definition of T
h(V3) = g(U2) - h(U2) *one term cancels, g(U3) is always zero, as U3 contains only `]` symbols*
Ahora mostramos que f (V) = f (U).
f(U) = U2 ~ P(h(U3) - g(U2)) = U2 claim 2, definition of P
f(V) = U2 ~ P(h(V3) - g(V2))
= U2 ~ P(h(V3) - g(U2))
= U2 ~ P(g(U2) - h(U2) - g(U2)) claim 3
= U2 ~ P(-h(U2))
= U2 definition P
Esto completa la prueba. QED
Hagamos también la unicidad.
Proposición 2:
Sea U, V dos programas diferentes y válidos. Entonces f (U)! = F (V)
Esto es bastante sencillo en comparación con la propuesta anterior.
Supongamos que U2 = V2. Pero entonces la única forma de U y V pueden ser diffrent es mediante la adición o la eliminación de n [
y ]
símbolos para U1 y U3, respectivamente. Sin embargo, esto cambia la salida de f, ya que f contará el número de ]
símbolos no coincidentes en el sufijo.
Por lo tanto, U2! = V2.
Obviamente, esto lleva a una contradicción. Como U2 y V2 están literalmente contenidos en la salida de f (U) yf (V) respectivamente, no pueden diferir, excepto en el 'borde', el lugar donde U2 está concatenado con U3. Pero el primer y último símbolo de U2 y V2 no pueden ser [
o ]
por definición, mientras que esos son los únicos símbolos permitidos en U1, U3, V1, V3, respectivamente, y de nuevo respectivamente. Así obtenemos U2 = V2. QED