这次作业难度不小,第一个作业hw1还好,第二个全部都可以使用comprehension完成,但要小心返回值,还有深入理解本课程中的vector的概念。第三个作业难度不大,但一不小心就做错了,一个原因是grader不够智能,另一个原因就是细节问题了,比如某个函数的参数必须是set而不能是list。
这次作业总共花了大约7个小时,Making me gong Nut! 不过还学到了提交作业时的一个技巧,就是:
C:\Python33\python C:\Python33\submit_politics_lab.py --verbose
下面是三个子作业的代码:
#hw1 # Please fill out this stencil and submit using the provided submission script. from GF2 import one ## Problem 1 p1_u = [ 0, 4] p1_v = [-1, 3] p1_v_plus_u = [-1,7] p1_v_minus_u = [-1,-1] p1_three_v_minus_two_u = [-3,1] ## Problem 2 p2_u = [-1, 1, 1] p2_v = [ 2, -1, 5] p2_v_plus_u = [1,0,6] p2_v_minus_u = [3,-2,4] p2_two_v_minus_u = [5,-3,9] p2_v_plus_two_u = [0,1,7] ## Problem 3 # Write your answer using GF2's one instead of the number 1 p3_vector_sum_1 = [one,0,0] p3_vector_sum_2 = [0,one,one] ## Problem 4 # Please express your solution as a set of the letters corresponding to the solutions. # For example, {'a','b','c'} is the subset consisting of: # a (1100000), b (0110000), and c (0011000). # Leave an empty set if it cannot be expressed in terms of the other vectors. u_0010010 = {'c','d','e'} u_0100010 = {'b','c','d','e'} ## Problem 5 # Use the same format as the previous problem v_0010010 = {'c','d'} v_0100010 = set() ## Problem 6 uv_a = sum([5,0]) uv_b = sum([x*y for x,y in zip([0,1],[12345,6])]) uv_c = sum([x*y for x,y in zip([-1,3],[5,7])]) uv_d =sum([-1/2,-1/2]) ## Problem 7 # use 'one' instead of '1' x_gf2 = [one,0,0,0] ## Problem 8 v1 = [2,3,-4,1] v2 = [1,-5,2,0] v3 = [4,1,-1,-1]第二个:
在这个作业中comprehension很重要
#vec.py def getitem(v,d): "Returns the value of entry d in v" assert d in v.D return v.f[d] if d in v.f else 0 def setitem(v,d,val): "Set the element of v with label d to be val" assert d in v.D v.f[d]=val def equal(u,v): "Returns true iff u is equal to v" assert u.D == v.D return {getitem(u,x)==getitem(v,x) for x in v.D}=={True} def add(u,v): "Returns the sum of the two vectors" assert u.D == v.D return Vec(u.D,{x:getitem(u,x)+getitem(v,x) for x in v.D}) def dot(u,v): "Returns the dot product of the two vectors" assert u.D == v.D return sum([getitem(u,x)*getitem(v,x) for x in v.D]) def scalar_mul(v, alpha): "Returns the scalar-vector product alpha times v" return Vec(v.D,{x:alpha*v.f[x] for x in v.f.keys()}) def neg(v): "Returns the negation of a vector" return Vec(v.D,{x:-y for x,y in v.f.items()}) ##### NO NEED TO MODIFY BELOW HERE ##### class Vec: """ A vector has two fields: D - the domain (a set) f - a dictionary mapping (some) domain elements to field elements elements of D not appearing in f are implicitly mapped to zero """ def __init__(self, labels, function): self.D = labels self.f = function __getitem__ = getitem __setitem__ = setitem __neg__ = neg __rmul__ = scalar_mul #if left arg of * is primitive, assume it's a scalar def __mul__(self,other): #If other is a vector, returns the dot product of self and other if isinstance(other, Vec): return dot(self,other) else: return NotImplemented # Will cause other.__rmul__(self) to be invoked def __truediv__(self,other): # Scalar division return (1/other)*self __add__ = add def __radd__(self, other): "Hack to allow sum(...) to work with vectors" if other == 0: return self def __sub__(a,b): "Returns a vector which is the difference of a and b." return a+(-b) __eq__ = equal def __str__(v): "pretty-printing" try: D_list = sorted(v.D) except TypeError: D_list = sorted(v.D, key=hash) numdec = 3 wd = dict([(k,(1+max(len(str(k)), len('{0:.{1}G}'.format(v[k], numdec))))) if isinstance(v[k], int) or isinstance(v[k], float) else (k,(1+max(len(str(k)), len(str(v[k]))))) for k in D_list]) # w = 1+max([len(str(k)) for k in D_list]+[len('{0:.{1}G}'.format(value,numdec)) for value in v.f.values()]) s1 = ''.join(['{0:>{1}}'.format(k,wd[k]) for k in D_list]) s2 = ''.join(['{0:>{1}.{2}G}'.format(v[k],wd[k],numdec) if isinstance(v[k], int) or isinstance(v[k], float) else '{0:>{1}}'.format(v[k], wd[k]) for k in D_list]) return "\n" + s1 + "\n" + '-'*sum(wd.values()) +"\n" + s2 def __repr__(self): return "Vec(" + str(self.D) + "," + str(self.f) + ")" def copy(self): "Don't make a new copy of the domain D" return Vec(self.D, self.f.copy())
第三个:
使用带lambda的max可以用到
voting_data = list(open("voting_record_dump109.txt")) ## Task 1 def create_voting_dict(): """ Input: None (use voting_data above) Output: A dictionary that maps the last name of a senator to a list of numbers representing the senator's voting record. Example: >>> create_voting_dict()['Clinton'] [-1, 1, 1, 1, 0, 0, -1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1] This procedure should return a dictionary that maps the last name of a senator to a list of numbers representing that senator's voting record, using the list of strings from the dump file (strlist). You will need to use the built-in procedure int() to convert a string representation of an integer (e.g. '1') to the actual integer (e.g. 1). You can use the split() procedure to split each line of the strlist into a list; the first element of the list will be the senator's name, the second will be his/her party affiliation (R or D), the third will be his/her home state, and the remaining elements of the list will be that senator's voting record on a collection of bills. A "1" represents a 'yea' vote, a "-1" a 'nay', and a "0" an abstention. The lists for each senator should preserve the order listed in voting data. """ return {x.split()[0]:[int(y) for y in x.split()[3:]] for x in voting_data} ## Task 2 def policy_compare(sen_a, sen_b, voting_dict): """ Input: last names of sen_a and sen_b, and a voting dictionary mapping senator names to lists representing their voting records. Output: the dot-product (as a number) representing the degree of similarity between two senators' voting policies Example: >>> voting_dict = {'Fox-Epstein':[-1,-1,-1,1],'Ravella':[1,1,1,1]} >>> policy_compare('Fox-Epstein','Ravella', voting_dict) -2 """ return sum([x*y for (x,y) in zip(voting_dict[sen_a],voting_dict[sen_b])]) ## Task 3 def most_similar(sen, voting_dict): """ Input: the last name of a senator, and a dictionary mapping senator names to lists representing their voting records. Output: the last name of the senator whose political mindset is most like the input senator (excluding, of course, the input senator him/herself). Resolve ties arbitrarily. Example: >>> vd = {'Klein': [1,1,1], 'Fox-Epstein': [1,-1,0], 'Ravella': [-1,0,0]} >>> most_similar('Klein', vd) 'Fox-Epstein' Note that you can (and are encouraged to) re-use you policy_compare procedure. """ max_sen=sen max_sim=-len(voting_dict[sen]) for x in voting_dict.keys(): if not x==sen: sim_x=policy_compare(sen, x, voting_dict) if sim_x>max_sim: max_sim=sim_x max_sen=x return max_sen ## Task 4 def least_similar(sen, voting_dict): """ Input: the last name of a senator, and a dictionary mapping senator names to lists representing their voting records. Output: the last name of the senator whose political mindset is least like the input senator. Example: >>> vd = {'Klein': [1,1,1], 'Fox-Epstein': [1,-1,0], 'Ravella': [-1,0,0]} >>> least_similar('Klein', vd) 'Ravella' """ min_sen=sen sim_x=0 min_sim=len(voting_dict[sen]) for x in voting_dict.keys(): if not x==sen: sim_x=policy_compare(sen, x, voting_dict) if sim_x<min_sim: min_sim=sim_x min_sen=x return min_sen ## Task 5 most_like_chafee = 'Jeffords' least_like_santorum = 'Feingold' # Task 6 def find_average_similarity(sen, sen_set, voting_dict): """ Input: the name of a senator, a set of senator names, and a voting dictionary. Output: the average dot-product between sen and those in sen_set. Example: >>> vd = {'Klein': [1,1,1], 'Fox-Epstein': [1,-1,0], 'Ravella': [-1,0,0]} >>> find_average_similarity('Klein', {'Fox-Epstein','Ravella'}, vd) -0.5 """ sum=0 for x in sen_set: sum+=policy_compare(sen, x, voting_dict) return sum/len(sen_set) most_average_Democrat = 'Smith' # give the last name (or code that computes the last name) # Task 7 def find_average_record(sen_set, voting_dict): """ Input: a set of last names, a voting dictionary Output: a vector containing the average components of the voting records of the senators in the input set Example: >>> voting_dict = {'Klein': [-1,0,1], 'Fox-Epstein': [-1,-1,-1], 'Ravella': [0,0,1]} >>> find_average_record({'Fox-Epstein','Ravella'}, voting_dict) [-0.5, -0.5, 0.0] """ t=[] tmp=sen_set.pop() sen_set=sen_set|{tmp} for x in range(len(voting_dict[tmp])): t.append(sum([voting_dict[y][x]for y in sen_set])/len(sen_set)) return t #voting_dict=create_voting_dict() #democrats=[x.split()[0] for x in voting_data if x.split()[1]=='D'] #average_Democrat_record = set(find_average_record(democrats, voting_dict)) average_Democrat_record = [-0.16279069767441862, -0.23255813953488372, 1.0, 0.8372093023255814, 0.9767441860465116, -0.13953488372093023, -0.9534883720930233, 0.813953488372093, 0.9767441860465116, 0.9767441860465116, 0.9069767441860465, 0.7674418604651163, 0.6744186046511628, 0.9767441860465116, -0.5116279069767442, 0.9302325581395349, 0.9534883720930233, 0.9767441860465116, -0.3953488372093023, 0.9767441860465116, 1.0, 1.0, 1.0, 0.9534883720930233, -0.4883720930232558, 1.0, -0.32558139534883723, -0.06976744186046512, 0.9767441860465116, 0.8604651162790697, 0.9767441860465116, 0.9767441860465116, 1.0, 1.0, 0.9767441860465116, -0.3488372093023256, 0.9767441860465116, -0.4883720930232558, 0.23255813953488372, 0.8837209302325582, 0.4418604651162791, 0.9069767441860465, -0.9069767441860465, 1.0, 0.9069767441860465, -0.3023255813953488] # (give the vector) # average_Democrat_record = [-0.162791, -0.232558, 1.000000, 0.837209, 0.976744, -0.139535, -0.953488, 0.813953, 0.976744, 0.976744, 0.906977, 0.767442, 0.674419, 0.976744, -0.511628, 0.930233, 0.953488, 0.976744, -0.395349, 0.976744, 1.000000, 1.000000, 1.000000, 0.953488, -0.488372, 1.000000, -0.325581, -0.069767, 0.976744, 0.860465, 0.976744, 0.976744, 1.000000, 1.000000, 0.976744, -0.348837, 0.976744, -0.488372, 0.232558, 0.883721, 0.441860, 0.906977, -0.906977, 1.000000, 0.906977, -0.302326] # Task 8 def bitter_rivals(voting_dict): """ Input: a dictionary mapping senator names to lists representing their voting records Output: a tuple containing the two senators who most strongly disagree with one another. Example: >>> voting_dict = {'Klein': [-1,0,1], 'Fox-Epstein': [-1,-1,-1], 'Ravella': [0,0,1]} >>> bitter_rivals(voting_dict) ('Fox-Epstein', 'Ravella') """ tx=0 ty=0 sums=len(voting_dict[list(voting_dict.keys())[0]]) for x in voting_dict.keys(): y=least_similar(x, voting_dict) min_s=policy_compare(x, y, voting_dict) if min_s<sums: sums=min_s tx=x ty=y return (tx, ty)