Основната ви цел е да напишете функция със следните име и аргументи: module_game(m1, m2)
.
Входни данни: m1
и m2
са модули.
Резултат: n-торка с 2 елемента, с броя на точките събрали първия и втория модул при играта, която е описана по-долу в условието.
Предварително известни факти:
{} {'baba': 5} {'a': 42, 'b': -69, 'x': 4360000634}
[] [()] [(1023, 4095, 8191), (), (), (0, 17), (3,)]
Правила на играта:
За атрибути по-надолу ще смятаме само тези реални атрибути на модулите, които не започват с _
(долна черта, подчертавка)
Всеки модул получава 1 точка за всяка функция в него, чието име започва с последните 3 символа на друга функция в същия модул. Ето пример за част от модул, която ни гарантира две точки по този параграф:
s = "baba"
def destroy(x, y):
print "Destroyed."
return 0
def roy_keen(x, y):
print "Babyboy."
return 0
def roy_boss(x, y):
print "Holy-shmolly, that is tea!"
return 0
Всеки модул получава 1 точка, за всеки списък в него, за който средното-аритметично на сумите от квадратите на n-орките в него е по-голямо от средно-аритметичното на всички цели числа в другия модул. Ако някоя n-торка е празна, нейната сума може да се смята за 0. Ако един списък е празен, неговото аритметично също може да се смята за 0.
Пример: имаме списъка [(1, 2), (), (8, -2), (-1, 5, -1)]
. Сумите на квадратите на n-торките са съответно: 5, 0, 68, 27. Средното им аритметично е точно 25.
По 1 точка получава модул, за всяка функция в него, която удовлетворява следните условия:
Пример за такава функция: def f(x, y): return x*y
3 точки носи на модул всеки речник, за който:
Пример за такъв речник: {'Chapman': 11, 'Charlie': 99, 'GILLIAM': 102, 'Idle': 666, 'Jones': 883, 'Palin': 55, 'Cleese': 1101}
def module_game(m1, m2):
return (assess(m1, m2), assess(m2, m1))
def assess(mod, mod_other):
return sum((
end3_funcs(mod),
avg_lists(mod, mod_other),
commutatives(mod),
3*monty_python_dicts(mod),
))
def valid_attributes(mod):s
return (attr for attr in dir(mod) if not attr.startswith('_'))
sum
приема последователност и му даваме n-торка: sum((
valid_attributes
няма нужда да връща списък, може да ползваме generator expressiondef end3_funcs(mod):
func_names = [attr for attr in valid_attributes(mod) if callable(getattr(mod, attr))]
count = 0
for func in func_names:
if len(func) < 3: continue
start = func[:3]
if any((otherfunc.endswith(start) for otherfunc in func_names if func != otherfunc)):
count += 1
return count
func_names
е списък (или „за влагането на генератори“)?any
?g = (x*x for x in xrange(4))
for a in g:
for b in g:
print (a, b)
(0, 1)
(0, 4)
(0, 9)
g.next()
във външния цикъл, a
, става 0g.next()
във вътрешния циъкл, b
, става 1g.next()
във вътрешния циъкл, b
, става 4g.next()
във вътрешния циъкл, b
, става 9g = [x for x in xrange(4)]
g = (x*x for x in xrange(4))
g_inner = (x*x for x in xrange(4))
for a in (x*x for x in xrange(4)):
for b in (x*x for x in xrange(4)):
print (a, b)
def gen_sq(n):
for x in xrange(n):
yield x*x
def gen_sq2(n):
return (x*x for x in xrange(n))
def avg_lists(mod, other):
other_ints = [getattr(other, attr) for attr in valid_attributes(other)
if isinstance(getattr(other, attr), (int, long))]
other_sum, other_len = sum(other_ints), len(other_ints)
mod_lists = (getattr(mod, attr) for attr in valid_attributes(mod)
if isinstance(getattr(mod, attr), list))
count = 0
square = lambda x: x*x
for l in mod_lists:
jingled_items = [sum(imap(square, tup)) for tup in l]
jingled_sum, jingled_len = sum(jingled_items), len(jingled_items)
# don't use floats
# we know that always both the sum and the len are non-negative
# except that other_sum could be negative
if jingled_sum > 0 and 0 == other_len:
count += 1
elif jingled_len == 0 and other_sum < 0:
count += 1
elif jingled_sum*other_len > jingled_len*other_sum:
count += 1
return count
def commutatives(mod):
# този път ф-ии--не имена
funcs = [getattr(mod, attr) for attr in valid_attributes(mod)
if callable(getattr(mod, attr))]
count = 0
for func in funcs:
if func(0,0) == 0 and\
all((func(i, j) == func(j, i)
for i in xrange(0, 99) for j in xrange(i+1, 100))):
count += 1
return count
def commutatives(mod):
# този път ф-ии--не имена
funcs = [getattr(mod, attr) for attr in valid_attributes(mod)
if callable(getattr(mod, attr))]
count = 0
for func in funcs:
point_commutative = ( func(i, j) == func(j, i)
for i in xrange(0, 99) for j in xrange(i+1, 100))
if func(0,0) == 0 and\
all(point_commutative):
count += 1
return count
any(iterable)
— връща истина, ако поне един от елементите на iterable
е истина.all(iterable)
— връща истина, ако всички елементи на iterable
са истина.>>>people = ('God', 'Monty', 'Pinkie', 'Mityo')
>>>wannaplay = lambda name: 'x' in name
>>>friends = lambda x,y: x[0] == y[0] and x != y
>>>capitalised = lambda x: x[0].isupper()
>>>print any(map(wannaplay, people))
False # Nobody wants to play
>>>print any([friends(name, 'Mityo') for name in people])
True # Monty
>>>print all(imap(capitalised, people))
True
>>>print all((friends(name, 'Mityo') for name in people))
False
def monty_python_dicts(mod):
WANTED = set(['chapman', 'cleese', 'gilliam', 'idle', 'jones', 'palin'])
dicts = [getattr(mod, attr) for attr in valid_attributes(mod) if isinstance(getattr(mod, attr), dict)]
count = 0
def make_strange_cmp(dict_):
def strange_cmp(x, y):
x, y = dict_[x], dict_[y]
sx, sy = str(sx).lstrip('-'), str(sx).lstrip('-')
if (len(sx) != len(sy)):
return cmp(len(sx), len(sy))
return cmp(math.tan(math.radians(x)), math.tan(math.radians(y)))
for d in dicts:
ordered = sorted(d, cmp=make_strange_cmp(d), reverse=True)
if set(imap(string.lower, ordered[:6])) == WANTED:
count += 1
return count
def monty_python_dicts(mod):
WANTED = set(['chapman', 'cleese', 'gilliam', 'idle', 'jones', 'palin'])
dicts = [getattr(mod, attr) for attr in valid_attributes(mod)
if isinstance(getattr(mod, attr), dict)]
count = 0
# DSU, DSU
def make_decorate(dict_):
def decorate(key):
value = dict_[key]
svalue = str(value).lstrip('-')
return (len(svalue), math.tan(math.radians(value)))
return decorate
for d in dicts:
ordered = sorted(d, key=make_decorate(d), reverse=True)
if set(imap(string.lower, ordered[:6])) == WANTED:
count += 1
return count
names = ['Monty Python', 'Bilbo Baggins', 'Mityo Python']
# 2 пъти split
# цялото се вика n*log(n) пъти
def names_cmp(n1, n2):
first1, last1 = n1.split()
first2, last2 = n2.split()
if last1 != last2:
return cmp(last1, last2)
else:
return cmp(first1, first2)
names.sort(names_cmp)
# (('Python', 'Monty'), 'Monty Python')
decorated = zip([tuple(reversed(name.split())) for name in names], names)
decorated.sort()
undecorated = [value for (decor, value) in decorated]
print undecorated
['Bilbo Baggins', 'Mityo Python', 'Monty Python']
zip
взима няколко списъка и връща списък от n-орки с поредните елементи на списъцитеready = sorted(names, key = lambda name: tuple(reversed(name.split())))
или:
def decorate(name):
first, last = name.split()
return last, first
ready = sorted(names, key = decorate)
key
параметъра на sort
и sorted
key
очаква функция с един аргумент и сортира по нейната стойност, а не по стойността на елементите на поредицатаkey