Tabla de clasificación - JIT compilado (más bajo es mejor)
- es1024 - 81.2 puntos (¡incluido un compilador que funciona!)
- Kieth Randall - 116 puntos
- Ell - 121 puntos
Tabla de clasificación - Interpretada (más bajo es mejor)
- Martin Büttner - 706654 puntos (alrededor de 2 horas).
- críptico - 30379 puntos (97 segundos)
Su misión, si elige aceptarla, es escribir el intérprete / VM de bytecode más pequeño posible. El VM / intérprete utiliza una pequeña arquitectura CISC (las operaciones pueden variar en tamaño), con el lenguaje que se especifica a continuación. Al finalizar, debe imprimir el valor de los 3 registros de la CPU para demostrar que se imprime la salida correcta (3,126,900,366).
Compilador
Si desea hacer sus propias pruebas, a continuación se publica un compilador. Siéntase libre de publicar sus exámenes con su respuesta.
Especificaciones "VM"
La VM tiene 3 registros integrales sin signo de 32 bits: R0, R1, R2. Se representan en hexadecimal como 0x00, 0x01 y 0x02.
Se deben admitir las siguientes operaciones:
El formato es [nombre] [... operandos ...], [código de operación 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 [línea de código, 4 bytes], 0x08 [número de línea de código de 4 bytes]
- CMP [registro, 1 byte] [registro, 1 byte], 0x09 [registro] [registro]
- BRANCHLT [línea de código, 4 bytes], 0x0a [número de línea de código de 4 bytes]
Algunas notas:
- Las operaciones matemáticas anteriores suman los valores de 2 registros, colocando la salida en el primer registro.
- CMP, el operador de comparación, debe comparar los valores de 2 registros y almacenar la salida en algún indicador interno (esto puede ser específico de la implementación) para uso futuro en instrucciones de bifurcación.
- Si se llama BRANCH antes que CMP, a menos que se llame BRANCHEQ, la "VM" no debe bifurcarse.
- PUSH / POP, como era de esperar, empuja o saca números de la pila.
- Los operadores Jump y Branch saltan a una operación específica (línea de código), no a una dirección binaria.
- Las operaciones de sucursal no hacen la comparación. Por el contrario, toman la salida de la última comparación para ejecutar.
- Los operadores Branch y Jump utilizan un sistema de indexación de número de línea basado en cero. (Por ejemplo, JMP 0 salta a la primera línea)
- Todas las operaciones deben realizarse en números sin signo que se desbordan a cero y no arrojan una excepción en un desbordamiento de enteros.
- La división por cero no está permitida y, como tal, el comportamiento del programa no está definido. Puedes (por ejemplo) ...
- Bloquea el programa.
- Finalice la ejecución de la VM y devuelva su estado actual.
- Mostrar un mensaje "ERR: División por 0".
- La terminación del programa se define como cuando el puntero de instrucción llega al final del programa (se puede suponer un programa no vacío).
Salida La salida debe ser exactamente esto (nuevas líneas incluidas)
R0 3126900366
R1 0
R2 10000
Puntos Los
puntos se calculan según la siguiente fórmula:Number Of Characters * (Seconds Needed To Run / 2)
Para evitar diferencias de hardware que causen tiempos diferentes, cada prueba se ejecutará en mi computadora (i5-4210u, 8GB ram) en el servidor ubuntu o Windows 8, así que trate de no usar un tiempo de ejecución increíblemente exótico que solo se compila en un Dual G5 Mac Pro con exactamente 762.66 mb de RAM libre.
Si está utilizando un lenguaje / tiempo de ejecución especializado, publique un enlace a él.
- Para las partes interesadas, he publicado el código de prueba (escrito en C #) aquí: http://pastebin.com/WYCG5Uqu
Programa de prueba
La idea surgió de aquí , por lo que utilizaremos una versión algo modificada de su programa.
La salida correcta para el programa es: 3,126,900,366
Cía:
int s, i, j;
for (s = 0, i = 0; i < 10000; i++) {
for (j = 0; j < 10000; j++)
s += (i * j) / 3;
}
En el código: [R0 es 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
En binario / 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
Puntos de bonificación (los efectos se aplican multiplicativamente) Por ejemplo, si califica para los tres, sería ((caracteres * 0.50) * 0.75) * 0.90
- Disminución del 50% si el intérprete es realmente un compilador JIT
- Disminución del 25% si aplica algún tipo de desenrollamiento de bucle / optimización significativa.
- 10% de disminución si extiende la VM con
- BRANCHEQ [línea de código, 4 bytes] (Rama si es igual - código de operación 0x0b)
- BRANCHGT [línea de código, 4 bytes] (Rama si es mayor que - opcode 0x0c)
- BRANCHNE [línea de código, 4 bytes] (Rama si no es igual - código de operación 0x0d)
- RLOAD [registro 1] [registro 2] (mueve el valor del registro 2 al registro 1 - código de operación 0x01).
No permitido
- Precompilar el caso de prueba en el programa está prohibido. Debe aceptar el código de bytes de STDIN o de un archivo (no importa cuál).
- Devolver la salida sin ejecutar el programa.
- Cualquier otra forma que se te ocurra para engañar al requisito de VM.
CMP
Verifica por menos que o igualdad? ¿Y qué pasa con su resultado?
MUL
y DIV
también están subespecificados. ¿Deben estar firmados o sin firmar? ¿Qué sucede en el desbordamiento de multiplicación?