A linguagem de programação mais dificil do mundo
2 participantes
Página 1 de 1
A linguagem de programação mais dificil do mundo
Em 1998 um doido chamado Ben Olmstead desenvolveu uma linguagem d programação chamada Malbolge, com o unico interesse d faze-la ser a linguagem mais dicifil d ser entendida do mundo, e ele conseguiu '-'
Apenas em 2000 foi criado o primeiro programa em malbolge por Anthony Youhas e ele afirmou ter dominado a linguagem
O proprio criador da linguagem "apelidou" ela d Programação do Inferno, e seu nome veio do oitavo círculo do Inferno na Comédia de Dante Alighieri.
Abaixo vcs vão ver o exemplo do conhecido Hello World feito em C, e mais abaixo ele feito em Malbolge.
Hello world em C:
Agr veja em Malbolge
Hello World em Malbolge:
A diferença é minima n é?! kkk
Para quem quiser saber mais sobre Malbolge: https://blol.org/735-malbolge-desmistificado
Apenas em 2000 foi criado o primeiro programa em malbolge por Anthony Youhas e ele afirmou ter dominado a linguagem
O proprio criador da linguagem "apelidou" ela d Programação do Inferno, e seu nome veio do oitavo círculo do Inferno na Comédia de Dante Alighieri.
Abaixo vcs vão ver o exemplo do conhecido Hello World feito em C, e mais abaixo ele feito em Malbolge.
Hello world em C:
- Código:
#include<stdio.h>
main()
{
printf("Hello World");
}
Agr veja em Malbolge
Hello World em Malbolge:
- Código:
(=<`:9876Z4321UT.-Q+*)M'&%$H"!~}|Bzy?=|{z]KwZY44Eq0/{mlk**
hKs_dG5[m_BA{?-Y;;Vb'rR5431M}/.zHGwEDCBA@98\6543W10/.R,+O<
A diferença é minima n é?! kkk
Para quem quiser saber mais sobre Malbolge: https://blol.org/735-malbolge-desmistificado
Re: A linguagem de programação mais dificil do mundo
Malbolge é uma linguagem de programação esotérica inventada por Ben Olmstead em 1998, cujo nome veio do oitavo círculo do Inferno na Divina Comédia de Dante Alighieri.
A maior característica de Malbolge é que ela foi especialmente desenhada para ser a pior linguagem de programação possível (a mais difícil e mais esotérica). Porém, muitos truques usados para complicá-la podem ser simplificados e entendidos.
Um pouco Mais da Linguagem
1. Introdução:
Criada por Ben Olmstead em 1998, e ganhou esse nome baseado no filme Inferno de Dante. Seu grande diferencial é ter sido desenvolvida para ser a pior linguagem possível para se programar, e o trabalho de seus desenvolvedores é torná-la o mais impossível de ser entendida pelos seus programadores.
2. Fatos da programação:
Malbolge é tão difícil de ser entendida que somente depois de dois anos de ter sido inventada que surgiu seu primeiro programa. Por sinal, não foi criado por um humano, mas sim por um algoritmo baseado em LISP, desenvolvido por Andrew Cooke.
Em 24 de Agosto de 2000, Anthony Youhas garantiu ter dominado a linguagem depois de ter conseguido criar três programas que conseguiam apenas imprimir várias frases diferentes!
Diz-se inclusive que levaria anos para se implementar uma simples instrução de repetição em Malbolge...
3. Implementando o Hello World!
nós fazemos o computador mostrar na tela a frase "Hello World". Apenas isso.
Esse seria o código Malbolge para fazer o computador mostrar na tela a frase "Hello World":
Basicamente, o Malbolge utiliza três registradores, que funcionam como variáveis: a, c, d. Elas iniciam com valor zero, onde c recebe a instrução que irá ser processada no momento, e d recebe um endereço de memória específico das operações implementadas.
Possui 59049 locações de memórias virtuais que podem armazenar números de dez dígitos. A primeira parte dessas locações recebem o programa, e as restantes são preenchidas por dados de uma instrução chamada Crazy Operation, que recebem os endereços anteriores
5. Instruções:
Malbolge possui 8 instruções, que funcionam a partir do valor que foi atribuído no registrador c. Em seguida, adiciona um valor de acordo com a instrução e subtrai por 94 até o número respectivo ser menos que 94. De acordo com o valor retornado, o interpretador Malbolge retornará a seguinte resposta:
4: O valor que está guardado no endereço de memória d será somado com um e e alí executará a dada operação.
5: Imprime o valor ASCII armazenado na variável a.
23: Adiciona o código ASCII da tecla pressionada na execução do algoritmo em a.
39: Rotaciona o valor que estiver armazenado em D em um dígito (por exemplo, se for o numero
40: Copia o valor armazenado em d e envia para d em forma de endereço de memória.
62: Realiza a Crazy Operation (que veremos logo abaixo) com o valor armazenado no endereço de memória d e com a e o armazena nos dois registradores.
68: Não faz nada.
81: Termina de executar o algoritmo.
Terminado de executar, o interpretador criptografa as instruções para que não realize a mesma função futuramente, e torne toda a tarefa de criação do algoritmo mais complexa.
5.1 Crazy Operation:
Pega dois valores ternários de dez dígitos e retorna os valores de acordo com a seguinte tabela ternária, como no exemplo:
Se executarmos a crazy operation
De forma bem simples, você compara cada digito individualmente e compara com o que está demonstrado na tabela. Por exemplo, se o crz 0001112220, 012012012 é esse, comparamos primeiro o
Simples demais, não?
5.2 Encriptação:
Depois de executar uma instrução, o que foi armazenado em C será subtraido repetidas vezes por 94, até seu resultado ser menor que 94. Em seguida, pode ser criptografada em dois métodos (só demonstraremos um pelo fato do segundo exigir atenção de uma tabela gigantesca):
Método 1: Retorna o seguinte trecho criptografado a partir do valor ASCII armazenado em c:
Código:
A maior característica de Malbolge é que ela foi especialmente desenhada para ser a pior linguagem de programação possível (a mais difícil e mais esotérica). Porém, muitos truques usados para complicá-la podem ser simplificados e entendidos.
Um pouco Mais da Linguagem
1. Introdução:
Criada por Ben Olmstead em 1998, e ganhou esse nome baseado no filme Inferno de Dante. Seu grande diferencial é ter sido desenvolvida para ser a pior linguagem possível para se programar, e o trabalho de seus desenvolvedores é torná-la o mais impossível de ser entendida pelos seus programadores.
2. Fatos da programação:
Malbolge é tão difícil de ser entendida que somente depois de dois anos de ter sido inventada que surgiu seu primeiro programa. Por sinal, não foi criado por um humano, mas sim por um algoritmo baseado em LISP, desenvolvido por Andrew Cooke.
Em 24 de Agosto de 2000, Anthony Youhas garantiu ter dominado a linguagem depois de ter conseguido criar três programas que conseguiam apenas imprimir várias frases diferentes!
Diz-se inclusive que levaria anos para se implementar uma simples instrução de repetição em Malbolge...
3. Implementando o Hello World!
nós fazemos o computador mostrar na tela a frase "Hello World". Apenas isso.
Esse seria o código Malbolge para fazer o computador mostrar na tela a frase "Hello World":
- Código:
(=<`:9876Z4321UT.-Q+*)M'&%$H"!~}|Bzy?=|{z]KwZY44Eq0/{mlk**
hKs_dG5[m_BA{?-Y;;Vb'rR5431M}/.zHGwEDCBA@98\6543W10/.R,+O<
Basicamente, o Malbolge utiliza três registradores, que funcionam como variáveis: a, c, d. Elas iniciam com valor zero, onde c recebe a instrução que irá ser processada no momento, e d recebe um endereço de memória específico das operações implementadas.
Possui 59049 locações de memórias virtuais que podem armazenar números de dez dígitos. A primeira parte dessas locações recebem o programa, e as restantes são preenchidas por dados de uma instrução chamada Crazy Operation, que recebem os endereços anteriores
- Código:
([m] = crz [m - 2], [m - 1])
5. Instruções:
Malbolge possui 8 instruções, que funcionam a partir do valor que foi atribuído no registrador c. Em seguida, adiciona um valor de acordo com a instrução e subtrai por 94 até o número respectivo ser menos que 94. De acordo com o valor retornado, o interpretador Malbolge retornará a seguinte resposta:
4: O valor que está guardado no endereço de memória d será somado com um e e alí executará a dada operação.
5: Imprime o valor ASCII armazenado na variável a.
23: Adiciona o código ASCII da tecla pressionada na execução do algoritmo em a.
39: Rotaciona o valor que estiver armazenado em D em um dígito (por exemplo, se for o numero
- Código:
000111254
- Código:
400011125
40: Copia o valor armazenado em d e envia para d em forma de endereço de memória.
62: Realiza a Crazy Operation (que veremos logo abaixo) com o valor armazenado no endereço de memória d e com a e o armazena nos dois registradores.
68: Não faz nada.
81: Termina de executar o algoritmo.
Terminado de executar, o interpretador criptografa as instruções para que não realize a mesma função futuramente, e torne toda a tarefa de criação do algoritmo mais complexa.
5.1 Crazy Operation:
Pega dois valores ternários de dez dígitos e retorna os valores de acordo com a seguinte tabela ternária, como no exemplo:
Se executarmos a crazy operation
- Código:
crz 0001112220, 012012012
- Código:
1001022211
- Código:
///0 1 2 0 1 0 0 1 1 0 2 2 2 2 1
De forma bem simples, você compara cada digito individualmente e compara com o que está demonstrado na tabela. Por exemplo, se o crz 0001112220, 012012012 é esse, comparamos primeiro o
- Código:
0001112220
- Código:
012012012
- Código:
///0 1 2 0 1 0 0 1 1 0 2 2 2 2 1
Simples demais, não?
5.2 Encriptação:
Depois de executar uma instrução, o que foi armazenado em C será subtraido repetidas vezes por 94, até seu resultado ser menor que 94. Em seguida, pode ser criptografada em dois métodos (só demonstraremos um pelo fato do segundo exigir atenção de uma tabela gigantesca):
Método 1: Retorna o seguinte trecho criptografado a partir do valor ASCII armazenado em c:
Código:
- Código:
0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123
- Código:
9m<.TVac`uY*MK'X~xDl}REokN:#?G"i@5z]&gqtyfr$(we4{WP)H-Zn,[%\3dL+Q;>U!pJS72FhOA1CB6v^=I_0/8|jsb[b][b][i][u][u][u][strike][strike][/strike][/strike][/u][/u][/u][/i][/b][/b]
Re: A linguagem de programação mais dificil do mundo
Introdução à Malbolge
Malbolge, Para aqueles não familiarizados com ele, é uma linguagem concebida para ser difícil (ou talvez impossível - até recentemente, não havia sequer um argumento informal mostrando Turing completude ) Para programar. Por exemplo, o efeito de qualquer instrução depende de onde ele está localizado na memória (mod 94, naturalmente), todas as instruções são auto-modificando (de acordo com uma tabela de permutação) e tanto o código de dados e os ponteiros estão incrementado após cada instrução, o que torna difícil para re-utilizar qualquer código ou dados. Não há nenhuma maneira para inicializar a memória, exceto para um dos 8 caracteres de instrução, não há carga ou STORE operador, e os únicos operadores de memória disponíveis (tanto deles) trabalham em trinary e são projetados para ser opaco. A única construção fluxo de controle é um salto incondicional computadorizada, que também é quase inútil uma vez que não há nenhuma maneira (ou certamente nenhuma maneira óbvia) para definir a memória de qualquer coisa, exceto os 8 caracteres de instrução.
Acredite ou não,
Originalmente, as informações sobre Malbolge foi publicado no site abaixo, embora este site agora está morto, de acordo com o autor: http://www.mines.edu/students/b/bolmstea/malbolge/
Felizmente (ou talvez não) essa informação foi preservada. Uma cópia do site original foi arquivado em
http://web.archive.org/web/20000815230017/http:/www.mines.edu/students/b/bolmstea/malbolge/
A especificação da linguagem copiada do site original:Especificação da linguagem Malbolge
O intérprete de referência copiado do site original: Malbolge Interpreter.
Nota: Sempre que a especificação eo intérprete diferem (por exemplo, a especificação chama '<' uma instrução de entrada e '/' um OUPUT, mas o intérprete faz o contrário), neste trabalho o intérprete for considerada correta.
Embora a língua tinha sido fora desde 1998, por muitos anos os programas conhecidos mais complexos era "Olá, mundo", disponível em várias versões.
http://www.acooke.org/andrew/writing/malbolge.html
http://www.antwon.com/index.php?p=234
http://www.wikipedia.org/wiki/Malbolge_programming_language
http://www2.latech.edu/~acm/helloworld/malbolge.html
Em 2004, com base na análise que se segue, eu escrevi um programa que copiou entrada à saída, apesar de não encerrar corretamente no final da entrada.
Houve uma reivindicação que os '99 garrafas de cerveja programa "tinha sido escrito em Malbolge. (O site foi (agora morto): http://99-bottles-of-beer.ls-la.net/m.html ) A implicação é que o programa estava fazendo looping, teste e impressão. No entanto, um exame mais atento mostra que o programador estava apenas fazendo um printf ("") do resultado desejado usando o código linha reta. Conceitualmente isso é exatamente o mesmo que o exemplo 'Olá mundo' acima.
Esta difícil tarefa de escrever um programa em geral Malbolge foi concluída para o real em 2005 por Hisashi Iizawa, Toshiki Sakabe, Masahiko Sakai, Keiichirou Kusakari, e Naoki Nishida. Seu papel "Método Programação em Linguagem ofuscado Malbolge" (em japonês) podem ser encontradas em http://www.sakabe.i.is.nagoya-u.ac.jp/~nishida/DB/pdf/iizawa05ss2005-22.pdf . O código fonte resultante para '99 garrafas de cerveja "pode ser encontrado em: http://www.99-bottles-of-beer.net/language-malbolge-995.html . Embora alguns da teoria desenvolvida aqui foi utilizado, reduzindo esta a prática era uma incrível façanha de programação proeza.
Malbolge como um sistema de encriptação
A maneira correta de pensar sobre Malbolge , Estou convencido, é como um criptógrafo e não um programador. Pense nisso como um código complexo e / ou algoritmo que transforma entrada para a saída. Em seguida, estudá-la para ver se você pode tirar proveito de suas fraquezas para forjar uma mensagem que produziu a saída que você deseja.
Encarado como um sistema de encriptação, tem vários pontos fracos:
Alguns ciclos de permutação são curtos
Em primeiro lugar, as instruções auto modificadoras não formam uma grande permutação. (Se eles fizeram, então qualquer instrução executado vezes suficientes sempre se transformar em um "Halt" em algum ponto). Assim, podemos encontrar instruções, que quando executado, se transformam em outras instruções, e depois de volta. Por exemplo, uma instrução OP, quando este se encontra na posição 20 (mod 94), vai tornar-se uma instrução de carga, então um NOP, em seguida, uma outra NOP, em seguida, de volta para uma instrução de PO, e assim por diante. Os ciclos são comprimento 2, 9, 4, 5, 6, e 68, e as instruções a serem executadas por cada ciclo depende da posição a partir da modificação 94. Em geral, os ciclos curtos são mais úteis do que os longos, mas o longo ciclo a dois mod 94 é muito bom, como ele ciclos entre as instruções de entrada, saída e de carga D de registro. Uma lista de todos os ciclos podem ser encontrados Aqui.
Instruções de salto não auto modificar
O próximo ponto fraco é uma pessoa importante - qualquer instrução salto não é auto modificação! Isso acontece porque a ordem é:
Instrução em C é executada
Instrução no C está embaralhada pela tabela de permutação
C é incrementado
Mas a instrução de ramificação muda C entre os passos (1) e (2). Assim, o endereço de desvio é um a menos que o alvo pretendido, e nem a própria instrução de desvio nem o alvo é modificada (o trabalho antes que o alvo é modificado, mas isso não é tão ruim. Na verdade vamos usar isso para grande vantagem mais tarde). Isto é muito útil, já que é muito mais fácil de lidar com a mudança de instruções do que mudar de fluxo de controle. Além disso, uma vez que uma instrução permuta-em uma instrução de ramo, isso não vai mudar ainda mais.
Inicialização de valores
A próxima fraqueza é no leitor programa. É evidente a partir da descrição de texto que a intenção é permitir que únicas instruções válidas a ser escrita na memória, e no resto da memória será preenchido pelo circuito OP. Isso em geral evita que o usuário (ab) seja iniciado com a memória configurada para quaisquer valores úteis. No entanto, a inspeção do código revela que caracteres não-impressão (0-31) e (128-255) são escritos diretamente para a memória sem verificar (exceto nova linha, tabulação, e alguns outros caracteres em branco (aqueles selecionados por isspace () ), que são ignorados). Alguém poderia argumentar isto é simplesmente um bug no interpretador, mas aproveitando um erro no intérprete parece muito no personagem (por assim dizer). Isto é muito útil, que permite o programador para assegurar que o endereço de destino de desvio para a direita é na local na memória, por exemplo.
Usando estas fraquezas, tenho conseguido escrever um Malbolge programa que copia sua entrada para a sua saída. Desde alguns de que é
não-impressão, aqui está uu-codificado:
começar
Aqui estão mais algumas observações, não aproveitadas ainda:
Obtendo aroung o efeito de instruções auto modificadoras
Todas as várias instruções aparecem em laçadas de comprimento 2, embora apenas quando este se encontra em certas posições de memória. Isto significa que você pode escrever uma rotina que faz a coisa certa todas as outras vezes, e nada os tempos alternados. No entanto, uma vez que as instruções só fará isso quando localizados nos pontos adequados, é necessário ramificar depois de cada um. Por exemplo, suponha que você queria fazer
Entrada
TO
rodar
Naquela ordem. Você pode fazer isso em qualquer local, mas apenas uma vez. Se você tentar executá-lo novamente, as instruções terá auto modificada de várias maneiras, ea próxima tentativa vai fazer algo un-pretendido. No entanto, se você fazê-lo desta forma:
De entrada (na posição 53, 94 mod)
Ramificação para 82
OP (no local 82, mod 94)
filial a 59
gire (no local 59, mod 94)
filial
Em seguida, cada instrução é localizado em que é parte de um ciclo de 2. Assim, a primeira vez que ele vai fazer o que é desejado, da próxima vez ele não fará nada em tudo, então da próxima vez que cada um vai fazer a coisa correta novamente .. Na verdade, você pode fazer ainda melhor - você pode executar a rotina, então filial para cada um dos ramos (isso pode funcionar desde que o destino de desvio não está codificado com o ramo, é no segmento de dados. Assim, o mesmo ramo pode saltar para vários locais diferentes.) Então, por ramo de uma filial em vez de ir para o local final diretamente ?? Uma vez que o efeito colateral de uma ramificação for para permutar a instrução apenas antes do alvo ramo! Assim, a execução do código, em seguida, encadeamento através dos ramos, restaura o código (se 2-cycle) para o estado original.
Muitas modificações são possíveis: pré-munging, munge como você vai, ou pós-fixação, como descrito acima. Cada um é útil em algumas circunstâncias.
Construindo NOPs imutáveis
Apenas alguns locais têm NOPs que podem ser carregados inicialmente, e permanecerá sempre NOPs.Existem tais ciclos para todas as localizações (mod 94) , Mas a maioria nunca passar por qualquer instrução oficial e, portanto, não pode ser carregado diretamente. No entanto, todos podem ser carregados, carregando uma constante 129-255, em seguida, fazendo um único rotate (usado como uma divisão por três.) Isto dá números na faixa de 43-85 (Note que os números devem ser divisível por três uma vez que a LST vai ser rodado para a trit mais significativo). Cada local tem pelo menos uma laçada NOP que contém um tal número.
Note-se que, no caso de NOPs, como em filiais, não precisa se preocupar com a duração do ciclo, embora por diferentes razões (ramos não mudam, e NOPs mudar, mas nós não nos importamos, enquanto eles se transformam em outro PON).
Algumas observações sobre o operador OP:
OP é definido como:
Se a memória (* D) é todos os queridos, então o resultado é apenas a um registo com 1s e 0s trocados.
Se o A é trit todos 2s, em seguida, o resultado é a memória com 1 e 2 trocados.
Todos os valores que são fáceis de encontrar (instruções ou entrada) terá 0s em suas Trits superiores. Assim, depois de qualquer OP eles terão todos os 1s nestes posição.
Você pode definir um local de memória para um valor conhecido como segue: Primeiro OP um local com si mesmo. (Qualquer instrução RODAR ou OP irá definir o registro A e memória para o mesmo valor). Depois de repor o registo D, em seguida, em vias com ele mesmo, um local conterá apenas 0s e 1s. Então, se você OP com um A de 0, você vai ter todos os queridos. Se você OP com um A de todos 1s, você vai configurar A e memória a 0.
Cargas e Lojas:
Pode sintetizar uma carga de 10 roda (que restaura o original). Alternativamente, você pode preencher um com todos os 2s, então OP a localização (que troca 1s e 2s na localização da memória. Em seguida, repita este processo, que troca a memória de volta e cargas A com o novo valor corrigido .. Você pode sintetizar um ' loja "por vias de duas vezes em locais fulled com todos" 1 de. (Se o trit memória é 1, então o bit OP é escrita com 0 e 1 revertida e 2 manteve o mesmo. Se você fizer isso duas vezes que você começa a parte traseira original).
Fazendo a aritmética em Malbolge
Eu suspeito que a melhor maneira de fazer aritmética é de pesquisa da tabela. Mesmo que isso é difícil (você precisa de uma mesa cheia de valores computados, seguido por uma matriz de tamanho igual de metas de filiais. Então você carrega o valor com uma instrução RODAR ou OP seguido por um valor de tabelas de NOPs imutáveis, seguido por uma carga e ramo. Claro que isso embaralha sua entrada na tabela, que deve então ser desfeita, e assim por diante.). Isso ainda parece mais fácil do que a síntese de aritmética de PO e gira, pelo menos para mim.
Densidade Código
A maior parte destas técnicas requerem considerável código para executar operações simples. Em geral, isso não é problema, e não afecta a integralidade Turing teórica. (Se a sua principal preocupação é a densidade do código, talvez Malbolge não é uma boa escolha de idiomas, ....) É um problema na prática, uma vez que apenas a parte inferior 256 locais podem ser facilmente tratadas por qualquer programa que você pode introduzir - quaisquer endereços mais altos deve ser sintetizada. Isso por si só leva um monte de código.
A estratégia geral para escrever programas maiores Malbolge, e provando prático completude de Turing.
Se o código pode ser feito para caber, em seguida, a combinações de PO, gira, e ramos computados deve permitir uma programa de inicialização que lê uma seqüência de byte arbitrário na memória, o que ajudaria a contornar a restrição de 8 caracteres permitido, e permite o uso de mais do espaço de endereço. Então talvez seja possível escrever um BrainF *** ->Malbolge compilador , E assim por diante .... Isto mostra que Molbolge satisfaz a definição prático de Turing completude - pode calcular qualquer problema que se encaixa dentro da sua memória. No entanto, Malbolge nunca pode atender a definição formal de Turing completude, O que exige o acesso a uma quantidade ilimitada de memória.
Provando completude formal de Turing.
No entanto, uma muito ligeira além Malbolge torna verdadeiramente e formalmente Turing completa. Não há nada na especificação Malbolge informando que as operações de entrada e saída não pode se referir ao mesmo fluxo de dados, que, em seguida, pode ser considerada uma fita com um 257 Símbolo do alfabeto. (257 desde ENTRADA pode devolver os valores 0..255, mais o valor especial
Tanto quanto eu posso determinar, Malbolge-T daria resultados idênticos ao clássico Malbolge com todos os programas existentes Malbolge *. (Como se a compatibilidade entre varients Malbolge foi um grande problema prático). No entanto, uma vez que Malbolge-T tem acesso a uma memória externa potencialmente ilimitada, é, pelo menos, tem a possibilidade de ser Turing completa. Na verdade, não é difícil mostrar, usando as técnicas de pesquisa de mesa utilizadas no BrainF *** ->Malbolge compilador , Que uma máquina de estado simples, com transições de estado completamente arbitrários podem ser implementadas. E se você pode implementar uma pequena máquina de estado arbitrário (5 estados vezes 5 símbolos é suficiente), e combiná-lo com a fita bi-direcional, então você pode implementar uma máquina de Turing Universal e, portanto, mostrar verdadeira completude de Turing.
* exceto para o programa de cópia de cima, que seria agora de backup para sempre após EOF na entrada, em vez de vomitar um número infinito de bytes com um valor de 168.
Poderia ser pior
Malbolge, embora, obviamente, difícil, poderia ser pior. Aqui estão algumas sugestões para torná-lo ainda mais difícil:
Refazer a tabela de permutação de instruções para remover todos os ciclos curtos.
Em particular, se cada ciclo possível para cada local contém pelo menos uma instrução não-NOP, então você pode nem mesmo construir um NOP que você pode confiar.
Remova a supervisão no interpretador de referência que permite a carga de usuário valores não-ascii diretamente.
Você poderia fazer o OP ainda menos útil, modificando-o para que o menor número de linhas e colunas como possível conter todos os três valores dígitos. Isso torna difícil para definir valores específicos que contêm todos os três Trits. Como alternativa, faça OP para que o maior número de linhas e colunas como possível conter todos os três valores Trit. Isto torna muito difícil de definir um endereço de memória para nada se você não sabe o valor anterior.
Modifique as instruções de como eles são buscados, e não quando elas são feitas. Então ramos demasiado auto iria modificar.
Feliz programação,
Lou Scheffer
A partir da página línguas estranhas de Ryan Kusnery:
O dia em que alguém escreve, em Malbolge , Um programa que simplesmente copia sua entrada para a sua saída, é o dia do meu cabelo se transforma espontaneamente verde. É o dia em que os elefantes são roxo e camelos voar, e uma vaca pode caber através de fundo de uma agulha.
Eu dedico todo o meu trabalho em Malbolge, em toda e qualquer forma, para o domínio público.
Malbolge, Para aqueles não familiarizados com ele, é uma linguagem concebida para ser difícil (ou talvez impossível - até recentemente, não havia sequer um argumento informal mostrando Turing completude ) Para programar. Por exemplo, o efeito de qualquer instrução depende de onde ele está localizado na memória (mod 94, naturalmente), todas as instruções são auto-modificando (de acordo com uma tabela de permutação) e tanto o código de dados e os ponteiros estão incrementado após cada instrução, o que torna difícil para re-utilizar qualquer código ou dados. Não há nenhuma maneira para inicializar a memória, exceto para um dos 8 caracteres de instrução, não há carga ou STORE operador, e os únicos operadores de memória disponíveis (tanto deles) trabalham em trinary e são projetados para ser opaco. A única construção fluxo de controle é um salto incondicional computadorizada, que também é quase inútil uma vez que não há nenhuma maneira (ou certamente nenhuma maneira óbvia) para definir a memória de qualquer coisa, exceto os 8 caracteres de instrução.
Acredite ou não,
- Código:
02101012220
Originalmente, as informações sobre Malbolge foi publicado no site abaixo, embora este site agora está morto, de acordo com o autor: http://www.mines.edu/students/b/bolmstea/malbolge/
Felizmente (ou talvez não) essa informação foi preservada. Uma cópia do site original foi arquivado em
http://web.archive.org/web/20000815230017/http:/www.mines.edu/students/b/bolmstea/malbolge/
A especificação da linguagem copiada do site original:Especificação da linguagem Malbolge
O intérprete de referência copiado do site original: Malbolge Interpreter.
Nota: Sempre que a especificação eo intérprete diferem (por exemplo, a especificação chama '<' uma instrução de entrada e '/' um OUPUT, mas o intérprete faz o contrário), neste trabalho o intérprete for considerada correta.
Embora a língua tinha sido fora desde 1998, por muitos anos os programas conhecidos mais complexos era "Olá, mundo", disponível em várias versões.
http://www.acooke.org/andrew/writing/malbolge.html
http://www.antwon.com/index.php?p=234
http://www.wikipedia.org/wiki/Malbolge_programming_language
http://www2.latech.edu/~acm/helloworld/malbolge.html
Em 2004, com base na análise que se segue, eu escrevi um programa que copiou entrada à saída, apesar de não encerrar corretamente no final da entrada.
Houve uma reivindicação que os '99 garrafas de cerveja programa "tinha sido escrito em Malbolge. (O site foi (agora morto): http://99-bottles-of-beer.ls-la.net/m.html ) A implicação é que o programa estava fazendo looping, teste e impressão. No entanto, um exame mais atento mostra que o programador estava apenas fazendo um printf ("") do resultado desejado usando o código linha reta. Conceitualmente isso é exatamente o mesmo que o exemplo 'Olá mundo' acima.
Esta difícil tarefa de escrever um programa em geral Malbolge foi concluída para o real em 2005 por Hisashi Iizawa, Toshiki Sakabe, Masahiko Sakai, Keiichirou Kusakari, e Naoki Nishida. Seu papel "Método Programação em Linguagem ofuscado Malbolge" (em japonês) podem ser encontradas em http://www.sakabe.i.is.nagoya-u.ac.jp/~nishida/DB/pdf/iizawa05ss2005-22.pdf . O código fonte resultante para '99 garrafas de cerveja "pode ser encontrado em: http://www.99-bottles-of-beer.net/language-malbolge-995.html . Embora alguns da teoria desenvolvida aqui foi utilizado, reduzindo esta a prática era uma incrível façanha de programação proeza.
Malbolge como um sistema de encriptação
A maneira correta de pensar sobre Malbolge , Estou convencido, é como um criptógrafo e não um programador. Pense nisso como um código complexo e / ou algoritmo que transforma entrada para a saída. Em seguida, estudá-la para ver se você pode tirar proveito de suas fraquezas para forjar uma mensagem que produziu a saída que você deseja.
Encarado como um sistema de encriptação, tem vários pontos fracos:
Alguns ciclos de permutação são curtos
Em primeiro lugar, as instruções auto modificadoras não formam uma grande permutação. (Se eles fizeram, então qualquer instrução executado vezes suficientes sempre se transformar em um "Halt" em algum ponto). Assim, podemos encontrar instruções, que quando executado, se transformam em outras instruções, e depois de volta. Por exemplo, uma instrução OP, quando este se encontra na posição 20 (mod 94), vai tornar-se uma instrução de carga, então um NOP, em seguida, uma outra NOP, em seguida, de volta para uma instrução de PO, e assim por diante. Os ciclos são comprimento 2, 9, 4, 5, 6, e 68, e as instruções a serem executadas por cada ciclo depende da posição a partir da modificação 94. Em geral, os ciclos curtos são mais úteis do que os longos, mas o longo ciclo a dois mod 94 é muito bom, como ele ciclos entre as instruções de entrada, saída e de carga D de registro. Uma lista de todos os ciclos podem ser encontrados Aqui.
Instruções de salto não auto modificar
O próximo ponto fraco é uma pessoa importante - qualquer instrução salto não é auto modificação! Isso acontece porque a ordem é:
Instrução em C é executada
Instrução no C está embaralhada pela tabela de permutação
C é incrementado
Mas a instrução de ramificação muda C entre os passos (1) e (2). Assim, o endereço de desvio é um a menos que o alvo pretendido, e nem a própria instrução de desvio nem o alvo é modificada (o trabalho antes que o alvo é modificado, mas isso não é tão ruim. Na verdade vamos usar isso para grande vantagem mais tarde). Isto é muito útil, já que é muito mais fácil de lidar com a mudança de instruções do que mudar de fluxo de controle. Além disso, uma vez que uma instrução permuta-em uma instrução de ramo, isso não vai mudar ainda mais.
Inicialização de valores
A próxima fraqueza é no leitor programa. É evidente a partir da descrição de texto que a intenção é permitir que únicas instruções válidas a ser escrita na memória, e no resto da memória será preenchido pelo circuito OP. Isso em geral evita que o usuário (ab) seja iniciado com a memória configurada para quaisquer valores úteis. No entanto, a inspeção do código revela que caracteres não-impressão (0-31) e (128-255) são escritos diretamente para a memória sem verificar (exceto nova linha, tabulação, e alguns outros caracteres em branco (aqueles selecionados por isspace () ), que são ignorados). Alguém poderia argumentar isto é simplesmente um bug no interpretador, mas aproveitando um erro no intérprete parece muito no personagem (por assim dizer). Isto é muito útil, que permite o programador para assegurar que o endereço de destino de desvio para a direita é na local na memória, por exemplo.
Usando estas fraquezas, tenho conseguido escrever um Malbolge programa que copia sua entrada para a sua saída. Desde alguns de que é
não-impressão, aqui está uu-codificado:
começar
- Código:
666 copy.mb
M1 "=" _ 04 / CT \ .SHY. # WIY> '= V
M = 71S 75Q;! 6EE85U955% -245 / 3DU, 2 Timóteo)
M2 $ = & # 141 0D% /SX]/#LZ.3@W-C4T,S(Q,"\N+2PK*BDH)R8E)",B(7Y]?'MZ
M> = 7AW G5T
M3 $ M * 24A'1D5 $ 0R9 O;? V] O; V] O; V] O; V] O; V] O; V] O; V] O; V] O; V] O; V] S; V]
MO; V] Y + V] O; V] O; V] O; V] O; V] O; V] O; V] O; V] O; V] O; V] O; V] O; V] O; V] O; V]
MO; V] O; V] O; V] O; V] O; V] O; V] O; V] O; V] O; V] O; V] O; V] O; V] O; V] O; V] O; V]
MO; V] O; V] O; V] O; V] O; V] O; V] O; V] O; V] O; V] O; V] O; V] O; V] O; V] O; V] O; V]
MO; V] O> 2] O; V] O; V] O; V] O; V] O; V] O; V] O; V] O; V] O; V] O; V] O; V] O; V] O;
[code]V]
FAÇA; V] O; V] O; V] O; V] O; V] O; V] O; V] O; V] O; V] O; V] O; V] O; T *
[/code]
Aqui estão mais algumas observações, não aproveitadas ainda:
Obtendo aroung o efeito de instruções auto modificadoras
Todas as várias instruções aparecem em laçadas de comprimento 2, embora apenas quando este se encontra em certas posições de memória. Isto significa que você pode escrever uma rotina que faz a coisa certa todas as outras vezes, e nada os tempos alternados. No entanto, uma vez que as instruções só fará isso quando localizados nos pontos adequados, é necessário ramificar depois de cada um. Por exemplo, suponha que você queria fazer
Entrada
TO
rodar
Naquela ordem. Você pode fazer isso em qualquer local, mas apenas uma vez. Se você tentar executá-lo novamente, as instruções terá auto modificada de várias maneiras, ea próxima tentativa vai fazer algo un-pretendido. No entanto, se você fazê-lo desta forma:
De entrada (na posição 53, 94 mod)
Ramificação para 82
OP (no local 82, mod 94)
filial a 59
gire (no local 59, mod 94)
filial
Em seguida, cada instrução é localizado em que é parte de um ciclo de 2. Assim, a primeira vez que ele vai fazer o que é desejado, da próxima vez ele não fará nada em tudo, então da próxima vez que cada um vai fazer a coisa correta novamente .. Na verdade, você pode fazer ainda melhor - você pode executar a rotina, então filial para cada um dos ramos (isso pode funcionar desde que o destino de desvio não está codificado com o ramo, é no segmento de dados. Assim, o mesmo ramo pode saltar para vários locais diferentes.) Então, por ramo de uma filial em vez de ir para o local final diretamente ?? Uma vez que o efeito colateral de uma ramificação for para permutar a instrução apenas antes do alvo ramo! Assim, a execução do código, em seguida, encadeamento através dos ramos, restaura o código (se 2-cycle) para o estado original.
Muitas modificações são possíveis: pré-munging, munge como você vai, ou pós-fixação, como descrito acima. Cada um é útil em algumas circunstâncias.
Construindo NOPs imutáveis
Apenas alguns locais têm NOPs que podem ser carregados inicialmente, e permanecerá sempre NOPs.Existem tais ciclos para todas as localizações (mod 94) , Mas a maioria nunca passar por qualquer instrução oficial e, portanto, não pode ser carregado diretamente. No entanto, todos podem ser carregados, carregando uma constante 129-255, em seguida, fazendo um único rotate (usado como uma divisão por três.) Isto dá números na faixa de 43-85 (Note que os números devem ser divisível por três uma vez que a LST vai ser rodado para a trit mais significativo). Cada local tem pelo menos uma laçada NOP que contém um tal número.
Note-se que, no caso de NOPs, como em filiais, não precisa se preocupar com a duração do ciclo, embora por diferentes razões (ramos não mudam, e NOPs mudar, mas nós não nos importamos, enquanto eles se transformam em outro PON).
Algumas observações sobre o operador OP:
OP é definido como:
- Código:
| A trit:
________ | _0__1__2_
0 | 1 0 0
* D 1 | 1 0 2
trit 2 | 2 2 1
Se a memória (* D) é todos os queridos, então o resultado é apenas a um registo com 1s e 0s trocados.
Se o A é trit todos 2s, em seguida, o resultado é a memória com 1 e 2 trocados.
Todos os valores que são fáceis de encontrar (instruções ou entrada) terá 0s em suas Trits superiores. Assim, depois de qualquer OP eles terão todos os 1s nestes posição.
Você pode definir um local de memória para um valor conhecido como segue: Primeiro OP um local com si mesmo. (Qualquer instrução RODAR ou OP irá definir o registro A e memória para o mesmo valor). Depois de repor o registo D, em seguida, em vias com ele mesmo, um local conterá apenas 0s e 1s. Então, se você OP com um A de 0, você vai ter todos os queridos. Se você OP com um A de todos 1s, você vai configurar A e memória a 0.
Cargas e Lojas:
Pode sintetizar uma carga de 10 roda (que restaura o original). Alternativamente, você pode preencher um com todos os 2s, então OP a localização (que troca 1s e 2s na localização da memória. Em seguida, repita este processo, que troca a memória de volta e cargas A com o novo valor corrigido .. Você pode sintetizar um ' loja "por vias de duas vezes em locais fulled com todos" 1 de. (Se o trit memória é 1, então o bit OP é escrita com 0 e 1 revertida e 2 manteve o mesmo. Se você fizer isso duas vezes que você começa a parte traseira original).
Fazendo a aritmética em Malbolge
Eu suspeito que a melhor maneira de fazer aritmética é de pesquisa da tabela. Mesmo que isso é difícil (você precisa de uma mesa cheia de valores computados, seguido por uma matriz de tamanho igual de metas de filiais. Então você carrega o valor com uma instrução RODAR ou OP seguido por um valor de tabelas de NOPs imutáveis, seguido por uma carga e ramo. Claro que isso embaralha sua entrada na tabela, que deve então ser desfeita, e assim por diante.). Isso ainda parece mais fácil do que a síntese de aritmética de PO e gira, pelo menos para mim.
Densidade Código
A maior parte destas técnicas requerem considerável código para executar operações simples. Em geral, isso não é problema, e não afecta a integralidade Turing teórica. (Se a sua principal preocupação é a densidade do código, talvez Malbolge não é uma boa escolha de idiomas, ....) É um problema na prática, uma vez que apenas a parte inferior 256 locais podem ser facilmente tratadas por qualquer programa que você pode introduzir - quaisquer endereços mais altos deve ser sintetizada. Isso por si só leva um monte de código.
A estratégia geral para escrever programas maiores Malbolge, e provando prático completude de Turing.
Se o código pode ser feito para caber, em seguida, a combinações de PO, gira, e ramos computados deve permitir uma programa de inicialização que lê uma seqüência de byte arbitrário na memória, o que ajudaria a contornar a restrição de 8 caracteres permitido, e permite o uso de mais do espaço de endereço. Então talvez seja possível escrever um BrainF *** ->Malbolge compilador , E assim por diante .... Isto mostra que Molbolge satisfaz a definição prático de Turing completude - pode calcular qualquer problema que se encaixa dentro da sua memória. No entanto, Malbolge nunca pode atender a definição formal de Turing completude, O que exige o acesso a uma quantidade ilimitada de memória.
Provando completude formal de Turing.
No entanto, uma muito ligeira além Malbolge torna verdadeiramente e formalmente Turing completa. Não há nada na especificação Malbolge informando que as operações de entrada e saída não pode se referir ao mesmo fluxo de dados, que, em seguida, pode ser considerada uma fita com um 257 Símbolo do alfabeto. (257 desde ENTRADA pode devolver os valores 0..255, mais o valor especial
- Código:
2222222222
- Código:
A = 2222222222
Tanto quanto eu posso determinar, Malbolge-T daria resultados idênticos ao clássico Malbolge com todos os programas existentes Malbolge *. (Como se a compatibilidade entre varients Malbolge foi um grande problema prático). No entanto, uma vez que Malbolge-T tem acesso a uma memória externa potencialmente ilimitada, é, pelo menos, tem a possibilidade de ser Turing completa. Na verdade, não é difícil mostrar, usando as técnicas de pesquisa de mesa utilizadas no BrainF *** ->Malbolge compilador , Que uma máquina de estado simples, com transições de estado completamente arbitrários podem ser implementadas. E se você pode implementar uma pequena máquina de estado arbitrário (5 estados vezes 5 símbolos é suficiente), e combiná-lo com a fita bi-direcional, então você pode implementar uma máquina de Turing Universal e, portanto, mostrar verdadeira completude de Turing.
* exceto para o programa de cópia de cima, que seria agora de backup para sempre após EOF na entrada, em vez de vomitar um número infinito de bytes com um valor de 168.
Poderia ser pior
Malbolge, embora, obviamente, difícil, poderia ser pior. Aqui estão algumas sugestões para torná-lo ainda mais difícil:
Refazer a tabela de permutação de instruções para remover todos os ciclos curtos.
Em particular, se cada ciclo possível para cada local contém pelo menos uma instrução não-NOP, então você pode nem mesmo construir um NOP que você pode confiar.
Remova a supervisão no interpretador de referência que permite a carga de usuário valores não-ascii diretamente.
Você poderia fazer o OP ainda menos útil, modificando-o para que o menor número de linhas e colunas como possível conter todos os três valores dígitos. Isso torna difícil para definir valores específicos que contêm todos os três Trits. Como alternativa, faça OP para que o maior número de linhas e colunas como possível conter todos os três valores Trit. Isto torna muito difícil de definir um endereço de memória para nada se você não sabe o valor anterior.
Modifique as instruções de como eles são buscados, e não quando elas são feitas. Então ramos demasiado auto iria modificar.
Feliz programação,
Lou Scheffer
A partir da página línguas estranhas de Ryan Kusnery:
O dia em que alguém escreve, em Malbolge , Um programa que simplesmente copia sua entrada para a sua saída, é o dia do meu cabelo se transforma espontaneamente verde. É o dia em que os elefantes são roxo e camelos voar, e uma vaca pode caber através de fundo de uma agulha.
Eu dedico todo o meu trabalho em Malbolge, em toda e qualquer forma, para o domínio público.
- Código:
POR FAVOR AGORA PARA DE FALAR DISSO
,==. |~~~
/ 66\ |
\c -_) |~~~
`) ( |
/ \ |~~~
/ \ \ |
(( /\ \_ |~~~
\\ \ `--`|
/ / / |~~~
Tópicos semelhantes
» Linguagem de programação BIRL(Treze memo)
» [TUTORIAL] Trocar jogo de linguagem facilmente com UI Dropdown v2.
» [TUTORIAL] Trocar jogo de linguagem facilmente com UI Dropdown via script.
» como criar um botao dentro do if() (em C# pq quero padronizar tudo na mesma linguagem)
» PROGRAMAÇÃO
» [TUTORIAL] Trocar jogo de linguagem facilmente com UI Dropdown v2.
» [TUTORIAL] Trocar jogo de linguagem facilmente com UI Dropdown via script.
» como criar um botao dentro do if() (em C# pq quero padronizar tudo na mesma linguagem)
» PROGRAMAÇÃO
Página 1 de 1
Permissões neste sub-fórum
Não podes responder a tópicos