Determinar se um idioma é Turing Complete é muito importante ao projetar um idioma. Também é uma tarefa bastante difícil para muitas linguagens de programação esotéricas, mas vamos aumentar um pouco. Vamos criar algumas linguagens de programação que são tão difíceis de provar Turing Complete que mesmo os melhores matemáticos do mundo não conseguirão prová-las de qualquer maneira. Sua tarefa é planejar e implementar uma linguagem cuja complexidade de Turing se baseie em um grande problema não resolvido em matemática .
Regras
O problema que você escolher deve ter sido colocado há pelo menos 10 anos e não ter sido resolvido, a partir da publicação desta pergunta. Pode ser qualquer conjectura comprovável em matemática e não apenas uma das listadas na página da Wikipedia .
Você deve fornecer uma especificação do idioma e uma implementação em um idioma existente.
A linguagem de programação deve ser Turing completa se e somente se a conjectura se mantiver. (ou se e somente se a conjectura não se mantiver)
Você deve incluir uma prova de por que seria Turing completo ou incompleto com base na conjectura escolhida. Você pode assumir acesso à memória ilimitada ao executar o intérprete ou o programa compilado.
Como estamos preocupados com a E / S de Completude Turing, não é necessário, no entanto, o objetivo é tornar o idioma mais interessante para que ele possa ajudar.
Este é um concurso de popularidade, por isso a resposta com mais votos vencerá.
Critérios de destino
O que uma boa resposta deve fazer? Aqui estão algumas coisas a procurar ao votar, mas não são tecnicamente necessárias
Não deve ser um patch simples de um idioma existente. Alterar um idioma existente para atender às especificações é bom, mas a correção de uma condição é desencorajada porque é chata. Como dito por ais523 no Nineteeth Byte:
Eu prefiro fazer com que os truques dos meus esolangs fiquem mais firmes no idioma
Deve ser interessante como uma linguagem esotérica independente.
fonte
Respostas:
Legendre
Essa linguagem é apenas completa em Turing se, e somente se, a conjectura de Legendre for falsa, ou seja, existe um número inteiro n> 0, de modo que não haja números primos entre n ^ 2 e (n + 1) ^ 2. Essa linguagem se inspira no Underload, embora em alguns aspectos seja muito diferente dela.
Os programas no Legendre são compostos de séries de números inteiros positivos (0 é especialmente proibido, porque essencialmente nega todo o objetivo do idioma). Cada número inteiro corresponde a um comando base no Legendre, ou a um comando potencial definido pelo usuário. O comando ao qual está atribuído é baseado no número de primos entre seu quadrado e o próximo número inteiro (equivalente à sequência OEIS A014085 ).
Os comandos do idioma modificam uma pilha, que pode conter números inteiros positivos arbitrariamente grandes. Se a pilha contiver 0, o 0 será removido imediatamente. Em detalhes, os comandos são:
2 (menor número inteiro produzindo este comando: 1): Coloque o próximo número inteiro no programa na pilha.
3 (menor número inteiro de produção: 4): pop o número inteiro superior na pilha e execute o comando associado a ele.
4 (menor: 6): pop o número inteiro superior. Se fosse 1, aumente o número inteiro superior na pilha.
5 (10): Troque os dois principais itens da pilha.
6 (15): Decrementa o número inteiro superior na pilha. Se isso resultar em 0, coloque o 0 e descarte-o.
7 (16): duplique o número inteiro superior na pilha.
8 (25): Interrompa a execução e imprima o conteúdo da pilha.
Este é o conjunto de instruções básicas, que é incapaz de fazer qualquer coisa interessante, muito menos fazer um loop. No entanto, há outro comando, que pode ser acessado apenas se a conjectura de Legendre for falsa.
Se esse comando estiver acessível de alguma forma, o idioma se tornará completo em Turing, pois é possível simular uma máquina Minsky.
Quando o comando 8 é executado ou o final do programa é alcançado, o programa termina e o caractere (Unicode) correspondente a cada número inteiro na pilha é impresso.
Programas de exemplo
Este programa simples empurra o número 2, depois 3 e finalmente um 10, antes de executar um 4 (comando: 3), o que faz com que o 10 (comando: 5) seja exibido e executado, trocando os 2 e 3.
Este programa demonstra o uso da correspondência indireta de número inteiro para comando. Primeiro, um 5 é pressionado, depois um 15 e um 1, usando três maneiras diferentes de codificar o comando 2. Em seguida, o 1 é exibido e, como resultado, o 15 é incrementado para 16 e, finalmente, executado. O programa termina com duas instâncias do número 5 na pilha.
Este programa demonstra o uso do comando 0, usando? como um número de espaço reservado. O programa primeiro armazena '1 5' na função 9, depois '15 31 'em 10, antes de executar a função 9 (usando 24), que empurra 5 para a pilha e a diminui repetidamente, até atingir 0 e é removida . Então, o programa pára.
Minsky machine
Para converter uma máquina Minsky em código Legendre, o comando 0 deve ser usado. Como esse comando é inacessível, a menos que a conjectura de Legendre seja falsa, usei um espaço reservado? em vez de.
Observe que todos os nomes das linhas de instruções da máquina Minsky precisam ter números inteiros com diferentes correspondências A014085 entre si e com os comandos base, além de 24 (9) e 31 (10).
Inicialização: x INC (A / B) y:UMA:
B:
x DEC (A / B) yz:UMA:
B:
x HALT:Para criar o programa final, anexe todas as partes (com x, y, z substituídos por seus pares) e adicione um único número inteiro para iniciar a primeira instrução na cadeia. Isso deve provar a completude de Turing da linguagem, caso a conjectura de Legendre seja falsa por contra-exemplo.
Intérprete
Este intérprete é escrito em Python (3) e foi testado nos três exemplos acima. Use os sinalizadores -a / - allowZero para permitir? para ser usado, -f / - file para executar o código diretamente de um arquivo e -s / - stackOut para gerar a pilha como uma lista Python. Se nenhum arquivo for fornecido, o intérprete entra em uma espécie de modo REPL, que é melhor usado com --stackOut.
fonte
União fechada
Esta linguagem de programação está completa se a conjectura dos Conjuntos fechados pela União estiver incorreta.
Controles
Lista de comandos:
x ++ Incremento x (INC)
x-- Decremento x (DEC)
j (x, y) Adicione o conjunto de instruções x se y for 0 no final da fila de instruções
Todas as variáveis são inicializadas como 0
Sintaxe
Os programas são escritos como um conjunto de conjuntos de comandos.
Comando1 Comando2 Comando3 ...
Comando1 Comando2 ...
...
Para determinar se o programa está fechado, cada conjunto é responsável apenas pela lista de comandos diferentes que estão no conjunto
j (x, y)! = J (a, b)
+ (x)! = + (Y)
Se qualquer tipo de comando (+, -, j) aparecer em pelo menos metade dos conjuntos, ele não fará nada.
Os programas podem terminar se não houver instruções no final da fila de instruções
Loops infinitos, incluindo o loop vazio, podem ser alcançados usando j (x, y)
Intérprete
Mostrar snippet de código
Completude de Turing
Se todos os três comandos, j (x, y), incrementarem, diminuirem os comandos, todos estarão disponíveis, para que uma máquina Minsky possa ser simulada.
Qualquer conjunto com apenas j (x, y) atingido usando j (x, y) é HALT
x ++ é INC
x-- é DEC
j (x, y) é JZ
Se a conjectura de conjuntos fechados de união estiver correta, pelo menos um dos três comandos será sempre desativado, impossibilitando que esse idioma seja Turing completo.
fonte
Fermat primos
O idioma funciona em duas fitas potencialmente infinitas, onde cada local da fita pode armazenar um número inteiro arbitrário. As duas fitas são preenchidas
-1
no início. Há também duas cabeças de fita que começam na posição 0 nas duas fitas.O intérprete primeiro lerá a entrada e armazenará os valores na primeira fita (dados), começando na posição 0.
Em seguida, ele lerá o programa fornecido. Para cada número que encontrar, ele primeiro verificará se o valor é um Fermat prime ou não. Se sim, ele gravará na segunda fita (instrução) qual Fermat prime é, caso contrário, gravará
-1
na fita de instruções.Em seguida, verifique o valor no ponteiro da instrução e siga um destes procedimentos:
-1
ou menos: saia do programa0
: Mova a posição da fita de dados uma para a esquerda. Mova a fita de instruções para a direita1
: Mova a posição da fita de dados uma para a direita. Mova a fita de instruções para a direita2
: Aumente o valor na posição da fita de dados. Mova a fita de instruções para a direita3
: Diminua o valor na posição da fita de dados. Mova a fita de instruções para a direita4
: Se o valor na posição atual da fita de dados for zero, mova a fita de instruções para a direita, até atingir um valor correspondente5
(ou maior) na fita de instruções ou algo menor que0
. Se for um5
(ou maior), mova o ponteiro da instrução novamente para a direita, se for menor do que0
sair do programa. Se o valor da posição atual da fita de dados não for zero, basta mover a fita de instruções uma para a direita5
ou mais: mova o ponteiro da instrução para a esquerda, até atingir o4
valor correspondente ou encontrar algo menor que0
. No caso deste último, saia do programa.(combinando
5
(ou mais) e4
valores, significa que, ao procurar o valor adequado na fita de instruções sempre que encontrar o mesmo valor que o comando inicial (ou5
(ou mais) ou4
), ele terá que pular o número apropriado do outro valor (4
ou5
(ou mais) respectivamente) na pesquisa)Loop, até que a instrução diga que você precisa sair do programa.
Quando o programa terminar, emita os valores na fita de dados da posição
0
até a primeira posição da fita que contém um-1
valor.Prova
Observe que o idioma é essencialmente mapeado para um intérprete Brainfuck sem IO, onde
F_5
é necessário que você possa executar qualquer tipo de loops adequados.No entanto, com base na conjectura Fermat principal, existem apenas 5 primos Fermat (
F_0
-F_4
). SeF_5
existe, o idioma é Turing-complete, como sabemos que Brainfuck é Turing-complete. No entanto, semF_5
você não será capaz de ramificar nem fazer loop, essencialmente prendendo você em programas muito simples.Implementação
(testado com ruby 2.3.1)
Exemplos:
Isso gravará
H
(abreviação deHello World!
) na tela com uma nova linha:Salve como
example.fermat
e execute-o assim (nota: você sempre precisa ter uma entrada):Este próximo exemplo fará uma cifra simples no estilo Caesar, incrementando cada valor da entrada em um. Obviamente, você precisa substituir
?
o 5º Fermat prime:Você pode testar se funciona ativando o modo de fraude e usando
2 4 1 2 5 3
como código-fonte:fonte
5
. Espero que eles tenham um bom teclado.Andorinhas c / Coco v2
Como a versão anterior apresentava erros que a tornavam inválida para este concurso, e não quero que os upvotes da versão anterior sejam significativamente diferentes, essa versão está sendo enviada como uma nova postagem.
Esse idioma não é Turing completo se a conjectura de Collatz puder ser comprovada para todos os números inteiros positivos. Caso contrário, o idioma é Turing completo.
Essa linguagem foi baseada no cardeal .
Primeiro, o contVal do programa é calculado usando a fórmula
contVal = sum (soma (valores ASCII da linha) * 2 ^ (número da linha-1))
Em seguida, duas andorinhas em direções opostas são criadas em cada A ou E e todas as instruções de curva condicionais são definidas para aguardar a inicialização.
As andorinhas criadas no E são direcionadas para a esquerda / direita e as andorinhas criadas no A são direcionadas para cima / para baixo.
Por fim, o código executará as etapas até que todos os ponteiros sejam removidos ou o contVal caia para um.
Em cada etapa, se contVal% 2 == 0, ele será dividido por 2; caso contrário, será multiplicado por três e incrementado por um.
Comandos:
0: defina o valor como 0
+: aumente o valor em 1
>: altere a direção para a direita
v: altere a direção para a direita
<: altere a direção para a esquerda
^: altere a direção para a esquerda R : altere a direção para cima
R: ponteiros subsequentes após o primeiro ponteiro compararem com o valor do primeiro ponteiro. Se for igual, siga em frente, depois vire à direita.
L: Os ponteiros subsequentes após o primeiro ponteiro são comparados com o valor do primeiro ponteiro. Se for igual, siga em frente, depois vire à esquerda.
E: Duplicar o ponteiro, mas seguindo nas direções esquerda e direita
A: Duplicar o ponteiro, mas seguindo nas direções para cima e para baixo
? : Remova o ponteiro se o valor for 0
Mostrar snippet de código
Explicação:
Se a conjectura de Collatz puder ser comprovada para todos os números inteiros positivos, a duração de qualquer programa executado nesse idioma será finita, pois o contVal sempre convergirá para 1, finalizando o programa.
Caso contrário, eu só preciso provar que esse idioma pode implementar as seguintes funções
Incremento: representado por +
Constante 0: representado por 0
Acesso variável: as variáveis são armazenadas como ponteiros enquanto viajam
Concatenação de instrução: alterando a distância percorrida para as operações, a ordem na qual as operações são executadas pode ser alterada
Loop For: Neste idioma
atuará como um loop for> conte até 1 (código adicional pode ser adicionado ao loop)
Da mesma forma, o código
Atuará como um fazer até igual ao valor condicional definido no loop R.
fonte
contVal
cada passo (e, portanto, se a conjectura é verdadeira, não há loops infinitos) - mas não vejo isso explicitamente declarado em nenhum lugar da resposta. ??Perfeição / Imperfeição
Uau, isso foi divertido.
Perfeição / Imperfeição só é completa se houver números perfeitos infinitos. Se houver, chama-se Perfeição, e se não houver, chama-se Imperfeição. Até que esse mistério seja resolvido, ele possui os dois nomes.
Um número perfeito é um número cujos divisores somam o número, então seis é um número perfeito porque
1+2+3=6
.Perfeição / Imperfeição tem as seguintes funções:
Perfeição / imperfeição é baseada em pilha, com uma pilha indexada a zero.
Comandos:
p(x, y)
: empurra x para a pilha na posição y.z(x, y)
: empurra x para a pilha na enésima posição, se livra do que estava anteriormente na enésima posiçãor(x)
: remove o décimo item da pilhak(x)
: retorna o décimo item na pilhaa(x, y)
: adiciona x e y. Quando usado com strings, ele os reúne na ordem xy.s(x, y)
: subtrai y de x. com cadeias, remove o último len (y) de xm(x, y)
: multiplica x e y. Se usado com cadeias, multiplica x vezes len y.d(x, y)
: divide x por yo(x)
: imprime xi(x, y)
: se x for avaliado como true, ele executa a função yn()
: retorna o contador no qual o bloco de códigos está sendo chamado.q()
: retorna o comprimento da pilhat()
: entrada do usuárioe(x, y)
: Se x é um número inteiro, se x e y têm o mesmo valor, isso retorna 1. se y é uma string, obtém o comprimento de y. se x é uma string, ele converte y em uma string e verifica se são iguais e, se forem, retorna 1. Caso contrário, retorna 0.l(x, y)
: se x for maior que y, ele retornará 1. Se houver uma sequência, ela usará o comprimento da sequência.b()
: interrompe o programa.c(x, y)
: executa x e, em seguida, y.Para obter o equivalente a um Python
and
, multiplique os dois valores. Paraor
, adicione os valores e paranot
, subtraia o valor de 1. Isso funciona apenas se o valor for 1 ou 0, o que pode ser alcançado dividindo o número por si próprio.Tipos de dados: números inteiros e seqüências de caracteres. As cadeias são indicadas por
''
e todos os números não inteiros são arredondados.Sintaxe:
O código consiste em funções aninhadas dentro de dez
{}
s. Por exemplo, um programa que iria começar a entradas e imprimi-los adicionado seria:{o(a(t(), t()))}
. No fundo do programa, existe um contador que inicia em 0 e progride em 1 toda vez que executa um bloco de código. O primeiro bloco de código é executado em0
e assim por diante. Uma vez que os dez blocos de código são executados, o sexto é executado toda vez que o contador atinge um número perfeito. Você não precisa ter todos os dez blocos de código para o programa funcionar, mas precisa de 7 se desejar fazer um loop. Para entender melhor como essa linguagem funciona, executar o seguinte programa, que imprime o contador cada vez que o contador chegar a um número perfeito:{}{}{}{}{}{}{o(n())}
.O intérprete pode ser encontrado aqui: repl.it/GL7S/37 . Selecione 1 e digite seu código no terminal ou cole seu código na
code.perfect
guia e selecione 2 ao executar. Fará sentido quando você tentar.Prova de completude de Turing / falta de completude de Turing.
De acordo com este artigo de troca de pilha de engenharia de software , um Turing complete deve poder ter uma forma de repetição condicional de salto e ter uma maneira de ler ou gravar memória. Ele pode ler / gravar memória na forma de pilha e pode executar um loop devido ao fato de o sexto bloco de código ser executado toda vez que o contador atingir um número perfeito. Se houver um número infinito de números perfeitos, ele poderá fazer um loop indefinidamente e Turing estiver completo, caso contrário, não o será.
Intérprete de etiqueta cíclica auto-a-bit que aceita 5 caracteres, 1 ou 0, como entrada:
Ele pode ser expandido para receber qualquer número de caracteres como entrada. Pode levar uma entrada infinita, mas apenas se houver números perfeitos infinitos!
fonte
Soles
Essa linguagem de programação é Turing completa se a conjectura de Scholz for verdadeira.
Eu escrevi esse idioma porque @SztupY estava dizendo que não haveria nenhum resultado que confiasse na conjectura para ser verdade, para que Turing estivesse completo
Lista de Comandos
Com esses comandos, esse idioma pode simular uma máquina Minsky
Intérprete
Eu recomendo não executar isso. Ele usa um método extraordinariamente lento de verificar a cadeia de adição.
Mostrar snippet de código
Conclusão de Turing
A linguagem usa um contador para o número de comandos executados, que são comparados com a conjectura de Scholz para modificar a integridade da linguagem.
Se a conjectura de Scholz for verdadeira, este programa funcionará exatamente como uma máquina Minsky normal com Salto de Decremento
Incrementar se Zero Parar
No entanto, se a conjectura de Scholz for falsa, o contador acabará por atingir um valor para o qual a conjectura de Scholz não é verdadeira. Como a linguagem foi projetada para sair ao atingir um número que a conjectura de Scholz é falsa, o programa será encerrado todas as vezes após a execução de muitos comandos. Portanto, todos os programas terão duração limitada. Como isso não concorda com os requisitos para o idioma ser Turing completo,
o idioma não estaria completo em Turing, se a conjectura de Scholz fosse falsa
fonte
Prometido
Github prometido .
O leia-me e a especificação estão no github, em "README.txt".
Geralmente, um programa de noivos é composto por pares de linhas, cujos comprimentos são pares primos gêmeos distintos ou pares de noivos (nenhuma duplicata pode ocorrer). O programa é executado ao encontrar "subconjuntos flexíveis" da primeira linha do par na segunda linha. O número de tais subconjuntos, combinado com a distância levenshtein entre a segunda linha original e a segunda linha sem os subconjuntos flexíveis, determina o comando a ser executado.
Vou extrair a prova para este post:
fonte
b
. Isso interpreta um programa BF, que é colocado depois dele, comob+++++.
. O tamanho do programa, no entanto, é limitado a 10 caracteres. Embora possa interpretar BF, não pode computar todos os programas que uma máquina de Turing pode.Paridade Amigável
Esse idioma é baseado na existência de números amigáveis com paridade oposta .
Comandos
Controle de fluxo
O programa alterna repetidamente da esquerda para a direita antes de retornar ao início. Se encontrar um "j", verifica o valor para determinar se deve alterar as linhas. Se o número for um número amigável com paridade oposta à sua correspondência, ele descerá uma linha (retornando ao topo). Caso contrário, se o número for um número amigável, ele subirá uma linha, se ainda não estiver na linha superior.
O programa só pode terminar se o programa atingir um x em qualquer linha fora da linha superior.
Completude de Turing
Este programa pode ser usado para simular uma máquina Minsky, assumindo que há um par de números amigáveis com paridade oposta.
j, {e} podem ser usados para simular JZ (r, x), embora verifique se há números amigáveis em oposição a zero.
+ é INC (r)
- é DEC (r)
x é HALT
Se você não conseguir sair da primeira linha, os comandos x e} não farão nada. Isso faz com que o programa não consiga entrar no estado HALT, a menos que seja um programa vazio. Portanto, sob a descrição de que a integridade de Turing exige um estado HALT , o idioma seria Turing incompleto.
Intérprete
Mostrar snippet de código
fonte
Nova linha
Disclaimer: É um pouco de confusão e bastante simples. Esta é a primeira língua que já escrevi e a conjectura é a única que entendi. Sei que outro usuário teve uma resposta mais longa com a mesma, mas decidi escrever isso de qualquer maneira.
Para escrever em Nova linha, você deve ter muito tempo e novas linhas (
\n
). Isso funciona com a conjectura de Legendre sendo verdadeira. Todo operador deve recorrer a um número na conjectura de Legendre que começamos com n = 1. Toda vez que você tem um operador, pega a quantidade de \ n e a conecta à Conjectura de Legendre e obtém o intervalo que a próxima quantidade principal de \ n deve cair. Então, para começar\n\n
, você passa para um operador e\n
depois para outro operador, estamos com três novas linhas. Agora, o próximo é o 5, para que você adicione\n\n
e atenda o operador, certificando-se de que a última linha do operador tenha a quantidade certa de novas linhas que você possui em uma quantidade principal que se enquadra na conjectura de Legendre que começamos.Os números (a matriz) são como as variáveis. Toda vez que um operador executa (que usa números), ele aumenta.
Desde que tenhamos números primos ilimitados que sigam as regras, esse idioma possui fita não finita.
Minsky machine
Como funciona:
Experimente na KhanAcademy .
fonte
Taggis
Taggis é uma linguagem baseada em sistemas de tags .
A completude do processo de Taggis é baseada na conjectura de Collatz
Sintaxe
A sintaxe de um programa Taggis é simplesmente três strings (regras de produção) que consistem inteiramente nas letras a, bec, separadas por espaços.
Execução
O único estado do programa do Taggis é uma sequência que consiste nos mesmos três caracteres.
O Taggis implementa um sistema de tags TS (3, 2), onde a cada passo as 2 primeiras letras da "tag" atual são removidas, e a primeira letra que estava nessa parte removida recebe sua regra de produção correspondente anexada ao final de a corda.
Por exemplo, o programa Taggis
bc a aaa
implementa o problema 3n + 1, em que as iterações são representadas por um número correspondente de sea
a etapa 3n + 1 é substituída por (3n + 1) / 2 [1], levando à saída do programa:Conclusão de Turing
Obviamente, esse sistema simples pode parecer simples demais para simular a integridade de Turing, mas acontece que qualquer máquina de Turing com 2 símbolos (uma classe que inclui máquinas universais) pode ser convertida em um sistema de tags com 2 caracteres removidos da cabeça, e regras de produção de 32 m, onde
m
é o número de estados na máquina de Turing.A menor máquina universal de Turing conhecida com apenas 2 símbolos usa 18 estados e, portanto, o sistema de tags correspondente contém 576 regras de produção impressionantes [2].
No entanto, a classe computacional do conjunto de todos os sistemas de tags com 3 produções e 2 símbolos removidos está ligada à conjectura de Collatz [2]. Se a conjectura de Collatz for falsa, Taggis estará completo em Turing. Caso contrário, é baseado em OUTRO problema não resolvido em matemática, encontrando uma máquina de Turing menor do que
que é equivalente à função original Collatz, pois 3n + 1 de um ímpar
n
será sempre par e, portanto, a divisão pode ser aplicada automaticamenteSistemas de tags e funções semelhantes a Collatz, Liesbeth De Mol ,
fonte