Task
======

Make a custom esolang interpreter for the language [InfiniTick](https://esolangs.org/wiki/InfiniTick). InfiniTick is a descendant of [Tick](https://esolangs.org/wiki/tick) but also very different. Unlike Tick, InfiniTick has 8 commands instead of 4. It also runs infinitely, stopping the program only when an error occurs. You may choose to do the [Tick](https://www.codewars.com/kata/esolang-tick) kata first.

Syntax/Info
======

InfiniTick runs in an infinite loop. This makes it both harder and easier to program in. It has an infinite memory of bytes and an infinite output amount. The program only stops when an error is reached. The program is also supposed to ignore non-commands.

Commands
======

`>`: Move data selector right.

`<`: Move data selector left.

`+`: Increment amount of memory cell. Truncate overflow: 255+1=0.

`-`: Decrement amount of memory cell. Truncate overflow: 0-1=255.

`*`: Add ascii value of memory cell to the output tape.

`&`: Raise an error, ie stop the program.

`/`: Skip next command if cell value is zero.

`\`: Skip next command if cell value is nonzero.

Examples
======

**Hello world!**

The following is a valid hello world program in InfiniTick.

```
'++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++**>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*>++++++++++++++++++++++++++++++++*>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*<<*>>>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*<<<<*>>>>>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*>+++++++++++++++++++++++++++++++++*&'
```

Notes
======

* Please be wordy and post your likes/dislikes in the discourse area.
* If this kata is a duplicate or uses incorrect style, this is not an issue, this is a suggestion.
* Please don't edit this kata just to change the estimated rank. Thank you!

Difficulty: introductory

Starter code:

def interpreter(tape):
	

Solutions:
def interpreter(tape):
    memory, ptr, output, iCmd = {}, 0, "", 0
    
    while True:
        cmd = tape[iCmd]
        if   cmd == ">":  ptr += 1
        elif cmd == "<":  ptr -= 1
        elif cmd == "+":  memory[ptr] = (memory.get(ptr, 0) + 1) % 256
        elif cmd == "-":  memory[ptr] = (memory.get(ptr, 0) - 1) % 256
        elif cmd == "*":  output += chr(memory.get(ptr, 0))
        elif cmd == "&":  break
        elif cmd == "/":  iCmd += memory.get(ptr, 0) == 0
        elif cmd == "\\": iCmd += memory.get(ptr, 0) != 0
        iCmd = (iCmd+1) % len(tape)
    
    return output

def interpreter(tape):
    memory, ptr, output, skip, i = {0: 0}, 0, "", False, 0
    
    while True:
        command = tape[i]
        i = (i + 1) % len(tape)
        
        if command in "><+-*&/\\" and skip:
            skip = False
            continue
        
        if   command == ">":  ptr += 1
        elif command == "<":  ptr -= 1
        elif command == "+":  memory[ptr] = (memory.get(ptr, 0) + 1) % 256
        elif command == "-":  memory[ptr] = (memory.get(ptr, 0) - 1) % 256
        elif command == "*":  output += chr(memory.get(ptr, 0))
        elif command == "&":  break
        elif command == "/"  and memory[ptr] == 0:  skip = True
        elif command == "\\" and memory[ptr] != 0:  skip = True
    
    return output

import itertools

def interpreter(tape):    
    cells, cell, out, skip = {}, 0, '', False
    for c in itertools.cycle(tape):
        if not skip:
            if c == '>': cell += 1
            if c == '<': cell -= 1
            if c == '+': cells[cell] = 1 if cell not in cells else 0 if cells[cell] == 255 else cells[cell] + 1
            if c == '-': cells[cell] = 255 if cell not in cells else 255 if cells[cell] == 0 else cells[cell] - 1
            if c == '*': out += chr(cells.get(cell, 0))
            if c == '&': break
        skip = (c == '/' and cells.get(cell, 0) == 0) or (c == '\\' and cells.get(cell, 0))
    return out

def interpreter(tape):
    infTick = Ticker()
    infTick.run(tape)
    return infTick.out
    
class Ticker():
    error = lambda x:None
    doc   = {'>':'_incr', '<':'_decr', '*':'_addA', 
             '+':'_icrC', '-':'_dcrC', '/':'_skpZ', '\\':'_skpN', '&':'_error'}
    
    def __init__(self):
        self.cell = 0
        self.dat  = [0] * 255
        self.out  = ''
        self.skip = 0
        self.end  = 0
        
    def skip(f):
        def wrap(cls):
            if not cls.skip:
                return f(cls)
            cls.skip = 0
        return wrap

    def run(self, com):
        while not self.end and len(self.out) != 256:
            [getattr(self, self.doc.get(k, 'error'))() for k in com]

    def _skpZ(self):
        if self.dat[self.cell] == 0:
            self.skip = 1
    
    def _skpN(self):
        if self.dat[self.cell] != 0:
            self.skip = 1
            
    @skip
    def _error(self):
        self.end = 1
        
    @skip
    def _addN(self):#!
        self.dat[self.cell] = ord(self.out[-1])

    @skip
    def _dcrC(self):#-
        self.dat[self.cell] -= 1
    
    @skip
    def _icrC(self):#+
        self.dat[self.cell] += 1
        
    @skip
    def _addA(self):#*
        self.out += chr(self.dat[self.cell]%256)
        
    @skip
    def _incr(self):#>
        self.cell += 1
        
    @skip
    def _decr(self):#<
        self.cell -= 1

def interpreter(tape):
    test = Ticker(tape)
    test.run()
    return test.out
    
class Ticker():
    error = lambda x:None
    doc   = {'>':'_incr', '<':'_decr', '*':'_addA', 
             '+':'_icrC', '-':'_dcrC', '/':'_skpZ', '\\':'_skpN', '&':'_error'}
    
    def __init__(self, tape):
        self.com = tape
        self.cell = 0
        self.dat = [0] * 255
        self.out = ''
        self.skip = 0
        self.end = 0
        
    def skip(f):
        def wrap(cond):
            if not cond.skip:
                return f(cond)
            cond.skip = 0
        return wrap

    def run(self):
        while not self.end and len(self.out) != 256:
            [getattr(self, self.doc.get(k, 'error'))() for k in self.com]

    def _skpZ(self):
        if self.dat[self.cell] == 0:
            self.skip = 1
    
    def _skpN(self):
        if self.dat[self.cell] != 0:
            self.skip = 1
            
    @skip
    def _error(self):
        self.end = 1
        
    @skip
    def _addN(self):#!
        self.dat[self.cell] = ord(self.out[-1])

    @skip
    def _dcrC(self):#-
        self.dat[self.cell] -= 1
    
    @skip
    def _icrC(self):#+
        self.dat[self.cell] += 1
        #
    @skip
    def _addA(self):#*
        self.out += chr(self.dat[self.cell]%256)
        
    @skip
    def _incr(self):#>
        self.cell += 1
        
    @skip
    def _decr(self):#<
        self.cell -= 1
          


from collections import defaultdict
from itertools import cycle

def interpreter(tape):
    i, skip, D, res = 0, False, defaultdict(int), []
    for c in cycle(tape):
        if skip: skip = False
        elif c == '>': i += 1
        elif c == '<': i -= 1
        elif c == '+': D[i] = (D[i] + 1)%256
        elif c == '-': D[i] = (D[i] - 1)%256
        elif c == '*': res.append(chr(D[i]))
        elif c == '&': break
        elif c == '/': skip = not D[i]
        elif c == '\\': skip = D[i]
    return ''.join(res)

from collections import defaultdict
from itertools import cycle

valid = ('<', '>', '+', '-', '*', '/', '\\', '&')

def interpreter(tape):
    memory = defaultdict(int)
    pointer = 0    
    input = cycle(c for c in tape if c in valid)
    output = ''    
    
    while True:
        c = next(input)
        if   c == '>': pointer += 1
        elif c == '<': pointer -= 1
        elif c == '+': memory[pointer] = (memory[pointer] + 1) % 256
        elif c == '-': memory[pointer] = (memory[pointer] - 1) % 256
        elif c == '*': output += chr(memory[pointer])
        elif c == '/'  and not memory[pointer]: next(input)
        elif c == '\\' and memory[pointer]: next(input)
        elif c == '&': return output

class InfiniTick:
    def __init__(self):
        self.mem = [0]
        self.pointer = 0
    
    def move_right(self):
        self.pointer += 1
        if self.pointer == len(self.mem):
            self.mem.append(0)
    
    def move_left(self):
        if self.pointer != 0:
            self.pointer -= 1
        else:
            self.mem.insert(0,0)
            self.pointer = 0

    def increment(self):
        self.mem[self.pointer] += 1
        if self.mem[self.pointer] > 255:
            self.mem[self.pointer] = 0
            
    def decrement(self):
        self.mem[self.pointer] -= 1
        if self.mem[self.pointer] < 0:
            self.mem[self.pointer] = 256 + self.mem[self.pointer]
            
    def output(self):
        return chr(self.mem[self.pointer])

    def process(self, tape):
        result = ""
        i = 0
        
        while True:
            if tape[i] == ">":
                self.move_right()
            elif tape[i] == "<":
                self.move_left()
            elif tape[i] == "+":
                self.increment()
            elif tape[i] == "-":
                self.decrement()
            elif tape[i] == "*":
                result += self.output()
            elif tape[i] == "&":
                break
            elif tape[i] == "/":
                if self.mem[self.pointer] == 0:
                    i += 1
            elif tape[i] == "\\":
                if self.mem[self.pointer] != 0:
                    i += 1
            i += 1
            if i == len(tape):
                i = 0
            elif i > len(tape):
                i = 1
                
        return result
        
def interpreter(tape):
    tick = InfiniTick()
    return tick.process(tape)

def interpreter(tape):
    selector = 0
    output = ""
    array = [0]
    commandIndex = 0
    
    while(True):
      command = tape[commandIndex%len(tape)]
      
      if command == '>':
        selector+=1;
        if selector == len(array):
          array.append(0)
      
      if command == '<':
        if selector == 0:
          array = [0] + array  
        else:
          selector-=1;
        
      if command == '+':
        array[selector]+=1;
        if array[selector] == 256:
          array[selector] = 0
      if command == '-':
        array[selector]-=1;
        if array[selector] == -1:
          array[selector] = 255
      if command == '/':
        if array[selector] == 0:
          commandIndex += 1
      if command == '\\':
        if array[selector] != 0:
          commandIndex += 1
      if command == '*':
        output = output + chr(array[selector])
      if command == '&':
        return output        
      commandIndex+=1  
    return output

def interpreter(tape):
    data, pos, res = [0 for i in range(tape.count('*'))], 0, ""
    while 1:
        try:
            for i in iter([i for i in tape]):
                if   i == "+": data[pos] = (data[pos] + 1) %256
                elif i == "-": data[pos] = (data[pos] - 1) %256
                elif i == ">": pos += 1
                elif i == "<": pos -= 1
                elif i == "*": res += chr(data[pos])
                elif i == "/" and data[pos] == 0: next(tape)
                elif i == "\\" and data[pos] != 0: next(tape)
                elif i == "&": return res
        except:
            pass