Этот ответ является формальным доказательством ответа TheNumberOne , перечисления действительных программ Brainf ** k , где может быть немного трудно понять тонкости, почему перечисление является правильным. Нетрудно понять, почему не существует какой-либо недопустимой программы, которая отображается на число, которое не включено в допустимую программу.
В этом ответе заглавные буквы используются для обозначения программ, а строчные переменные используются для функций и целых чисел. ~ является оператором конкатенации.
Предложение 1:
Пусть функция f будет программой, описанной в этом ответе. Тогда для каждой программы U существует действительная программа V такая, что f (U) = f (V)
Определение 1:
Пусть g (X) будет номером того, [
что появляется в программе X, и пусть h (X) будет номером того, ]
что появляется.
Определение 2:
Определите P (x), чтобы быть этой функцией:
P(x) = "" (the empty program) when x <= 0
P(x) = "]" when x = 1
P(x) = "]]" when x = 2
etcetera
Определение 3:
Для программы X обозначим X1 как самый большой префикс [
символов, X2 - его центр, а X3 - самый большой суффикс ]
символов.
Доказательство предложения 1:
Если g (U) = h (U), то U - правильная программа, и мы можем взять V = U. (тривиальный случай).
Если g (U) <h (U), то мы можем создать V, добавив n = h (U) - g (U) [
символов. Очевидно, что f (V) = f (U), поскольку все [
символы в префиксе удалены.
Теперь рассмотрим g (U)> h (U). Определить T = U2 ~ U3. если g (T) <= h (T), то мы можем построить V, удалив n = g (U) - h (U) [
символов.
Таким образом, мы можем предположить, что h (T) <g (T). Построим V = T ~ P (g (T) - h (T)).
Нам нужно три небольших факта, чтобы продолжить:
Утверждение 1: g (U2) = g (T)
U3 [
по своему определению не содержит символов. Поскольку T = U2 ~ U3, все его [
символы находятся в первой части.
Утверждение 2: h (U3) <g (T)
Это следует из того, что h (T) <g (T) и h (U3) <h (U3 ~ U2) = h (T).
Утверждение 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*
Теперь покажем, что 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
Это завершает доказательство. QED
Давайте сделаем уникальность также.
Предложение 2:
Пусть U, V две разные, действительные программы. Тогда f (U)! = F (V)
Это довольно просто по сравнению с предыдущим предложением.
Предположим, что U2 = V2. Но тогда единственный способ, которым U и V могут различаться, - это добавление или удаление n [
и ]
символов к U1 и U3 соответственно. Тем не менее, это изменяет вывод f, так как f будет подсчитывать количество непревзойденных ]
символов в суффиксе.
Таким образом, U2! = V2.
Очевидно, это приводит к противоречию. Поскольку U2 и V2 буквально содержатся в выходных данных f (U) и f (V) соответственно, они не могут отличаться, кроме как на «краю», месте, где U2 соединяется с U3. Но первый и последний символы U2 и V2 не могут быть [
или ]
по определению, в то время как это единственные символы, разрешенные в U1, U3, V1, V3 соответственно и соответственно снова. Таким образом, мы получаем U2 = V2. QED