Nada mal para um tarpit de Turing bastante detalhado ...
N
Count i while _%128-9 {
Count x while _/128%2 {
Write 40
_+128
}
Write _%128
_+128-_%128+N
}
Count j while _/256-j {
Write 41
}
(Sim, todo esse espaço em branco é obrigatório.)
Nota: devido às limitações de entrada do Acc !! , é impossível ler uma sequência arbitrária de caracteres sem um delimitador final. Portanto, este programa espera entrada (no stdin) como uma sequência seguida por um caractere de tabulação.
Acc !! ?
É uma linguagem que criei que parece apenas inutilizável . O único tipo de dados são números inteiros, a única construção de fluxo de controle é o Count x while yloop, e a única maneira de armazenar dados é um único acumulador _. A entrada e a saída são executadas um caractere de cada vez, usando o valor especial Ne a Writeinstrução Apesar dessas limitações, tenho certeza de que Acc !! é Turing completo.
Explicação
A estratégia básica em Acc !! A programação é usar a %divisão mod e número inteiro /para particionar conceitualmente o acumulador, permitindo que ele armazene vários valores ao mesmo tempo. Neste programa, usamos três seções: os sete bits de ordem mais baixa ( _%128) armazenam um código ASCII da entrada; o próximo bit ( _/128%2) armazena um valor de flag; e os bits restantes ( _/256) contam o número de parênteses necessárias.
Entrada em Acc !! vem do valor especial N, que lê um único caractere e avalia seu código ASCII. Qualquer declaração que consiste apenas em uma expressão atribui o resultado dessa expressão ao acumulador. Então, começamos armazenando o código do primeiro caractere no acumulador.
_%128irá armazenar o caractere lido mais recentemente. Portanto, o primeiro loop é executado enquanto _%128-9é diferente de zero - ou seja, até o caractere atual ser uma guia.
Dentro do loop, queremos imprimir, a ( menos que estejamos na primeira iteração. Desde Acc !! não tem declaração if, temos que usar loops para condicionais. Usamos o bit 128 do acumulador _/128%2, como valor de flag. Na primeira passagem, a única coisa no acumulador é um valor ASCII <128, portanto, o sinalizador é 0 e o loop é ignorado. Em cada passe subsequente, garantiremos que a bandeira seja 1.
Dentro do Count xloop (sempre que o sinalizador é 1), escrevemos um paren aberto (ASCII 40) e adicionamos 128 ao acumulador, configurando o sinalizador para 0 e saindo do loop. Isso também aumenta o valor de _/256, que usaremos como registro de proximidade a ser produzido.
Independentemente do valor da flag, escrevemos o char de entrada mais recente, que é simplesmente _%128.
A próxima tarefa ( _+128-_%128+N) faz duas coisas. Primeiro, adicionando 128, ele define o sinalizador para a próxima vez no loop. Segundo, zera o _%128slot, lê outro caractere e o armazena lá. Então nós fazemos um loop.
Quando o Count iloop termina, acabamos de ler um caractere de tabulação, e o valor do acumulador se divide assim:
_%128: 9(o caractere de tabulação)
_/128%2: 1(a bandeira)
_/256: número de caracteres lidos, menos 1
(O menos 1 é porque nós adicionamos 128 ao acumulador apenas uma vez durante a primeira passagem pelo loop principal.) Tudo o que precisamos agora são os parênteses. Count j while _/256-jloops _/256vezes, escrevendo um parêntese (ASCII 41) a cada vez. Voila!