Classificação - JIT compilado (quanto mais baixo, melhor)
- es1024 - 81,2 pontos (incluindo um compilador funcional!)
- Kieth Randall - 116 pontos
- Ell - 121 pontos
Tabela de classificação - Interpretada (quanto mais baixo, melhor)
- Martin Büttner - 706654 pontos (algo em torno de 2 horas).
- criptych - 30379 pontos (97 segundos)
Sua missão, se você aceitar, é escrever o menor intérprete / VM de bytecode possível. O VM / intérprete usa uma pequena arquitetura CISC (as operações podem variar em tamanho), com o idioma especificado abaixo. Após a conclusão, você deve imprimir o valor dos 3 registros da CPU para provar que a saída correta é impressa (3.126.900.366).
Compilador
Se você quiser fazer seus próprios testes, um compilador será publicado abaixo. Sinta-se livre para publicar seus testes com sua resposta.
Especificações "VM"
A VM possui 3 registradores integrais não assinados de 32 bits: R0, R1, R2. Eles são representados em hexadecimal como 0x00, 0x01 e 0x02.
As seguintes operações devem ser suportadas:
O formato é [nome] [... operandos ...], [código op hexadecimal] [... operandos repetidos ...]
- LOAD [registro] [valor de 4 bytes], 0x00 [registro] [valor de 4 bytes]
- PUSH [registro], 0x02 [registro]
- POP [registro], 0x03 [registro]
- ADD [registro, 1 byte] [registro, 1 byte], 0x04 [registro] [registro]
- SUB [registro, 1 byte] [registro, 1 byte], 0x05 [registro] [registro]
- MUL [registro, 1 byte] [registro, 1 byte], 0x06 [registro] [registro]
- DIV [registro, 1 byte] [registro, 1 byte], 0x07 [registro] [registro]
- JMP [linha de código, 4 bytes], 0x08 [número da linha de código de 4 bytes]
- CMP [registro, 1 byte] [registro, 1 byte], 0x09 [registro] [registro]
- BRANCHLT [linha de código, 4 bytes], 0x0a [número da linha de código de 4 bytes]
Algumas notas:
- As operações matemáticas acima adicionam os valores de 2 registros, colocando a saída no primeiro registro.
- O CMP, o operador de comparação, deve comparar os valores de 2 registros e armazenar a saída em algum sinalizador interno (isso pode ser específico da implementação) para uso futuro em instruções de ramificação.
- Se BRANCH for chamado antes do CMP, a menos que BRANCHEQ seja chamado, a "VM" não deverá ramificar.
- PUSH / POP, sem surpresa, empurra ou abre números da pilha.
- Os operadores de salto e ramificação saltam para uma operação específica (linha de código), não para um endereço binário.
- As operações da filial não fazem a comparação. Em vez disso, eles usam a saída da última comparação para executar.
- Os operadores de desvio e salto usam um sistema de indexação de número de linha baseado em zero. (Por exemplo, o JMP 0 salta para a primeira linha)
- Todas as operações devem ser executadas em números não assinados que transbordam para zero e não lançam uma exceção em um estouro inteiro.
- A divisão por zero não é permitida e, como tal, o comportamento do programa não está definido. Você pode (por exemplo) ...
- Falha no programa.
- Finalize a execução da VM e retorne seu estado atual.
- Mostrar uma mensagem "ERR: Divisão por 0".
- A finalização do programa é definida como quando o ponteiro da instrução chega ao final do programa (um programa não vazio pode ser assumido).
Saída A saída deve ser exatamente isso (novas linhas incluídas)
R0 3126900366
R1 0
R2 10000
Pontos Os
pontos são calculados com base na seguinte fórmula:Number Of Characters * (Seconds Needed To Run / 2)
Para evitar diferenças de hardware que causam tempos diferentes, cada teste será executado no meu computador (i5-4210u, 8 GB de RAM) no servidor ubuntu ou no Windows 8, portanto, tente não usar algum tempo de execução exótico insano que compila apenas em um Dual G5 Mac Pro com exatamente 762,66 mb de RAM livre.
Se você estiver usando um tempo de execução / idioma especializado, poste um link para ele.
- Para as partes interessadas, publiquei o código de teste (escrito em C #) aqui: http://pastebin.com/WYCG5Uqu
Programa de teste
A ideia veio daqui , então usaremos uma versão um pouco modificada do programa deles.
A saída correta para o programa é: 3.126.900.366
Em C:
int s, i, j;
for (s = 0, i = 0; i < 10000; i++) {
for (j = 0; j < 10000; j++)
s += (i * j) / 3;
}
No código: [R0 é representativo de s, R1 de j, R2 de i]
LOAD R0 0
LOAD R2 0 <--outer loop value
LOAD R1 0 <--inner loop value
--Begin inner loop--
PUSH R1 <--push inner loop value to the stack
MUL R1 R2 <--(i*j)
PUSH R2
LOAD R2 3
DIV R1 R2 <-- / 3
POP R2
ADD R0 R1 <-- s+=
POP R1
PUSH R2
LOAD R2 1
ADD R1 R2 <--j++
POP R2
PUSH R2
LOAD R2 10000
CMP R1 R2 <-- j < 10000
POP R2
BRANCHLT 3 <--Go back to beginning inner loop
--Drop To outer loop--
LOAD R1 1
ADD R2 R1 <--i++
LOAD R1 10000
CMP R2 R1 <-- i < 10000
LOAD R1 0 <--Reset inner loop
BRANCHLT 2
Em binário / hexadecimal:
0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x02 0x00 0x00 0x00 0x00
0x00 0x01 0x00 0x00 0x00 0x00
0x02 0x01
0x06 0x01 0x02
0x02 0x02
0x00 0x02 0x00 0x00 0x00 0x03
0x07 0x01 0x02
0x03 0x02
0x04 0x00 0x01
0x03 0x01
0x02 0x02
0x00 0x02 0x00 0x00 0x00 0x01
0x04 0x01 0x02
0x03 0x02
0x02 0x02
0x00 0x02 0x00 0x00 0x27 0x10
0x09 0x01 0x02
0x03 0x02
0x0a 0x00 0x00 0x00 0x03
0x00 0x01 0x00 0x00 0x00 0x01
0x04 0x02 0x01
0x00 0x01 0x00 0x00 0x27 0x10
0x09 0x02 0x01
0x00 0x01 0x00 0x00 0x00 0x00
0x0a 0x00 0x00 0x00 0x02
Pontos de bônus (os efeitos são aplicados de forma multiplicativa) Por exemplo, se você se qualificar para os três, seria ((caracteres * 0,50) * 0,75) * 0,90
- Redução de 50% se o intérprete for realmente um compilador JIT
- Redução de 25% se aplicar qualquer tipo de desenrolar / otimização significativa do loop.
- 10% de redução se você estender a VM com
- BRANCHEQ [linha de código, 4 bytes] (Ramificação se igual - opcode 0x0b)
- BRANCHGT [linha de código, 4 bytes] (Ramificar se for maior que - opcode 0x0c)
- FILIAL [linha de código, 4 bytes] (Ramificação se não for igual - opcode 0x0d)
- RLOAD [registro 1] [registro 2] (mova o valor do registro 2 para o registro 1 - código de operação 0x01).
Não permitido
- É pré-compilado o caso de teste no programa. Você deve aceitar o bytecode de STDIN ou de um arquivo (não importa qual).
- Retornando a saída sem executar o programa.
- Qualquer outra maneira de enganar o requisito da VM.
CMP
seleção para menor ou igualdade? E o que acontece com o resultado?
MUL
e DIV
também são subespecificados. Eles devem ser assinados ou não assinados? O que acontece no estouro de multiplicação?