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: introductory

Starter code:

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

Solutions:
# -*- coding: utf-8 -*-
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=r'\((-?\d+)([+\-*/])(-?\d+)\)'):
        args = list(args)
        s = re.sub(r'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))

import operator

class Placeholder:
    def __init__(self, op=None, left=None, right=None):
        self.op = op
        self.left = left
        self.right = right
    def eval(self, args):
        if self.op:
            x, args = self.left.eval(args) if isinstance(self.left, Placeholder) else (self.left, args)
            y, args = self.right.eval(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.eval(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()

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=[]):
#         if Placeholder.num != -1:
#             Placeholder.num = -1
        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()

from operator import mul, add,  floordiv, sub


class Placeholder:
    num = -1
    def __init__(self, so_farr=[]):
#         if Placeholder.num != -1:
#             Placeholder.num = -1
        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]
                    continue
            i += 1
            if i >= len(ds):
                i = 0
                priori += 1
        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)

# a skeleton class with required operators provided for convenience
# feel free to use another approach
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
# a skeleton class with required operators provided for convenience
# feel free to use another approach
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()