Hausaufgabe 4: Datenabstraktion, Bäume

F9: Div-Intervall (diese Frage birgt Fallstricke)

Alyssa implementiert unten die Division durch Multiplikation mit dem Kehrwert von y. Ben Bitdiddle, ein erfahrener Systemprogrammierer, schaut Alyssa über die Schulter und bemerkt, dass nicht klar ist, was es bedeutet, durch ein Intervall zu dividieren, das über Null hinausgeht. Fügen Sie Alyssas Code eine assert -Anweisung hinzu, um sicherzustellen, dass kein solches Intervall als Teiler verwendet wird:

def div_interval(x, y):
    """Return the interval that contains the quotient of any value in x divided by
    any value in y. Division is implemented as the multiplication of x by the
    reciprocal of y."""
    "*** YOUR CODE HERE ***"
    reciprocal_y = interval(1/upper_bound(y), 1/lower_bound(y))
    return mul_interval(x, reciprocal_y)

 1. Das zweite Entsperrbeispiel:

Eingabe: AssertionError (es kann zu Fehlern bei der Großschreibung kommen)

 2. Zwei Funktionen müssen geändert werden:

(Das zweite Beispiel definiert x, y als Lambdas anstelle von Listen neu)

TypeError: „Funktion“-Objekt ist nicht abonnierbar (wenn nicht festgestellt wird, ob x eine Funktion ist)

(Dies wird nicht empfohlen, der abstrahierte Code befindet sich in p3)


from inspect import isfunction
def mul_interval(x, y):
    """Return the interval that contains the product of any value in x and any
    value in y."""
    if isfunction(x):
        p1 = x(0) * y(0)
        p2 = x(0) * y(1)
        p3 = x(1) * y(0)
        p4 = x(1) * y(1)
        return lambda x: min(p1, p2, p3, p4) if x == 0 else max(p1, p2, p3, p4)
    else:
        p1 = x[0] * y[0]
        p2 = x[0] * y[1]
        p3 = x[1] * y[0]
        p4 = x[1] * y[1]
        return [min(p1, p2, p3, p4), max(p1, p2, p3, p4)]

def div_interval(x, y):
    """Return the interval that contains the quotient of any value in x divided by
    any value in y. Division is implemented as the multiplication of x by the
    reciprocal of y."""
    "*** YOUR CODE HERE ***"
    assert lower_bound(y) >0 or upper_bound(y)<0, "AssertionError!"
    reciprocal_y = interval(1 / upper_bound(y), 1 / lower_bound(y))
    return mul_interval(x, reciprocal_y)

3. (Ich habe herausgefunden, dass dies zur Überprüfung der Abstraktion dient, und der Code wird unten geändert):

