My smallest code interpreter in Java


The problem

Impressed from real-world Brainf**okay, we need to create an interpreter of that language which is able to help the next directions:

  • > increment the info pointer (to level to the subsequent cell to the best).
  • < decrement the info pointer (to level to the subsequent cell to the left).
  • + increment (improve by one, truncate overflow: 255 + 1 = 0) the byte on the information pointer.
  • - decrement (lower by one, deal with as unsigned byte: 0 – 1 = 255 ) the byte on the information pointer.
  • . output the byte on the information pointer.
  • , settle for one byte of enter, storing its worth within the byte on the information pointer.
  • [ if the byte at the data pointer is zero, then instead of moving the instruction pointer forward to the next command, jump it forward to the command after the matching ] command.
  • ] if the byte on the information pointer is nonzero, then as an alternative of shifting the instruction pointer ahead to the subsequent command, leap it again to the command after the matching [ command.

The function will take in input…

  • the program code, a string with the sequence of machine instructions,
  • the program input, a string, eventually empty, that will be interpreted as an array of bytes using each character’s ASCII code and will be consumed by the , instruction

… and will return …

  • the output of the interpreted code (always as a string), produced by the . instruction.

Implementation-specific details for this challenge:

  • Your memory tape should be large enough – the original implementation had 30,000 cells but a few thousand should suffice for this challenge
  • Each cell should hold an unsigned byte with wrapping behavior (i.e. 255 + 1 = 0, 0 – 1 = 255), initialized to 0
  • The memory pointer should initially point to a cell in the tape with a sufficient number (e.g. a few thousand or more) of cells to its right. For convenience, you may want to have it point to the leftmost cell initially
  • You may assume that the command will never be invoked when the input stream is exhausted
  • Error-handling, e.g. unmatched square brackets and/or memory pointer going past the leftmost cell is not required in this challenge. 

The solution in Java code

Option 1:

import java.util.*;

public class BrainLuck {

    private int selector, lenCode, iCode;
    private StringBuilder lstInput, out;
    private List<Integer> stack;
    private Map<Integer,Integer> bracketD;
    private String code;

    public BrainLuck(String code) {      
    
        selector = 0;
        lenCode = code.length();
        iCode = 0;
        this.code = code;
        out = new StringBuilder();
        stack = new ArrayList<Integer>();
        stack.add(0);
        bracketD = new HashMap<Integer,Integer>();
        
        List<Integer> stackD = new ArrayList<Integer>();
        for (int i=0 ; i<lenCode ; i++) {
            if (code.charAt(i) == '[') stackD.add(i);
            if (code.charAt(i) == ']') {
                int h = stackD.take away( stackD.measurement()-1 );
                bracketD.put(h, i);
                bracketD.put(i, h);
            }
        }
    }

    public String course of(String enter) {
        
        lstInput = new StringBuilder(enter);
        
        whereas (iCode < lenCode) {
            if ( (code.charAt(iCode) == '>') && (selector++ == stack.measurement()-1) ) stack.add(0);
            if ( (code.charAt(iCode) == '<') && (selector-- == 0) ) stack.add(0, 0);
            if (code.charAt(iCode) == '+') stack.set(selector, (stack.get(selector)+1) % 256);
            if (code.charAt(iCode) == '-') stack.set(selector, (stack.get(selector)-1) % 256);
            if (code.charAt(iCode) == '.') out.append( (char) stack.get(selector).intValue() );
            if (code.charAt(iCode) == ',') {
                stack.set(selector, (int) lstInput.charAt(0));
                lstInput.deleteCharAt(0);
            }
            if (code.charAt(iCode) == '[' && stack.get(selector) == 0) iCode = bracketD.get(iCode);
            if (code.charAt(iCode) == ']' && stack.get(selector) != 0) iCode = bracketD.get(iCode);
            iCode++;
        }
        return out.toString();
    }
}

Choice 2:

import java.util.*;

public class BrainLuck {
    String code;
    public BrainLuck(String code) {      
      this.code=code;
    }

    public String course of(String enter) {
    System.out.println(code);
      Stack<Integer> brack = new Stack<Integer>();
      Checklist<Byte> bytes = new ArrayList<Byte>();
      int pointer=0;
      String out="";
      bytes.add((byte)0);
      for(int i=0; i<code.size();i++) {
        char c = code.charAt(i);
        if(c=='>'){
          pointer++;
          if(pointer==bytes.measurement()) bytes.add((byte)0);
        }else if(c=='<'){
          pointer--;
          if(pointer==-1) {
            bytes.add(0,(byte)0);
            pointer=0;
          }
        }else if(c=='+'){
          bytes.set(pointer,(byte)(bytes.get(pointer)+1));
        }else if(c=='-'){
          bytes.set(pointer,(byte)(bytes.get(pointer)-1));
        }else if(c=='.'){
          out+=(char)(int)bytes.get(pointer);
        }else if(c==','){
          if(!enter.isEmpty()){
            bytes.set(pointer,(byte)(int)enter.charAt(0));
            enter=enter.substring(1);
          }
        }else if(c=='['){
          if(bytes.get(pointer)==0) {
            int left=1,k=i;
            while(left!=0){
              k++;
              if(code.charAt(k)=='[') left++;
              else if(code.charAt(k)==']') left--;
            }
            i=okay;
          }
          else brack.push(i);
        }else if(c==']'){
          if(bytes.get(pointer)!=0) i=brack.peek();
          else brack.pop();
        }
      }
      return out;
    }
}

Choice 3:

import java.util.LinkedList;
import java.util.stream.Collectors;

public class BrainLuck {
  
    personal ultimate String code;
    personal LinkedList<Byte> enter;
    personal ultimate LinkedList<Byte> reminiscence;
    personal ultimate StringBuilder output;

    public BrainLuck(String code) {
      this.code = code;
      reminiscence = new LinkedList<>();
      reminiscence.add((byte)0);
      output = new StringBuilder("");
    }

    public String course of(String inputStr) {
      enter = inputStr.chars().mapToObj(n -> (byte) n).gather(Collectors.toCollection(LinkedList::new));
      LinkedList<Integer> dad and mom = new LinkedList<>();
      int pointer = 0;
      for (int i = 0; i < code.size(); i++) {
        change (code.charAt(i)) {
          case '>':
            if (reminiscence.measurement() - 1 < ++pointer) reminiscence.add((byte)0);
            break;
          case '<':
            pointer--;
            break;
          case '+':
            reminiscence.set(pointer, (byte) (reminiscence.get(pointer) + 1));
            break;
          case '-':
            reminiscence.set(pointer, (byte) (reminiscence.get(pointer) - 1));
            break;
          case '.':
            output.append((char) reminiscence.get(pointer).byteValue());
            break;
          case ',':
            reminiscence.set(pointer, enter.pop());
            break;
          case '[':
            if (memory.get(pointer) != 0) {
              parents.push(i);
            } else {
              int size = parents.size();
              while (code.charAt(++i) != ']' || dad and mom.measurement() != measurement) {
                if (code.charAt(i) == '[') parents.push(i);
                if (code.charAt(i) == ']') dad and mom.pop();
              }
            }
            break;
          case ']':
            if (reminiscence.get(pointer) != 0) {
              i = dad and mom.peekFirst();
            } else {
              dad and mom.pop();
            }
            break;
        }
      }
      return output.toString();
    }
}

Take a look at instances to validate our answer

import org.junit.Take a look at;

import java.util.Random;
import java.util.UUID;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

public class BrainLuckTest {
    personal ultimate Random random = new Random(System.currentTimeMillis());

    @Take a look at
    public void testEchoUntilByte255Encountered() {
        assertThat(new BrainLuck(",+[-.,+]").course of("Codewars" + ((char) 255)), is("Codewars"));
    }

    @Take a look at
    public void testEchoUntilByte0Encountered() {
        assertThat(new BrainLuck(",[.[-],]").course of("Codewars" + ((char) 0)), is("Codewars"));
    }

    @Take a look at
    public void testTwoNumbersMultiplier() {
        ultimate char[] enter = {8, 9};
        assertThat(new BrainLuck(",>,<[>[->+>+<<]>>[-<<+>>]<<<-]>>.").course of(String.valueOf(enter[0]) + String.valueOf(enter[1])), is(String.valueOf((char) (enter[0] * enter[1]))));
    }

    @Take a look at
    public void testHelloWorld() {
        assertThat(new BrainLuck("++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.").course of(""), is("Good day World!"));
    }

    @Take a look at
    public void testEchoUntilByte255EncounteredWithRandomSequence() {
        String randomSequence = UUID.randomUUID().toString();
        assertThat(new BrainLuck(",+[-.,+]").course of(randomSequence + ((char) 255)), is(randomSequence));
    }

    @Take a look at
    public void testEchoUntilByte0EncounteredWithRandomSequence() {
        String randomSequence = UUID.randomUUID().toString();
        assertThat(new BrainLuck(",[.[-],]").course of(randomSequence + ((char) 0)), is(randomSequence));
    }

    @Take a look at
    public void testTwoNumbersMultiplierWithRandomNumbers() {
        ultimate char[] enter = {(char) (random.nextInt(10) + 1), (char) (random.nextInt(10) + 1)};
        assertThat(new BrainLuck(",>,<[>[->+>+<<]>>[-<<+>>]<<<-]>>.").course of(String.valueOf(enter[0]) + String.valueOf(enter[1])), is(String.valueOf((char) (enter[0] * enter[1]))));
    }

    @Take a look at
    public void testFibonacci() {
        assertThat(new BrainLuck(",>+>>>>++++++++++++++++++++++++++++++++++++++++++++>++++++++++++++++++++++++++++++++<<<<<<[>[>>>>>>+>+<<<<<<<-]>>>>>>>[<<<<<<<+>>>>>>>-]<[>++++++++++[-<-[>>+>+<<<-]>>>[<<<+>>>-]+<[>[-]<[-]]>[<<[>>>+<<<-]>>[-]]<<]>>>[>>+>+<<<-]>>>[<<<+>>>-]+<[>[-]<[-]]>[<<+>>[-]]<<<<<<<]>>>>>[++++++++++++++++++++++++++++++++++++++++++++++++.[-]]++++++++++<[->-<]>++++++++++++++++++++++++++++++++++++++++++++++++.[-]<<<<<<<<<<<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<-[>>.>.<<<[-]]<<[>>+>+<<<-]>>>[<<<+>>>-]<<[<+>-]>[<+>-]<<<-]").course of(String.valueOf((char) 10)), is("1, 1, 2, 3, 5, 8, 13, 21, 34, 55"));
    }
}

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles