diff --git a/brainfuck2/bf2.kt b/brainfuck2/bf2.kt index 50d9badd..33317414 100644 --- a/brainfuck2/bf2.kt +++ b/brainfuck2/bf2.kt @@ -1,38 +1,45 @@ +@file:JvmName("BfKotlin") + +import java.io.File import java.io.IOException -import java.nio.file.Files -import java.nio.file.Paths +import java.io.PrintStream -sealed class Op() { - class Inc(val v: Int): Op() - class Move(val v: Int): Op() - class Loop(val loop: Array): Op() - object Print: Op() +sealed class Op { + object Inc : Op() + object Dec : Op() + object MoveUp : Op() + object MoveDown : Op() + class Loop(val loop: Array) : Op() + class Print(val out: PrintStream) : Op() } -class Tape { - private var tape: IntArray = IntArray(1) +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) - System.arraycopy(this.tape, 0, tape, 0, this.tape.size) + this.tape.copyInto(tape) this.tape = tape } } } - -class Program(code: String) { + +class KtProgram(code: String, out: PrintStream) { private val ops: Array + private val printer = Op.Print(out) init { val it = code.iterator() @@ -43,11 +50,11 @@ class Program(code: String) { val res = arrayListOf() while (it.hasNext()) { when (it.next()) { - '+' -> res.add(Op.Inc(1)) - '-' -> res.add(Op.Inc(-1)) - '>' -> res.add(Op.Move(1)) - '<' -> res.add(Op.Move(-1)) - '.' -> res.add(Op.Print) + '+' -> 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() } @@ -55,42 +62,34 @@ class Program(code: String) { return res.toTypedArray() } - fun run() { - _run(ops, Tape()) + fun run(): KtTape { + val tape = KtTape() + _run(ops, tape) + return tape } - - private fun _run(program: Array, tape: Tape) { + + private fun _run(program: Array, tape: KtTape) { for (op in program) { when (op) { - is Op.Inc -> tape.inc(op.v) - is Op.Move -> tape.move(op.v) - is Op.Loop -> while (tape.get() > 0) { - _run(op.loop, tape) - } - is Op.Print -> print(tape.get().toChar()) + 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 warming() { - val WARM_PROGRAM = ">++[<+++++++++++++>-]<[[>+>+<<-]>[<+>-]++++++++[>++++++++<-]>[-]<<>++++++++++[>++++++++++[>++++++++++[>++++++++++[>++++++++++[>++++++++++[>++++++++++[-]<-]<-]<-]<-]<-]<-]<-]++++++++++" - - System.err.println("warming") - val start_time = System.currentTimeMillis() - Program(WARM_PROGRAM).run() - System.err.println("time: ${(System.currentTimeMillis() - start_time) / 1e3}s") +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) { - val code = String(Files.readAllBytes(Paths.get(args[0]))) - - warming() - - System.err.println("run") - val start_time = System.currentTimeMillis() - val program = Program(code) - program.run() - System.err.println("time: ${(System.currentTimeMillis() - start_time) / 1e3}s") + val code = File(args[0]).readText(Charsets.US_ASCII) + runWithTiming(KtProgram(code, System.out)::run) }