def mul_interval(x, y):
    """Return the interval that contains the product of any value in x and any
    value in 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 interval(min(p1, p2, p3, p4), max(p1, p2, p3, p4))

4. Passsituation: 

Assignment: Homework 4
OK, version v1.18.1
=====================================================================

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Running tests

---------------------------------------------------------------------
Test summary
    2 test cases passed! No cases failed.

F11: Quadratisch

Schreiben Sie eine Funktion quadratic die das Intervall aller Werte zurückgibt f(t) so dass t im Argumentintervall liegt < /span> :quadratische Funktion ist eine x und f(t)

f(t) = a*t*t + b*t + c

Stellen Sie sicher, dass Ihre Implementierung das kleinste Intervall dieser Art zurückgibt, eines, bei dem das Problem der Mehrfachreferenzen nicht auftritt.

Hinweis: Die Ableitung f'(t) = 2*a*t + b, und daher ist der Extrempunkt der quadratischen Gleichung -b/(2*a):

Beachten Sie die Verwendung abstrakter Funktionen: 

def quadratic(x, a, b, c):
    """Return the interval that is the range of the quadratic defined by
    coefficients a, b, and c, for domain interval x.

    >>> str_interval(quadratic(interval(0, 2), -2, 3, -1))
    '-3 to 0.125'
    >>> str_interval(quadratic(interval(1, 3), 2, -3, 1))
    '0 to 10'
    """
    "*** YOUR CODE HERE ***"
    def f(t):
        return a * t * t + b * t + c

    l,r=f(lower_bound(x)),f(upper_bound(x))
    turning_point = -b / (2 * a)
    
    if upper_bound(x)>turning_point>lower_bound(x):
        return interval(min(l,r,f(turning_point)),max(l,r,f(turning_point)))
    else:
        return interval(min(l,r),max(l,r))

Vollständiger Antwortcode:

HW_SOURCE_FILE = __file__


def mobile(left, right):
    """Construct a mobile from a left arm and a right arm."""
    assert is_arm(left), "left must be a arm"
    assert is_arm(right), "right must be a arm"
    return ['mobile', left, right]


def is_mobile(m):
    """Return whether m is a mobile."""
    return type(m) == list and len(m) == 3 and m[0] == 'mobile'


def left(m):
    """Select the left arm of a mobile."""
    assert is_mobile(m), "must call left on a mobile"
    return m[1]


def right(m):
    """Select the right arm of a mobile."""
    assert is_mobile(m), "must call right on a mobile"
    return m[2]


def arm(length, mobile_or_planet):
    """Construct a arm: a length of rod with a mobile or planet at the end."""
    assert is_mobile(mobile_or_planet) or is_planet(mobile_or_planet)
    return ['arm', length, mobile_or_planet]


def is_arm(s):
    """Return whether s is a arm."""
    return type(s) == list and len(s) == 3 and s[0] == 'arm'


def length(s):
    """Select the length of a arm."""
    assert is_arm(s), "must call length on a arm"
    return s[1]


def end(s):
    """Select the mobile or planet hanging at the end of a arm."""
    assert is_arm(s), "must call end on a arm"
    return s[2]


def planet(size):
    """Construct a planet of some size."""
    assert size > 0
    return ['planet', size]


def size(w):
    """Select the size of a planet."""
    assert is_planet(w), 'must call size on a planet'
    "*** YOUR CODE HERE ***"
    return w[1]


def is_planet(w):
    """Whether w is a planet."""
    return type(w) == list and len(w) == 2 and w[0] == 'planet'


def examples():
    t = mobile(arm(1, planet(2)),
               arm(2, planet(1)))
    u = mobile(arm(5, planet(1)),
               arm(1, mobile(arm(2, planet(3)),
                             arm(3, planet(2)))))
    v = mobile(arm(4, t), arm(2, u))
    return (t, u, v)


def total_weight(m):
    """Return the total weight of m, a planet or mobile.

    >>> t, u, v = examples()
    >>> total_weight(t)
    3
    >>> total_weight(u)
    6
    >>> total_weight(v)
    9
    >>> from construct_check import check
    >>> # checking for abstraction barrier violations by banning indexing
    >>> check(HW_SOURCE_FILE, 'total_weight', ['Index'])
    True
    """
    if is_planet(m):
        return size(m)
    else:
        assert is_mobile(m), "must get total weight of a mobile or a planet"
        return total_weight(end(left(m))) + total_weight(end(right(m)))


def balanced(m):
    """Return whether m is balanced.

    >>> t, u, v = examples()
    >>> balanced(t)
    True
    >>> balanced(v)
    True
    >>> w = mobile(arm(3, t), arm(2, u))
    >>> balanced(w)
    False
    >>> balanced(mobile(arm(1, v), arm(1, w)))
    False
    >>> balanced(mobile(arm(1, w), arm(1, v)))
    False
    >>> from construct_check import check
    >>> # checking for abstraction barrier violations by banning indexing
    >>> check(HW_SOURCE_FILE, 'balanced', ['Index'])
    True
    """
    "*** YOUR CODE HERE ***"

    def check_balance(test_arm):
        if is_planet(test_arm[2]):
            weight = total_weight(test_arm[2])
        else:
            if not balanced(test_arm[2]):
                return False
            else:
                weight = total_weight(test_arm[2])
        return length(test_arm), weight

    if check_balance(m[1]):
        left_len, left_weight = check_balance(m[1])
    else:
        return False

    if check_balance(m[2]):
        right_len, right_weight = check_balance(m[2])
    else:
        return False
    if left_len * left_weight == right_len * right_weight:
        return True
    else:
        return False


def totals_tree(m):
    """Return a tree representing the mobile with its total weight at the root.

    >>> t, u, v = examples()
    >>> print_tree(totals_tree(t))
    3
      2
      1
    >>> print_tree(totals_tree(u))
    6
      1
      5
        3
        2
    >>> print_tree(totals_tree(v))
    9
      3
        2
        1
      6
        1
        5
          3
          2
    >>> from construct_check import check
    >>> # checking for abstraction barrier violations by banning indexing
    >>> check(HW_SOURCE_FILE, 'totals_tree', ['Index'])
    True
    """
    "*** YOUR CODE HERE ***"
    if is_planet(m):
        return [m[1]]
    else:
        toal_label = total_weight(m[1][2]) + total_weight(m[2][2])
        return tree(toal_label, [totals_tree(m[1][2]), totals_tree(m[2][2])])


# totals_tree(t)

def replace_leaf(t, find_value, replace_value):
    """Returns a new tree where every leaf value equal to find_value has
    been replaced with replace_value.

    >>> yggdrasil = tree('odin',
    ...                  [tree('balder',
    ...                        [tree('thor'),
    ...                         tree('freya')]),
    ...                   tree('frigg',
    ...                        [tree('thor')]),
    ...                   tree('thor',
    ...                        [tree('sif'),
    ...                         tree('thor')]),
    ...                   tree('thor')])
    >>> laerad = copy_tree(yggdrasil) # copy yggdrasil for testing purposes
    >>> print_tree(replace_leaf(yggdrasil, 'thor', 'freya'))
    odin
      balder
        freya
        freya
      frigg
        freya
      thor
        sif
        freya
      freya
    >>> laerad == yggdrasil # Make sure original tree is unmodified
    True
    """
    "*** YOUR CODE HERE ***"
    if not t:
        return []
    if label(t) == find_value and not branches(t):
        t_branches = list(replace_leaf(branch1, find_value, replace_value) for branch1 in branches(t))
        return tree(replace_value, t_branches)
    else:
        t_branches = list(replace_leaf(branch1, find_value, replace_value) for branch1 in branches(t))
        return tree(label(t), t_branches)


def preorder(t):
    """Return a list of the entries in this tree in the order that they
    would be visited by a preorder traversal (see problem description).

    >>> numbers = tree(1, [tree(2), tree(3, [tree(4), tree(5)]), tree(6, [tree(7)])])
    >>> preorder(numbers)
    [1, 2, 3, 4, 5, 6, 7]
    >>> preorder(tree(2, [tree(4, [tree(6)])]))
    [2, 4, 6]
    """
    "*** YOUR CODE HERE ***"
    target = []
    target.append(label(t))
    for t_branch in branches(t):
        target += preorder(t_branch)
    return target


def has_path(t, phrase):
    """Return whether there is a path in a tree where the entries along the path
    spell out a particular phrase.

    >>> greetings = tree('h', [tree('i'),
    ...                        tree('e', [tree('l', [tree('l', [tree('o')])]),
    ...                                   tree('y')])])
    >>> print_tree(greetings)
    h
      i
      e
        l
          l
            o
        y
    >>> has_path(greetings, 'h')
    True
    >>> has_path(greetings, 'i')
    False
    >>> has_path(greetings, 'hi')
    True
    >>> has_path(greetings, 'hello')
    True
    >>> has_path(greetings, 'hey')
    True
    >>> has_path(greetings, 'bye')
    False
    """
    assert len(phrase) > 0, 'no path for empty phrases.'
    "*** YOUR CODE HERE ***"

    # 检查首项
    i = 1
    find_setence = preorder(t)
    if phrase[0] != find_setence[0]:
        return False
    else:
        if i == len(phrase):
            return True
    # 查找后续部分
    for alpha in find_setence[1:]:
        if alpha == phrase[i]:
            i += 1
            if i == len(phrase):
                return True
    return False


def interval(a, b):
    """Construct an interval from a to b."""
    return [a, b]


def lower_bound(x):
    """Return the lower bound of interval x."""
    "*** YOUR CODE HERE ***"
    return x[0]


def upper_bound(x):
    """Return the upper bound of interval x."""
    "*** YOUR CODE HERE ***"
    return x[1]


def str_interval(x):
    """Return a string representation of interval x.
    """
    return '{0} to {1}'.format(lower_bound(x), upper_bound(x))


def add_interval(x, y):
    """Return an interval that contains the sum of any value in interval x and
    any value in interval y."""
    lower = lower_bound(x) + lower_bound(y)
    upper = upper_bound(x) + upper_bound(y)
    return interval(lower, upper)


from inspect import isfunction


def mul_interval(x, y):
    """Return the interval that contains the product of any value in x and any
    value in y."""
    # if isfunction(x):
    #     p1 = x(0) * y(0)
    #     p2 = x(0) * y(1)
    #     p3 = x(1) * y(0)
    #     p4 = x(1) * y(1)
    #     return lambda x: min(p1, p2, p3, p4) if x == 0 else max(p1, p2, p3, p4)
    # else:
    #     p1 = x[0]*y[0]
    #     p2 = x[0] * y[1]
    #     p3 = x[1] * y[0]
    #     p4 = x[1] * y[1]
    #     return [min(p1, p2, p3, p4), max(p1, p2, p3, p4)]
    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 interval(min(p1, p2, p3, p4), max(p1, p2, p3, p4))


def sub_interval(x, y):
    """Return the interval that contains the difference between any value in x
    and any value in y."""
    "*** YOUR CODE HERE ***"
    return interval(lower_bound(x) - upper_bound(y), upper_bound(x) - lower_bound(y))


def div_interval(x, y):
    """Return the interval that contains the quotient of any value in x divided by
    any value in y. Division is implemented as the multiplication of x by the
    reciprocal of y."""
    "*** YOUR CODE HERE ***"
    # assert lower_bound(y) >0 or upper_bound(y)<0, "AssertionError!"
    # reciprocal_y = interval(1 / upper_bound(y), 1 / lower_bound(y))
    # return mul_interval(x, reciprocal_y)
    assert 0 < lower_bound(y) or 0 > upper_bound(y)
    reciprocal_y = interval(1 / upper_bound(y), 1 / lower_bound(y))
    return mul_interval(x, reciprocal_y)


def multiple_references_explanation():
    return """The multiple reference problem..."""


def quadratic(x, a, b, c):
    """Return the interval that is the range of the quadratic defined by
    coefficients a, b, and c, for domain interval x.

    >>> str_interval(quadratic(interval(0, 2), -2, 3, -1))
    '-3 to 0.125'
    >>> str_interval(quadratic(interval(1, 3), 2, -3, 1))
    '0 to 10'
    """
    "*** YOUR CODE HERE ***"
    def f(t):
        return a * t * t + b * t + c

    l,r=f(lower_bound(x)),f(upper_bound(x))
    turning_point = -b / (2 * a)

    if upper_bound(x)>turning_point>lower_bound(x):
        return interval(min(l,r,f(turning_point)),max(l,r,f(turning_point)))
    else:
        return interval(min(l,r),max(l,r))
    # if not isfunction(x):
    #     x1 = x
    # else:
    #     x1 = [x(0), x(1)]
    #
    # turning_point = -b / (2 * a)
    #
    # if lower_bound(x) < turning_point < upper_bound(x):
    #     if a > 0:
    #         if not isfunction(x):
    #             return [f(turning_point), max(f(x1[0]), f(x1[1]))]
    #         else:
    #             return lambda x:f(turning_point) if x==0 else max(f(x1[0]), f(x1[1]))
    #     else:
    #         if not isfunction(x):
    #             return [min(f(x1[0]), f(x1[1])), f(turning_point)]
    #         else:
    #             return lambda x:  min(f(x1[0]), f(x1[1])) if x == 0 else f(turning_point)
    # else:
    #     if not isfunction(x):
    #         return [min(f(x1[0]), f(x1[1])), max(f(x1[0]), f(x1[1]))]
    #     else:
    #         return lambda x:min(f(x1[0]), f(x1[1]))if x==0 else max(f(x1[0]), f(x1[1]))



def par1(r1, r2):
    return div_interval(mul_interval(r1, r2), add_interval(r1, r2))


def par2(r1, r2):
    one = interval(1, 1)
    rep_r1 = div_interval(one, r1)
    rep_r2 = div_interval(one, r2)
    return div_interval(one, add_interval(rep_r1, rep_r2))


def check_par():
    """Return two intervals that give different results for parallel resistors.

    >>> r1, r2 = check_par()
    >>> x = par1(r1, r2)
    >>> y = par2(r1, r2)
    >>> lower_bound(x) != lower_bound(y) or upper_bound(x) != upper_bound(y)
    True
    """
    r1 = interval(2, 1)  # Replace this line!
    r2 = interval(2, 1)  # Replace this line!
    return r1, r2


# Tree ADT

def tree(label, branches=[]):
    """Construct a tree with the given label value and a list of branches."""
    for branch in branches:
        assert is_tree(branch), 'branches must be trees'
    return [label] + list(branches)


def label(tree):
    """Return the label value of a tree."""
    return tree[0]


def branches(tree):
    """Return the list of branches of the given tree."""
    return tree[1:]


def is_tree(tree):
    """Returns True if the given tree is a tree, and False otherwise."""
    if type(tree) != list or len(tree) < 1:
        return False
    for branch in branches(tree):
        if not is_tree(branch):
            return False
    return True


def is_leaf(tree):
    """Returns True if the given tree's list of branches is empty, and False
    otherwise.
    """
    return not branches(tree)


def print_tree(t, indent=0):
    """Print a representation of this tree in which each node is
    indented by two spaces times its depth from the root.

    >>> print_tree(tree(1))
    1
    >>> print_tree(tree(1, [tree(2)]))
    1
      2
    >>> numbers = tree(1, [tree(2), tree(3, [tree(4), tree(5)]), tree(6, [tree(7)])])
    >>> print_tree(numbers)
    1
      2
      3
        4
        5
      6
        7
    """
    print('  ' * indent + str(label(t)))
    for b in branches(t):
        print_tree(b, indent + 1)


def copy_tree(t):
    """Returns a copy of t. Only for testing purposes.

    >>> t = tree(5)
    >>> copy = copy_tree(t)
    >>> t = tree(6)
    >>> print_tree(copy)
    5
    """
    return tree(label(t), [copy_tree(b) for b in branches(t)])

Guess you like

Origin blog.csdn.net/2301_79140115/article/details/134929490