In Scala, an underscore may be used to create a partially applied version of an infix operator using placeholder syntax. For example, `(_ * 3)` is a function that multiplies its input by 3. With a bit of manipulation, this idea can be extended to work on any arbitrary expression.

Create an value/object named `x` that acts as a placeholder in an arithmetic expression. The placeholder should support the four basic integer arithmetic operations: addition, subtraction, multiplication, and integral (floor) division. When the expression with placeholders is called, it should fill the placeholders in the expression from left to right (regardless of operator precedence) with the values it is given.

Here are a few examples:
```
calling (x + 3)       with [1]   gives 1 + 3               = 4
calling (10 - x)      with [4]   gives 10 - 4              = 6
calling (x + 2 * x)   with [1 3] gives 1 + 2 * 3   = 1 + 6 = 7
calling ((x + 2) * x) with [1 3] gives (1 + 2) * 3 = 3 * 3 = 9
calling (4 * (x / 2)) with [5]   gives 4 * (5 / 2) = 4 * 2 = 8
```

All inputs and outputs to/from the expression will be integer types. All expressions tested in this kata will be valid, i.e. there will be no division by zero and the number of values passed in will always be the same as the number of placeholders.

Note: `eval` and `exec` are disabled

Difficulty: EASY

Starter code:
def __init__(self, op=None, left=None, right=None):
	

Solutions:
import operator

class Placeholder:

	def __init__(self, op=None, left=None, right=None):
		self.op = op
		self.left = left
		self.right = right

	def calc(self, args):
		if self.op:
			(x, args) = self.left.calc(args) if isinstance(self.left, Placeholder) else (self.left, args)
			(y, args) = self.right.calc(args) if isinstance(self.right, Placeholder) else (self.right, args)
			return (self.op(x, y), args)
		return (args[0], args[1:])

	def __call__(self, *args):
		return self.calc(args)[0]

	def __add__(self, other):
		return Placeholder(op=operator.add, left=self, right=other)

	def __sub__(self, other):
		return Placeholder(op=operator.sub, left=self, right=other)

	def __mul__(self, other):
		return Placeholder(op=operator.mul, left=self, right=other)

	def __floordiv__(self, other):
		return Placeholder(op=operator.floordiv, left=self, right=other)

	def __radd__(self, other):
		return Placeholder(op=operator.add, left=other, right=self)

	def __rsub__(self, other):
		return Placeholder(op=operator.sub, left=other, right=self)

	def __rmul__(self, other):
		return Placeholder(op=operator.mul, left=other, right=self)

	def __rfloordiv__(self, other):
		return Placeholder(op=operator.floordiv, left=other, right=self)
x = Placeholder()


import re

