-
Notifications
You must be signed in to change notification settings - Fork 259
Expand file tree
/
Copy pathbf2.kt
More file actions
95 lines (81 loc) · 2.35 KB
/
bf2.kt
File metadata and controls
95 lines (81 loc) · 2.35 KB
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
92
93
94
95
@file:JvmName("BfKotlin")
import java.io.File
import java.io.IOException
import java.io.PrintStream
sealed class Op {
object Inc : Op()
object Dec : Op()
object MoveUp : Op()
object MoveDown : Op()
class Loop(val loop: Array<Op>) : Op()
class Print(val out: PrintStream) : Op()
}
class KtTape {
private var tape: IntArray = IntArray(16)
private var pos: Int = 0
val state: IntArray get() = tape.copyOf()
fun get(): Int {
return tape[pos]
}
fun inc(x: Int) {
tape[pos] += x
}
fun move(x: Int) {
pos += x
while (pos >= tape.size) {
val tape = IntArray(this.tape.size * 2)
this.tape.copyInto(tape)
this.tape = tape
}
}
}
class KtProgram(code: String, out: PrintStream) {
private val ops: Array<Op>
private val printer = Op.Print(out)
init {
val it = code.iterator()
ops = parse(it)
}
private fun parse(it: CharIterator): Array<Op> {
val res = arrayListOf<Op>()
while (it.hasNext()) {
when (it.next()) {
'+' -> res.add(Op.Inc)
'-' -> res.add(Op.Dec)
'>' -> res.add(Op.MoveUp)
'<' -> res.add(Op.MoveDown)
'.' -> res.add(printer)
'[' -> res.add(Op.Loop(parse(it)))
']' -> return res.toTypedArray()
}
}
return res.toTypedArray()
}
fun run(): KtTape {
val tape = KtTape()
_run(ops, tape)
return tape
}
private fun _run(program: Array<Op>, tape: KtTape) {
for (op in program) {
when (op) {
is Op.Inc -> tape.inc(1)
is Op.Dec -> tape.inc(-1)
is Op.MoveUp -> tape.move(1)
is Op.MoveDown -> tape.move(-1)
is Op.Loop -> while (tape.get() > 0) _run(op.loop, tape)
is Op.Print -> op.out.print(tape.get().toChar())
}
}
}
}
fun runWithTiming(runnable: () -> Any?) {
val startTime = System.currentTimeMillis()
runnable()
System.err.printf("time: %.3fs\n", (System.currentTimeMillis() - startTime) / 1e3)
}
@Throws(IOException::class)
fun main(args: Array<String>) {
val code = File(args[0]).readText(Charsets.US_ASCII)
runWithTiming(KtProgram(code, System.out)::run)
}