Un gros coup de déterrage ici, pour vous montrer la puissance de Kotlin !
Vous vous souvenez peut-être de ma version optimisée de l’interpéteur en Java. Voici une version plus rapide en Kotlin (10 secondes sur la fractale contre 12 avec Java sur mon PC actuel) et qui tient en moins de 100 lignes, imports et mise en forme correcte comprises :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91 | package fr.spacefox.brainfuck
import java.io.File
import java.io.IOException
import java.io.InputStreamReader
import kotlin.system.measureTimeMillis
class CompiledBrainFuck(strProgram: String) {
private val instructions = strProgram
.filter { it in listOf('+', '-', '>', '<', '[', ']', '.', ',') }
.replace(">[-]<[->+<]", "m") // Move
.replace("[->+<]", "a") // Addition
.replace("[-]", "0") // Cell reset
.toCharArray()
private val ram = IntArray(30000)
private val inputReader = InputStreamReader(System.`in`)
fun run() {
val (compiled, parameters) = compile(instructions)
var ramPtr = 0
var programPtr = 0
do {
when (compiled[programPtr]) {
'>', '<' -> ramPtr += parameters[programPtr]
'+', '-' -> ram[ramPtr] = (ram[ramPtr] + parameters[programPtr]) % 0xFFFF
'0' -> ram[ramPtr] = 0
'a' -> { ram[ramPtr + 1] += ram[ramPtr] ; ram[ramPtr] = 0 }
'm' -> { ram[ramPtr + 1] = ram[ramPtr] ; ram[ramPtr] = 0 }
'[' -> if (ram[ramPtr] == 0) programPtr = parameters[programPtr]
']' -> if (ram[ramPtr] != 0) programPtr = parameters[programPtr]
'.' -> print(ram[ramPtr].toChar())
',' -> ram[ramPtr] = try { inputReader.read() } catch (e: IOException) { 0 }
}
programPtr++
} while (programPtr < compiled.size)
}
private fun compile(unCompiled: CharArray): Pair<CharArray, IntArray> {
val compiled = mutableListOf<Char>()
val parameters = mutableListOf<Int>()
var lastInstruction = '\u0000'
for (instruction in unCompiled) {
when (instruction) {
'>', '+' -> if (instruction == lastInstruction) {
parameters[parameters.lastIndex]++
} else {
compiled.add(instruction)
parameters.add(1)
}
'<', '-' -> if (instruction == lastInstruction) {
parameters[parameters.lastIndex]--
} else {
compiled.add(instruction)
parameters.add(-1)
}
else -> {
compiled.add(instruction)
parameters.add(0)
}
}
lastInstruction = instruction
}
for (open in 0..compiled.lastIndex) {
if (compiled[open] == '[') {
var loops = 1
var close = open
while (loops > 0) {
close++
when {
compiled[close] == '[' -> loops++
compiled[close] == ']' -> loops--
}
}
parameters[open] = close // Match [ → ]
parameters[close] = open // Match ] → [
}
}
return Pair(compiled.toCharArray(), parameters.toIntArray())
}
}
fun main(args: Array<String>) {
val time = measureTimeMillis { CompiledBrainFuck(File(args[0]).readText()).run() }
println("Completed in $time ms")
}
|