class Exp(object):

	def __init__(self, v='x'):
		self.exp = v
	__str__ = lambda self: self.exp
	make = lambda self, other, sign, r=1: Exp('({}{}{})'.format(*[self.exp, sign, str(other)][::r]))
	oparation = lambda self, a, b, sign: str(a + b if sign == '+' else a - b if sign == '-' else a * b if sign == '*' else a // b)

	def __call__(self, *args, sr='\\((-?\\d+)([+\\-*/])(-?\\d+)\\)'):
		args = list(args)
		s = re.sub('x', lambda x: str(args.pop(0)), self.exp)
		k = re.search(sr, s)
		while k:
			(a, sign, b) = k.groups()
			s = s[:k.start()] + self.oparation(int(a), int(b), sign) + s[k.end():]
			k = re.search(sr, s)
		return int(s)
x = Exp()
for (i, j) in zip('add sub mul floordiv radd rsub rmul rfloordiv'.split(), '+-*/' * 2):
	setattr(Exp, f'__{i}__', lambda self, other, sign=j, r=[1, -1][i[0] == 'r']: self.make(other, sign, r))


def unwrap(obj, x):
	return obj.do(x) if hasattr(obj, 'do') else obj

class Placeholder:

	def __init__(self, action=lambda x: x.pop(0)):
		self.do = action

	def __call__(self, *args):
		return self.do([*args])

	def __add__(self, other):
		return Placeholder(lambda x: self.do(x) + unwrap(other, x))

	def __sub__(self, other):
		return Placeholder(lambda x: self.do(x) - unwrap(other, x))

	def __mul__(self, other):
		return Placeholder(lambda x: self.do(x) * unwrap(other, x))

	def __floordiv__(self, other):
		return Placeholder(lambda x: self.do(x) // unwrap(other, x))

	def __radd__(self, other):
		return Placeholder(lambda x: unwrap(other, x) + self.do(x))

	def __rsub__(self, other):
		return Placeholder(lambda x: unwrap(other, x) - self.do(x))

	def __rmul__(self, other):
		return Placeholder(lambda x: unwrap(other, x) * self.do(x))

	def __rfloordiv__(self, other):
		return Placeholder(lambda x: unwrap(other, x) // self.do(x))
x = Placeholder()


from operator import mul, add, floordiv, sub

class Placeholder:
	num = -1

	def __init__(self, so_farr=[]):
		self.so_far = so_farr

	def __call__(self, *args):
		ds = self.unpacked()
		(priori, m) = (0, 0)
		for i in range(len(ds)):
			if ds[i] == '':
				ds[i] = args[m]
				m += 1
		i = 0
		while len(ds) > 1:
			if i < len(ds) and isinstance(ds[i], tuple):
				if ds[i][1] == priori:
					ds[i] = ds[i][0](ds[i - 1], ds[i + 1])
					del ds[i - 1]
					del ds[i]
					priori += 1
					continue
			i += 1
			if i >= len(ds):
				i = 0
		Placeholder.num = -1
		return ds[0]

	def unpacked(self):
		ds = []
		for i in range(len(self.so_far)):
			if isinstance(self.so_far[i], Placeholder):
				ds += self.so_far[i].unpacked()
			else:
				ds += [self.so_far[i]]
		if not self.so_far:
			ds += ['']
		return ds

	def __add__(self, other):
		self.nullif()
		Placeholder.num += 1
		return Placeholder(self.so_far + [(add, self.num), other])

	def __sub__(self, other):
		self.nullif()
		Placeholder.num += 1
		return Placeholder(self.so_far + [(sub, self.num), other])

	def nullif(self):
		if not self.so_far:
			self.so_far.append('')

	def __mul__(self, other):
		self.nullif()
		Placeholder.num += 1
		return Placeholder(self.so_far + [(mul, self.num), other])

	def __floordiv__(self, other):
		self.nullif()
		Placeholder.num += 1
		return Placeholder(self.so_far + [(floordiv, self.num), other])

	def __radd__(self, other):
		self.nullif()
		Placeholder.num += 1
		return Placeholder([other, (add, self.num)] + self.so_far)

	def __rsub__(self, other):
		self.nullif()
		Placeholder.num += 1
		return Placeholder([other, (sub, self.num)] + self.so_far)

	def __rmul__(self, other):
		self.nullif()
		Placeholder.num += 1
		return Placeholder([other, (mul, self.num)] + self.so_far)

	def __rfloordiv__(self, other):
		self.nullif()
		Placeholder.num += 1
		return Placeholder([other, (floordiv, self.num)] + self.so_far)
x = Placeholder()


class Placeholder:

	def __init__(self, n, f):
		(self.n, self.f) = (n, f)

	def __call__(self, *args):
		return self.f(*args)

	def __add__(self, other):
		if isinstance(other, Placeholder):
			return Placeholder(self.n + other.n, lambda *args: self(*args[:self.n]) + other(*args[self.n:]))
		return Placeholder(self.n, lambda *args: self(*args) + other)

	def __sub__(self, other):
		if isinstance(other, Placeholder):
			return Placeholder(self.n + other.n, lambda *args: self(*args[:self.n]) - other(*args[self.n:]))
		return Placeholder(self.n, lambda *args: self(*args) - other)

	def __mul__(self, other):
		if isinstance(other, Placeholder):
			return Placeholder(self.n + other.n, lambda *args: self(*args[:self.n]) * other(*args[self.n:]))
		return Placeholder(self.n, lambda *args: self(*args) * other)

	def __floordiv__(self, other):
		if isinstance(other, Placeholder):
			return Placeholder(self.n + other.n, lambda *args: self(*args[:self.n]) // other(*args[self.n:]))
		return Placeholder(self.n, lambda *args: self(*args) // other)

	def __radd__(self, other):
		if isinstance(other, Placeholder):
			return Placeholder(self.n + other.n, lambda *args: other(*args[:self.n]) + self(*args[self.n:]))
		return Placeholder(self.n, lambda *args: other + self(*args))

	def __rsub__(self, other):
		if isinstance(other, Placeholder):
			return Placeholder(self.n + other.n, lambda *args: other(*args[:self.n]) - self(*args[self.n:]))
		return Placeholder(self.n, lambda *args: other - self(*args))

	def __rmul__(self, other):
		if isinstance(other, Placeholder):
			return Placeholder(self.n + other.n, lambda *args: other(*args[:self.n]) * self(*args[self.n:]))
		return Placeholder(self.n, lambda *args: other * self(*args))

	def __rfloordiv__(self, other):
		if isinstance(other, Placeholder):
			return Placeholder(self.n + other.n, lambda *args: other(*args[:self.n]) // self(*args[self.n:]))
		return Placeholder(self.n, lambda *args: other // self(*args))
x = Placeholder(1, int)


import operator

def placeholdify(other):
	if not isinstance(other, Placeholder):
		return Placeholder(lambda : other, 0)
	return other

def make_bin_op(op):

	def __op__(self, other):
		other = placeholdify(other)
		return Placeholder(lambda *args: op(self(*args[:self.n]), other(*args[self.n:])), self.n + other.n)
	return __op__

def make_bin_rop(op):

	def __rop__(self, other):
		other = placeholdify(other)
		return Placeholder(lambda *args: op(other(*args[:other.n]), self(*args[other.n:])), self.n + other.n)
	return __rop__

class Placeholder:

	def __init__(self, f, n):
		self.f = f
		self.n = n

	def __call__(self, *args):
		return self.f(*args)
	__add__ = make_bin_op(operator.add)
	__sub__ = make_bin_op(operator.sub)
	__mul__ = make_bin_op(operator.mul)
	__floordiv__ = make_bin_op(operator.floordiv)
	__radd__ = make_bin_rop(operator.add)
	__rsub__ = make_bin_rop(operator.sub)
	__rmul__ = make_bin_rop(operator.mul)
	__rfloordiv__ = make_bin_rop(operator.floordiv)
x = Placeholder(lambda x: x, 1)


class Placeholder:

	def __init__(self, num=None):
		self.func = None
		self.needed = 1 if num is None else 0
		self.num = num
		self.left = None
		self.right = None

	def __call__(self, *args):
		if type(args[0]) == tuple:
			args = args[0]
		if self.func is None:
			return args[0] if self.num is None else self.num
		left = self.left(args[:self.left.needed])
		right = self.right(args[self.left.needed:])
		return self.func(left, right)

	def op(self, other, func):
		x = Placeholder()
		x.left = self
		x.right = Placeholder(other) if type(other) == int else other
		x.num = None
		x.func = func
		x.needed = x.left.needed + x.right.needed
		return x

	def __add__(self, other):
		return self.op(other, lambda x, y: x + y)

	def __sub__(self, other):
		return self.op(other, lambda x, y: x - y)

	def __mul__(self, other):
		return self.op(other, lambda x, y: x * y)

	def __floordiv__(self, other):
		return self.op(other, lambda x, y: x // y)

	def rop(self, other, func):
		x = Placeholder()
		x.right = self
		x.left = Placeholder(other) if type(other) == int else other
		x.num = None
		x.func = func
		x.needed = x.left.needed + x.right.needed
		return x

	def __radd__(self, other):
		return self.rop(other, lambda x, y: x + y)

	def __rsub__(self, other):
		return self.rop(other, lambda x, y: x - y)

	def __rmul__(self, other):
		return self.rop(other, lambda x, y: x * y)

	def __rfloordiv__(self, other):
		return self.rop(other, lambda x, y: x // y)
x = Placeholder()


import operator

def calc(tree, args):
	if tree.left is None:
		tree.left = args.pop(0)
	if isinstance(tree.left, Tree):
		tree.left = calc(tree.left, args)
	if tree.right is None:
		tree.right = args.pop(0)
	if isinstance(tree.right, Tree):
		tree.right = calc(tree.right, args)
	return tree.op(tree.left, tree.right)

class Tree:

	def __init__(self, left=None, op=None, right=None):
		self.left = left
		self.right = right
		self.op = op

	def __call__(self, *args):
		args = list(args)
		result = calc(self, args)
		self.__init__()
		return result

	def __add__(self, other):
		return self._left_op(other, operator.add)

	def __sub__(self, other):
		return self._left_op(other, operator.sub)

	def __mul__(self, other):
		return self._left_op(other, operator.mul)

	def __floordiv__(self, other):
		return self._left_op(other, operator.floordiv)

	def __radd__(self, other):
		return self._right_op(other, operator.add)

	def __rsub__(self, other):
		return self._right_op(other, operator.sub)

	def __rmul__(self, other):
		return self._right_op(other, operator.mul)

	def __rfloordiv__(self, other):
		return self._right_op(other, operator.floordiv)

	def _left_op(self, right, op):
		left = None
		if self.op:
			left = self
		current = Tree(left, op, right)
		if isinstance(right, Tree):
			if self is right:
				current.right = None
			elif right.op:
				current.right = Tree(right.left, right.op, right.right)
			else:
				current.right = None
		return current

	def _right_op(self, left, op):
		right = None
		if self.op:
			right = self
		current = Tree(left, op, right)
		if isinstance(left, Tree):
			if self is left:
				current.left = None
			elif left.op:
				current.left = Tree(left.left, left.op, left.right)
			else:
				current.left = None
		return current
x = Tree()