Esta resposta é uma prova formal da resposta de TheNumberOne , Enumerate Brainf ** k programas válidos , onde pode ser um pouco difícil entender os pontos positivos da razão pela qual a enumeração está correta. Não é trivial entender por que não há algum programa inválido que mapeie para um número não coberto por um programa válido.
Em toda essa resposta, maiúsculas são usadas para denotar programas e variáveis em minúsculas são usadas para funções e números inteiros. ~ é o operador de concatenação.
Proposição 1:
Seja a função f o programa descrito nessa resposta. Então, para todo programa U existe um programa válido V tal que f (U) = f (V)
Definição 1:
Seja g (X) o número [
que aparece no programa X e h (X) seja o número ]
que aparece.
Definição 2:
Defina P (x) para esta função:
P(x) = "" (the empty program) when x <= 0
P(x) = "]" when x = 1
P(x) = "]]" when x = 2
etcetera
Definição 3:
Dado um programa X, denote X1 como seu maior prefixo de [
caracteres, X2 seu centro e X3 seu maior sufixo de ]
caracteres.
Prova da proposição 1:
Se g (U) = h (U), então U é um programa válido, e podemos usar V = U. (caso trivial).
Se g (U) <h (U), então podemos criar V acrescentando n = h (U) - g (U) [
símbolos. Obviamente f (V) = f (U), pois todos os [
símbolos no prefixo são removidos.
Agora considere g (U)> h (U). Defina T = U2 ~ U3. se g (T) <= h (T), então podemos construir V removendo n = g (U) - h (U) [
símbolos.
Portanto, podemos assumir que h (T) <g (T). Construa V = T ~ P (g (T) - h (T)).
Precisamos de três pequenos fatos para prosseguir:
Reivindicação 1: g (U2) = g (T)
U3 não contém nenhum [
símbolo por sua definição. Como T = U2 ~ U3, seus [
símbolos estão todos na primeira parte.
Reivindicação 2: h (U3) <g (T)
Isso resulta da observação de que h (T) <g (T) eh (U3) <h (U3 ~ U2) = h (T).
Reivindicação 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*
Agora 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
Isso completa a prova. QED
Vamos fazer exclusividade também.
Proposição 2:
Seja U, V dois programas válidos diferentes. Então f (U)! = F (V)
Isso é bastante simples em comparação com a proposição anterior.
Vamos supor que U2 = V2. Mas a única maneira de U e V serem diferentes é adicionando ou removendo n [
e ]
símbolos a U1 e U3, respectivamente. No entanto, isso altera a saída de f, pois f contará o número de ]
símbolos não correspondentes no sufixo.
Assim U2! = V2.
Obviamente, isso leva a uma contradição. Como U2 e V2 estão literalmente contidos na saída de f (U) ef (V), respectivamente, eles não podem diferir, exceto na 'borda', o local em que U2 é concatenado com U3. Mas o primeiro e o último símbolo de U2 e V2 não podem ser [
ou ]
por definição, enquanto esses são os únicos símbolos permitidos em U1, U3, V1, V3, respectivamente e respectivamente novamente. Assim, temos U2 = V2. QED