def is_variable(x): return is_string(x)
def is_same_variable(v1, v2):
    return is_variable(v1) and is_variable(v2) and v1 == v2
def is_sum(x):
    return is_pair(x) and head(x) == "+"
def number_equal(exp, num):
    return is_number(exp) and exp == num
def make_sum(a1, a2):
    return (a2
            if number_equal(a1, 0)
            else a1
            if number_equal(a2, 0)
            else a1 + a2
            if is_number(a1) and is_number(a2)
            else llist("+", a1, a2))
def make_product(m1, m2):
    return (0
            if number_equal(m1, 0) or number_equal(m2, 0)
            else m2
            if number_equal(m1, 1)
            else m1
            if number_equal(m2, 1)
            else m1 * m2
            if is_number(m1) and is_number(m2)
            else llist("*", m1, m2))
def addend(s): return head(tail(s))
def is_product(x):
    return is_pair(x) and head(x) == "*"
def multiplier(s): return head(tail(s))
# change the representation of terms
# by defining augend and multiplicand

def deriv(exp, variable):
    return (0
            if is_number(exp)
            else (1 if is_same_variable(exp, variable) else 0)
            if is_variable(exp)
            else make_sum(deriv(addend(exp), variable),
                          deriv(augend(exp), variable))
            if is_sum(exp)
            else make_sum(make_product(multiplier(exp),
                                       deriv(multiplicand(exp), variable)),
                          make_product(deriv(multiplier(exp), variable),
                                       multiplicand(exp)))
            if is_product(exp)
            else error("unknown expression type -- deriv", exp))
