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 number_equal(exp, num):
    return is_number(exp) and exp == num
def items_before_first(op, s):
    return (None
            if is_string(head(s)) and head(s) == op
            else pair(head(s),
                      items_before_first(op, tail(s))))
def items_after_first(op, s):
    return (tail(s)
            if is_string(head(s)) and head(s) == op
            else items_after_first(op, tail(s)))
def simplify_unary_linked_list(s):
    return (head(s)
            if is_pair(s) and is_none(tail(s))
            else s)
def contains_plus(s):
    return (False
            if is_none(s)
            else True
            if is_string(head(s)) and head(s) == "+"
            else contains_plus(tail(s)))
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))
# a sequence of terms and operators is a sum
# if and only if at least one + operator occurs
def is_sum(x):
    return is_pair(x) and contains_plus(x)
def addend(s):
    return simplify_unary_linked_list(items_before_first("+", s))
def augend(s):
    return simplify_unary_linked_list(items_after_first("+", s))
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))
# a sequence of terms and operators is a product
# if and only if no + operator occurs
def is_product(x):
    return is_pair(x) and not contains_plus(x)
def multiplier(s):
    return simplify_unary_linked_list(items_before_first("*", s))
def multiplicand(s):
    return simplify_unary_linked_list(items_after_first("*", s))
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))

print(deriv(llist("x", "*", 4), "x"))
