# Work class Worker: greeting = 'Sir' def __init__(self): self.elf = Worker def work(self): return self.greeting + ', I work' def __repr__(self): return Bourgeoisie.greeting class Bourgeoisie(Worker): greeting = 'Peon' def work(self): print(Worker.work(self)) return 'My job is to gather wealth' jack = Worker() john = Bourgeoisie() jack.greeting = 'Maam' def work(): """Working. >>> Worker().work() 'Sir, I work' >>> jack Peon >>> jack.work() 'Maam, I work' >>> john.work() Peon, I work 'My job is to gather wealth' >>> john.elf.work(john) 'Peon, I work' """ # Built-in functions & comprehensions def min_abs_indices(s): """Indices of all elements in list s that have the smallest absolute value. >>> min_abs_indices([-4, -3, -2, 3, 2, 4]) [2, 4] >>> min_abs_indices([1, 2, 3, 4, 5]) [0] """ min_abs = min(map(abs, s)) return list(filter(lambda i: abs(s[i]) == min_abs, range(len(s)))) # OR return [i for i in range(len(s)) if abs(s[i]) == min_abs] def largest_adj_sum(s): """Largest sum of two adjacent elements in a list s. >>> largest_adj_sum([-4, -3, -2, 3, 2, 4]) 6 >>> largest_adj_sum([-4, 3, -2, -3, 2, -4]) 1 """ return max([x + y for x, y in zip(s[:-1], s[1:])]) # OR return max([s[i] + s[i + 1] for i in range(len(s) - 1)]) # OR return max(map(lambda i: s[i] + s[i + 1], range(len(s) - 1))) def digit_dict(s): """Map each digit d to the lists of elements in s that end with d. >>> digit_dict([5, 8, 13, 21, 34, 55, 89]) {1: [21], 3: [13], 4: [34], 5: [5, 55], 8: [8], 9: [89]} """ return {i: [x for x in s if x % 10 == i] for i in range(10) if any([x % 10 == i for x in s])} # OR last_digits = list(map(lambda x: x % 10, s)) return {i: [x for x in s if x % 10 == i] for i in range(10) if i in last_digits} def all_have_an_equal(s): """Does every element equal some other element in s? >>> all_have_an_equal([-4, -3, -2, 3, 2, 4]) False >>> all_have_an_equal([4, 3, 2, 3, 2, 4]) True """ return min([sum([1 for y in s if x == y]) for x in s]) > 1 # OR return all([s[i] in s[:i] + s[i+1:] for i in range(len(s))]) # OR return all(map(lambda x: s.count(x) > 1, s)) # Linked lists def ordered(s, key=lambda x: x): """Is Link s ordered? >>> ordered(Link(1, Link(3, Link(4)))) True >>> ordered(Link(1, Link(4, Link(3)))) False >>> ordered(Link(1, Link(-3, Link(4)))) False >>> ordered(Link(1, Link(-3, Link(4))), key=abs) True >>> ordered(Link(-4, Link(-1, Link(3)))) True >>> ordered(Link(-4, Link(-1, Link(3))), key=abs) False """ if s is Link.empty or s.rest is Link.empty: return True elif key(s.first) > key(s.rest.first): return False else: return ordered(s.rest) def merge(s, t): """Return a sorted Link containing the elements of sorted s & t. >>> a = Link(1, Link(5)) >>> b = Link(1, Link(4)) >>> merge(a, b) Link(1, Link(1, Link(4, Link(5)))) >>> a Link(1, Link(5)) >>> b Link(1, Link(4)) """ if s is Link.empty: return t elif t is Link.empty: return s elif s.first <= t.first: return Link(s.first, merge(s.rest, t)) else: return Link(t.first, merge(s, t.rest)) def merge_in_place(s, t): """Return a sorted Link containing the elements of sorted s & t. >>> a = Link(1, Link(5)) >>> b = Link(1, Link(4)) >>> merge_in_place(a, b) Link(1, Link(1, Link(4, Link(5)))) >>> a Link(1, Link(1, Link(4, Link(5)))) >>> b Link(1, Link(4, Link(5))) """ if s is Link.empty: return t elif t is Link.empty: return s elif s.first <= t.first: s.rest = merge_in_place(s.rest, t) return s else: t.rest = merge_in_place(s, t.rest) return t class Link: """A linked list. >>> Link(1, Link(2, Link(3))) Link(1, Link(2, Link(3))) >>> s = Link(1, Link(Link(2, Link(3)), Link(4))) >>> s Link(1, Link(Link(2, Link(3)), Link(4))) >>> print(s) <1 <2 3> 4> """ empty = () def __init__(self, first, rest=empty): assert rest is Link.empty or isinstance(rest, Link) self.first = first self.rest = rest def __repr__(self): if self.rest: rest_repr = ', ' + repr(self.rest) else: rest_repr = '' return 'Link(' + repr(self.first) + rest_repr + ')' def __str__(self): string = '<' while self.rest is not Link.empty: string += str(self.first) + ' ' self = self.rest return string + str(self.first) + '>'