Skip to content

Instantly share code, notes, and snippets.

@Pyeroh
Created March 3, 2017 03:17
Show Gist options
  • Save Pyeroh/7c170cbd52eb6a43201a444d2b577b04 to your computer and use it in GitHub Desktop.
Save Pyeroh/7c170cbd52eb6a43201a444d2b577b04 to your computer and use it in GitHub Desktop.
Brainfuck interpreter
public class BrainLuck {
private static Map<String, Consumer<Data>> operations = new HashMap<>();
static {
operations.put(">", Data::incrementPointer);
operations.put("<", Data::decrementPointer);
operations.put("+", Data::increment);
operations.put("-", Data::decrement);
operations.put(".", Data::output);
}
private static class Data {
private final List<Byte> data = new ArrayList<>();
private int currentPointer = 0;
private final List<Byte> output = new ArrayList<>();
public Data() {
data.add((byte) 0);
}
public void incrementPointer() {
currentPointer++;
if (data.size() <= currentPointer) {
data.add((byte) 0);
}
}
public void decrementPointer() {
currentPointer--;
}
public void increment() {
int valueAtPointer = data.get(currentPointer);
if (valueAtPointer == 255) {
valueAtPointer = -1;
}
data.set(currentPointer, (byte) ++valueAtPointer);
}
public void decrement() {
int valueAtPointer = data.get(currentPointer);
if (valueAtPointer == 0) {
valueAtPointer = 256;
}
data.set(currentPointer, (byte) --valueAtPointer);
}
public byte get() {
return data.get(currentPointer);
}
public void output() {
output.add(get());
}
public void input(byte b) {
data.set(currentPointer, b);
}
}
private List functions = new ArrayList<>();
private int currentInstruction;
private List<int[]> bracketPairs = new ArrayList<>();
public BrainLuck(String code) {
int i = 0;
for (String instruction : code.split("")) {
int currentI = i;
if (operations.containsKey(instruction)) {
functions.add(operations.get(instruction));
} else {
switch (instruction) {
case ",":
functions.add((BiConsumer<Data, Byte>) Data::input);
break;
case "[":
bracketPairs.add(new int[] { i, findMatchingBracket(code, i) });
Consumer<Data> o = d -> currentInstruction = (d.get() == 0 ? bracketPairs.stream().filter(arr -> arr[0] == currentI).findFirst().get()[1] : currentInstruction);
functions.add(o);
break;
case "]":
o = d -> currentInstruction = (d.get() != 0 ? bracketPairs.stream().filter(arr -> arr[1] == currentI).findFirst().get()[0] : currentInstruction);
functions.add(o);
break;
}
}
i++;
}
}
private int findMatchingBracket(String code, int openingBracket) {
int openedBrackets = 0;
int openedBracketsBeforeToFind = -1;
int index = 0;
for (String s : code.split("")) {
if (index == openingBracket) {
openedBracketsBeforeToFind = openedBrackets;
}
if (s.equals("[")) {
openedBrackets++;
}
if (s.equals("]")) {
openedBrackets--;
}
if (openedBrackets == openedBracketsBeforeToFind) {
return index;
}
index++;
}
return -1;
}
public String process(String input) {
currentInstruction = 0;
Data data = new Data();
String processedInput = input;
while (currentInstruction < functions.size()) {
Object instruction = functions.get(currentInstruction);
if (instruction instanceof Consumer) {
((Consumer<Data>) instruction).accept(data);
}
if (instruction instanceof BiConsumer) {
char first = processedInput.charAt(0);
processedInput = processedInput.substring(1, processedInput.length());
((BiConsumer<Data, Byte>) instruction).accept(data, (byte) first);
}
currentInstruction++;
}
return data.output.stream().map(b -> new String(new byte[] { b })).collect(Collectors.joining());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment