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!

Source: codewars | Difficulty: EASY
Tags: String algorithms

Data structures

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


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