code: def random_expr_with_required_var(depth, required_var, optional_list, ops):
    
    if not depth:
      if required_var:
        return required_var
      return str(optional_list[random.randrange(len(optional_list))])
  
    max_depth_side = random.randrange(2)
    other_side_depth = random.randrange(depth)
  
    required_var_side = random.randrange(2)
  
    left = random_expr_with_required_var(
        depth - 1 if max_depth_side else other_side_depth, required_var
        if required_var_side else None, optional_list, ops)
    right = random_expr_with_required_var(
        depth - 1 if not max_depth_side else other_side_depth, required_var
        if not required_var_side else None, optional_list, ops)
  
    op = ops[random.randrange(len(ops))]
    return ExprNode(left, right, op)
docs: Generate a random expression tree with a required variable.
  
    The required variable appears exactly once in the expression.
  
    Args:
      depth: At least one leaf will be this many levels down from the top.
      required_var: A char. This char is guaranteed to be placed exactly once at
          a leaf somewhere in the tree. This is the var to solve for.
      optional_list: A list of chars. These chars are randomly selected as leaf
          values. These are constant vars.
      ops: A list of ExprOp instances.
  
    Returns:
      An ExprNode instance which is the root of the generated expression tree.