def make_interval(x, y):
    return pair(x, y)
def lower_bound(x):
    return head(x)
def upper_bound(x):
    return tail(x)
def make_interval(x, y):
    return pair(x, y)
def lower_bound(i):
    return head(i)
def upper_bound(i):
    return tail(i)
# printing the interval in one line requires some string
# manipulation: str turns a number into a string
# and the operator + can be applied to strings for
# string concatenation
def print_interval(i):
    return ("[ "  + str(lower_bound(i)) +
            " , " + str(upper_bound(i)) + " ]")
def mul_interval(x, y):
    p1 = lower_bound(x) * lower_bound(y)
    p2 = lower_bound(x) * upper_bound(y)
    p3 = upper_bound(x) * lower_bound(y)
    p4 = upper_bound(x) * upper_bound(y)
    return make_interval(min(p1, p2, p3, p4),
                         max(p1, p2, p3, p4))
def div_interval(x, y):
    return (error("division error (interval spans 0)")
            if lower_bound(y) <= 0 and upper_bound(y) >= 0
            else mul_interval(x, make_interval(1 / upper_bound(y),
                                               1 / lower_bound(y))))

print(print_interval(div_interval(make_interval(1, 2),
                            make_interval(3, 5))))

# expected: '[ 0.2 , 0.6666666666666666 ]'
