Classifica - JIT compilato (inferiore è meglio)
- es1024 - 81.2 punti (incluso un compilatore funzionante!)
- Kieth Randall - 116 punti
- Ell - 121 punti
Classifica - Interpretato (Inferiore è meglio)
- Martin Büttner - 706654 punti (da qualche parte circa 2 ore).
- criptych - 30379 punti (97 secondi)
La tua missione, se scegli di accettarla, è quella di scrivere il più piccolo interprete / VM del codice byte possibile. Il VM / interprete utilizza una piccola architettura CISC (le operazioni possono variare di dimensioni), con la lingua specificata di seguito. Al termine, è necessario stampare il valore dei 3 registri della CPU per provare che viene stampato l'output corretto (3.126.900.366).
Compiler
Se desideri effettuare i tuoi test, di seguito viene pubblicato un compilatore. Sentiti libero di pubblicare i tuoi test con la tua risposta.
Specifiche "VM"
La macchina virtuale ha 3 registri integrali senza segno a 32 bit: R0, R1, R2. Sono rappresentati in esadecimale come 0x00, 0x01 e 0x02.
Devono essere supportate le seguenti operazioni:
Il formato è [nome] [... operandi ...], [codice op esadecimale] [... operandi ripetuti ...]
- LOAD [registro] [valore 4 byte], 0x00 [registro] [valore 4 byte]
- 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 [riga codice, 4 byte], 0x08 [numero riga codice 4 byte]
- CMP [registro, 1 byte] [registro, 1 byte], 0x09 [registro] [registro]
- BRANCHLT [riga codice, 4 byte], 0x0a [numero riga codice 4 byte]
Alcune note:
- Le suddette operazioni matematiche sommano i valori di 2 registri, posizionando l'output nel primo registro.
- CMP, l'operatore di confronto, dovrebbe confrontare i valori di 2 registri e memorizzare l'output in alcuni flag interni (questo può essere specifico dell'implementazione) per un uso futuro nelle istruzioni di diramazione.
- Se BRANCH viene chiamato prima di CMP, a meno che non venga chiamato BRANCHEQ, la "VM" non dovrebbe diramarsi.
- PUSH / POP non sorprende che spinga o schiocchi numeri dalla pila.
- Gli operatori Jump e Branch passano a un'operazione specifica (riga di codice), non a un indirizzo binario.
- Le operazioni di filiale non fanno il confronto. Piuttosto, prendono l'esecuzione dell'ultimo confronto.
- Gli operatori Branch e Jump utilizzano un sistema di indicizzazione del numero di riga in base zero. (Ad esempio, JMP 0 passa alla prima riga)
- Tutte le operazioni devono essere eseguite su numeri senza segno che traboccano a zero e non generano un'eccezione su un overflow intero.
- La divisione per zero non è consentita e, in quanto tale, il comportamento del programma non è definito. Puoi (per esempio) ...
- Arresto anomalo del programma.
- Termina l'esecuzione della VM e restituisce lo stato corrente.
- Mostra un messaggio "ERR: divisione per 0".
- La conclusione del programma è definita come quando il puntatore dell'istruzione raggiunge la fine del programma (si può presumere un programma non vuoto).
Output L'output deve essere esattamente questo (nuove righe incluse)
R0 3126900366
R1 0
R2 10000
Punti I
punti vengono calcolati in base alla seguente formula:Number Of Characters * (Seconds Needed To Run / 2)
Per evitare differenze hardware che causano tempi diversi, ogni test verrà eseguito sul mio computer (i5-4210u, 8 GB di RAM) su server Ubuntu o Windows 8, quindi cerca di non usare un runtime insano-esotico che si compila solo su un Dual G5 Mac Pro con esattamente 762,66 MB di RAM libera.
Se stai utilizzando un runtime / una lingua specializzati, pubblica un link ad esso.
- Per le parti interessate, ho pubblicato il codice di prova (scritto in C #) qui: http://pastebin.com/WYCG5Uqu
Programma di test
L'idea è nata da qui , quindi useremo una versione leggermente modificata del loro programma.
L'output corretto per il programma è: 3.126.900.366
In C:
int s, i, j;
for (s = 0, i = 0; i < 10000; i++) {
for (j = 0; j < 10000; j++)
s += (i * j) / 3;
}
Nel codice: [R0 è rappresentativo di s, R1 di j, R2 di 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
In binario / esadecimale:
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
Punti bonus (gli effetti vengono applicati in modo moltiplicativo) Ad esempio se ti qualifichi per tutti e tre, sarebbe ((caratteri * 0,50) * 0,75) * 0,90
- Riduzione del 50% se l'interprete è in realtà un compilatore JIT
- Riduzione del 25% se applica qualsiasi tipo di srotolamento / ottimizzazione significativa del loop.
- Riduzione del 10% se si estende la VM con
- BRANCHEQ [riga di codice, 4 byte] (Branch se uguale - opcode 0x0b)
- BRANCHGT [riga di codice, 4 byte] (Branch se maggiore di - opcode 0x0c)
- BRANCHNE [riga di codice, 4 byte] (Branch se non uguale - opcode 0x0d)
- RLOAD [register 1] [register 2] (sposta il valore del registro 2 sul registro 1 - opcode 0x01).
Non consentito
- È vietato precompilare il caso di test nel programma. Devi accettare il bytecode da STDIN o da un file (non importa quale).
- Restituisce l'output senza eseguire il programma.
- In qualsiasi altro modo ti venga in mente di imbrogliare il requisito della VM.
CMP
assegno di minore o l'uguaglianza? E cosa succede al suo risultato?
MUL
e DIV
sono anche sottostimati. Dovrebbero essere firmati o non firmati? Cosa succede all'overflow di moltiplicazione?