Eu projetei uma linguagem na qual a aritmética de ponteiros é a principal ferramenta de programação.
Aqui estão alguns exemplos.
(print 0 to 8)
=9[>1=9-*-1.>-1-1]
(print 1 to 10 with spaces in between, character literal extension used)
=1[.>1=10-*-1[>1=' '!>-2+1;-2];1]='\n'!
(compute the factorial of 10)
=10>1=*-1-1[>-1**1>1-1]>-1.
(print "hi")
=104!=105!
(print "hi" with extension for arrays)
={104,105,0}[!>1]
(print "Hello, world!" with extension for C-style string literals)
="Hello, world!"[!>1]
Especificação de idioma
A definição da linguagem é muito simples. Você entenderá com muita facilidade se tiver experiência com C, mas não assumirei isso.
Todo programa no PointerLang possui o ponteiro , em resumo P
,. Você pode pensar nisso como uma variável global única oculta, que você pode controlar usando comandos . P
inicialmente aponta para o início da matriz . Cada elemento da matriz tem o tipo int
que é um número inteiro assinado de 32 bits.
Para programadores C
int32_t *P = malloc(1000);
No PointerLang, existem comandos e argumentos . Um argumento é aquele int
que deve vir após um comando. Todos os comandos são executados da esquerda para a direita, a menos que seja especificado o contrário. A seguir está a lista de comandos. A
significa argumento. Um comando sem A
meios não leva a um argumento. Um comando com A
deve receber um argumento. Dentro dos parênteses está a expressão C equivalente.
=A
: atribua A em P (*P = A
)+A
: adicione A em P (*P += A
)-A
: subtraia A em P (*P -= A
)*A
: multiplicar por A em P (*P *= A
)/A
: divida por A em P (*P /= A
)>A
: moverP
porA
(P += A
).
: imprime o número inteiro em P (printf("%d", *P)
)!
: imprime o número inteiro em P como ASCII (printf("%c", (char)*P)
)[
: se o valor em P for 0, vá para o comando após o próximo]
(while (*P) {
)]
: vá para o anterior[
que é o par correspondente (}
);A
: seA
for positivo, vá para o comando após o próximoA
th]
; seA
for negativo, vá para oA
th[
vindo antes; se A for 0, não faça nada.
Um literal inteiro é um argumento.
Os dois a seguir são argumentos especiais que aceitam um argumento.
-A
: avaliado como um argumento com o mesmo valor absolutoA
e o sinal oposto deA
; menos unário*A
: MovimentoP
porA
, avaliar o valor emP
, movimentoP
por-A
(P[A]
)
Todos os comentários no PointerLang estão entre parênteses (comment)
.
Programa de exemplo
Este programa que conta de 1 a 10 é um bom exemplo para concluir sua compreensão.
(print 1 to 10 with spaces in between)
=1[.>1=10-*-1[>1=32!>-2+1;-2];1]=10!
Tenha cuidado ao interpretar -*-1
. -
é o comando e *-1
é o argumento. Um literal inteiro indica efetivamente o final de um par de argumentos de comando.
Pode ser traduzido para C com correspondência 1 para 1, conforme
int main(void) {
int32_t *P = malloc(1000);
*P = 1; // =1
l:
while (*P) { // [
printf("%d", *P); // .
P += 1; // > 1
*P = 10; // =10
*P -= P[-1]; // -*-1
while (*P) { // [
P += 1; // >1
*P = 32; // =32
printf("%c", (char)*P); // !
P += -2; // >-2
*P += 1; // +1
goto l; // ;-2
} // ]
break; // ;1
} // ]
*P = 10; // =10
printf("%c", (char)*P); // !
return 0;
}
Extensões podem ser aplicadas a essa linguagem, como literais de caracteres, matrizes, literais de cadeias etc., mas você não precisa implementá-las, para simplificar.
O desafio
Você precisa implementar os principais recursos detalhados na seção Especificação de Idioma e nas NOTAS abaixo. Experimente a sua linguagem de programação favorita, escrevendo o programa mais curto possível.
NOTA1: O tamanho da matriz é indefinido. Mas deve ser grande o suficiente para resolver a maioria dos problemas.
NOTA2: Estouro de número inteiro é indefinido.
NOTA3: A especificação define apenas o resultado ou o efeito de determinadas construções de linguagem. Por exemplo, você não precisa seguir exatamente as etapas na definição do argumento *
.
NOTA4: Quaisquer caracteres que não sejam comandos, argumentos ou comentários, espaços em branco são ignorados. =104!=105!
é o mesmo que = 1 0 4! = 1 05 !
por exemplo.
NOTA5: Comentários não são aninhados. ((comment))
é um erro de sintaxe.
NOTA6: Fiz uma alteração de última hora para corrigir um buraco no meu idioma. O ~
comando agora não é utilizado e ;
sempre recebe um argumento.
NOTA7: Todo literal inteiro é decimal.
fonte
=9[>1=9-*-1.>-1-1]
imprime de 0 a 9? Depois de pontuar 8 porque P [0] = 1, subtrai 1 imediatamente antes do final do loop, o que faz com que P [0] = 0 e, quando ele inicia o loop novamente, deve sair porque P [0] = 0, para que exemplo deve imprimir apenas de 0 a 8. Ou estou realmente confuso?Respostas:
C 413
Graças a @ceilingcat por algumas peças muito boas de golfe - agora ainda mais curtas
Experimente online!
e a versão um pouco menos complicada da minha resposta original:
fonte
switch(...){case'(':...case'.':...
porj=='('?...:j=='.'?...
chamadas de função e fatoradas para caber no operador ternário.