Algumas dicas aqui:
Constantes:
A página de constantes dos Esolangs possui uma lista extremamente útil das maneiras mais curtas de criar valores específicos. Encontro-me consultando esta página pelo menos duas vezes por programa.
O começo de tudo:
+++[[<+>>++<-]>]
Isso configura a fita no formato 3 * n ^ 2, que se parece com
3 6 12 24 48 96 192 128 0 0 '
Por que isso é tão importante?
Vamos descer a lista:
- 3 e 6 são chatos
- 12: Perto de 10 (nova linha) ou 13 (retorno de carro). Também pode ser usado no balcão para 0-9
- 24: Perto de 26, o número de letras no alfabeto
- 48: ASCII para
0
- 96: Perto de 97, ASCII para
a
- 196 e 128: 196-128 = 64, próximo a 65, o ASCII para
A
.
A partir desse algoritmo, estamos no início de praticamente todas as seqüências no intervalo ASCII, juntamente com um contador para cada uma e uma nova linha de fácil alcance.
Um exemplo prático:
Imprimir todas as letras maiúsculas e minúsculas e dígitos.
Com algoritmo:
+++[[<+>>++<-]>]<<[-<->]<<<<++[->>+.>+.<<<]<--[>>.+<<-]
Sem:
+++++++++++++[->+++++++>++>+++++>++++>+<<<<<]>+++++>[-<+.>>.+<]>>---->---[-<.+>]
Passamos a maior parte dos bytes apenas inicializando a fita no segundo exemplo. Parte disso é compensada pelos movimentos extras no primeiro exemplo, mas esse método tem claramente a vantagem.
Alguns outros algoritmos interessantes na mesma linha:
3 * 2 ^ n + 1:
+++[[<+>>++<-]+>]
Tape: 4 7 13 25 49 65 197 129 1 0'
Isso compensa os valores em 1, o que realiza algumas coisas. Torna os 12 um retorno de carro, os 64 o início real do alfabeto maiúsculo e os 24 mais próximos de 26.
2 ^ n:
+[[<+>>++<-]>]
Tape: 1 2 4 8 16 32 64 128
Como 64 é bom para letras maiúsculas, 32 é o ASCII para espaço e 128 pode ser usado como contador de 26 (130/5 = 26). Isso pode salvar bytes em certas situações em que não são necessários dígitos e letras minúsculas.
Escolha a implementação que se adequa à pergunta:
- As células negativas são quase sempre úteis e não há motivos para evitá-las (a menos que isso não mude sua contagem de bytes)
- Quase exatamente a mesma coisa com células de quebra automática, ainda mais porque muitas constantes usam quebra automática.
- Os tamanhos de células arbitrárias são úteis para sequências matemáticas infinitas, como o cálculo infinito da sequência de Fibonacci (
+[[-<+>>+>+<<]>]
) ou o processamento de números maiores / negativos. A desvantagem é que alguns métodos comuns, como [-]
e [->+<]
não podem ser invocados, apenas no caso de o número ser negativo.
- EOF como 0, -1 ou nenhuma alteração. 0 é geralmente preferível, pois você pode repetir uma entrada inteira sem verificações extras. -1 é útil ao fazer um loop sobre estruturas de matriz. Ainda não encontrei um uso sem alterações :(.
Acompanhe o que está acontecendo:
Em todos os momentos, você deve ter comentários sobre onde o ponteiro deve estar em relação aos dados ao seu redor e certifique-se de conhecer o intervalo de valores possíveis de cada célula. Isso é especialmente importante quando você divide o ponteiro antes de um loop, porque você deseja unir as duas possibilidades depois.
A qualquer momento, meu código está repleto de comentários em todas as outras linhas que se parecem com isso:
*0 *dat a_1 ? 0' !0 0*
or
*0 *dat 0' ap1 0 !0 0*
Alguns conselhos extras são para atribuir significados especiais aos símbolos. No exemplo acima, '
é onde está o ponteiro, *
significa repetição nessa direção, ?
significa uma célula com valor desconhecido, !0
significa uma célula diferente de zero, _
é um substituto -
e p
é um substituto para +
. or
implica que a fita possa se parecer com qualquer uma das representações e precisa ser manuseada como tal.
Seu esquema de símbolos não precisa necessariamente ser o mesmo que o meu (que tem algumas falhas), apenas precisa ser consistente. Isso também é extremamente útil ao depurar, porque você pode executá-lo até esse ponto e comparar a fita real com a que você deve ter, o que pode indicar possíveis falhas no seu código.