Este site teve muitos problemas ao implementar vários idiomas na tag intérprete . No entanto, praticamente todos eles eram linguagens esotéricas que ninguém usa. Hora de criar um intérprete para uma linguagem prática que a maioria dos usuários provavelmente já conhece. Sim, é um shell script, caso você tenha problemas para ler o título (não que você tenha). (sim, eu intencionalmente fiz esse desafio, pois estou entediado com linguagens como GolfScript e Befunge ganhando tudo, então coloquei um desafio em que uma linguagem de programação mais prática tem maiores chances de ganhar)
No entanto, o script de shell é uma linguagem relativamente grande, então não vou pedir para você implementá-lo. Em vez disso, vou criar um pequeno subconjunto da funcionalidade de script de shell.
O subconjunto que eu decidi é o seguinte subconjunto:
- Executando programas (os programas conterão apenas letras, no entanto, mesmo que aspas simples sejam permitidas)
- Argumentos do programa
- Aspas simples (aceitando qualquer caractere ASCII imprimível, incluindo espaço em branco, excluindo as aspas simples)
- Sequências sem aspas (permitindo letras, números e traços ASCII)
- Tubos
- Instruções vazias
- Várias instruções separadas por nova linha
- À direita / à esquerda / vários espaços
Nesta tarefa, você deve ler a entrada do STDIN e executar todos os comandos solicitados. Você pode assumir com segurança o sistema operacional compatível com POSIX, para que não haja necessidade de portabilidade com o Windows ou algo assim. Você pode assumir com segurança que os programas que não são canalizados para outros programas não serão lidos no STDIN. Você pode assumir com segurança que os comandos existirão. Você pode assumir com segurança que nada mais será usado. Se alguma suposição segura for quebrada, você poderá fazer qualquer coisa. Você pode assumir com segurança no máximo 15 argumentos e linhas abaixo de 512 caracteres (se você precisar de alocação de memória explícita, ou algo assim - eu realmente darei pequenas chances de ganhar para C, mesmo que elas ainda sejam pequenas). Você não precisa limpar os descritores de arquivo.
Você tem permissão para executar programas a qualquer momento - mesmo após receber a linha completa ou após o término do STDIN. Escolha qualquer abordagem que você deseja.
Caixa de teste simples que permite testar seu shell (observe o espaço em branco após o terceiro comando):
echo hello world
printf '%08X\n' 1234567890
'echo' 'Hello, world!'
echo heeeeeeelllo | sed 's/\(.\)\1\+/\1/g'
yes|head -3
echo '\\'
echo 'foo bar baz' | sed 's/bar/BAR/' | sed 's/baz/zap/'
O programa acima deve gerar o seguinte resultado:
hello world
499602D2
Hello, world!
helo
y
y
y
\\
foo BAR zap
Você não tem permissão para executar o próprio shell, a menos que não tenha argumentos para o comando (essa exceção foi feita para Perl, que executa o comando no shell quando coloca apenas um argumento system
, mas sinta-se à vontade para abusar dessa exceção por outros idiomas também, se você puder fazer isso de uma maneira que salve caracteres), ou o comando executado será o próprio shell. Este é provavelmente o maior problema nesse desafio, pois muitas linguagens possuem system
funções que executam o shell. Em vez disso, use APIs de linguagem que chamam programas diretamente, como o subprocess
módulo em Python. Esta é uma boa idéia para a segurança de qualquer maneira e, bem, você não gostaria de criar um shell inseguro, gostaria? Isso provavelmente interrompe o PHP, mas existem outras linguagens para escolher de qualquer maneira.
Se você estiver indo para fazer o seu programa em shell script, você não estão autorizados a utilizar eval
, source
ou .
(como em uma função, não um personagem). Tornaria o desafio muito fácil na minha opinião.
Abuso inteligente de regras permitido. Há muitas coisas que eu não permiti explicitamente, mas tenho quase certeza de que você ainda pode fazer coisas que ainda não fiz. Às vezes, fico surpreso com a maneira como as pessoas interpretam minhas regras. Além disso, lembre-se de que você pode fazer qualquer coisa por qualquer coisa que eu não tenha mencionado. Por exemplo, se eu tentar usar variáveis, você pode limpar o disco rígido (mas não o faça).
O código mais curto vence, pois é um codegolf.
fonte
Respostas:
Bash (92 bytes)
Aproveitando a mesma brecha que essa resposta , aqui está uma solução muito mais curta:
Python (
247241239 bytes)fonte
*
), mas, além disso, fica ótimo :-). Estou surpreso que um novo membro tenha feito uma solução tão boa para um problema difícil.C (340 bytes)
Não tenho nenhuma experiência em golfe, mas você precisa começar em algum lugar, então aqui vai:
Adicionei quebras de linha para que você não precise rolar, mas não as incluí na minha contagem, pois elas não têm significado semântico. Aqueles após as diretivas do pré-processador são necessários e foram contados.
Versão ungolfed
Recursos
'ec'ho He'll''o 'world
funcionam como deveriam. Pode ser que o código tenha sido mais simples sem esse recurso, por isso, gostaria de esclarecer se isso é necessário.Problemas conhecidos
execvp
chamada falhar, por exemplo, devido a um nome de programa digitado incorretamente. Então nós temos dois processos brincando de concha simultaneamente.Caracteres especiais '|' e quebra de linha mantêm seu significado especial dentro de seqüências de caracteres entre aspas. Isso viola os requisitos, por isso estou investigando maneiras de corrigir isso.Corrigido, a um custo de cerca de 11 bytes.Outras notas
echo 'foo bar baz' | sed 's/bar/BAR/' | sed 's/baz/zap/'
travou. Aparentemente, o problema era o canal de gravação não fechado, então tive que adicionar esse comando close, que aumentou meu tamanho de código em 10 bytes. Talvez existam sistemas em que essa situação não ocorra, portanto meu código pode ser classificado com 10 bytes a menos. Eu não sei.?:
pode ter sido aninhado,
sem(…)
.fonte
int c, m, f[3];
foramain
, para evitar declarar tipos. Para variáveis globais, você não precisa declararint
. Mas, geralmente, solução interessante.yes|head -3
continuam indo para sempre e o shell sai após cada comando. Estou usando a versão 4.6.3 do gcc (Ubuntu / Linaro 4.6.3-1ubuntu5) sem nenhuma opção.#define B break;case
(obreak;
antesdefault
se torna)B-1:
) e 2 substituindocase'\n'
ecase'\''
) porcase 10
ecase 39
.bash (+ tela) 160
Produzirá algo como:
fonte
Fator (208 caracteres)
Como as regras não proíbem a transferência do trabalho para terceiros ( http://www.compileonline.com/execute_bash_online.php ), eis uma solução:
Você pode escrever o programa como uma linha única ainda mais curta no repl ( 201 caracteres):
fonte
Perl, 135 caracteres
Este shell faz algumas coisas estúpidas. Inicie um shell interativo
perl shell.pl
e tente:ls
imprime em uma coluna, porque a saída padrão não é um terminal. O shell redireciona a saída padrão para um pipe e lê a partir do pipe.perl -E 'say "hi"; sleep 1'
espera 1 segundo para dizer oi, porque o shell atrasa a saída.dd
lê 0 bytes, a menos que seja o primeiro comando desse shell. O shell redireciona a entrada padrão de um tubo vazio, para cada pipeline após o primeiro.perl -e '$0 = screamer; print "A" x 1000000' | dd of=/dev/null
termina com sucesso.perl -e '$0 = screamer; print "A" x 1000000' | cat | dd of=/dev/null
pendura a concha!pkill -f screamer
outro shell), o shell continuará.perl -e 'fork and exit; $0 = sleeper; sleep'
pendura a concha!'echo $((2+3))'
executa o comando em / bin / sh. Esse é o comportamento do exec e do sistema do Perl com um argumento, mas apenas se o argumento contiver caracteres especiais.Versão ungolfed
fonte