Прикреплённый файл «contest_86.n.py»
Загрузка 1 #!/usr/bin/env python3
2 ClDt='''
3 02_Conditionals 2017-10-13
4 03_DataTypes 2017-10-20
5 04_Functions 2017-10-27
6 05_Lists 2017-11-03
7 06_Strings 2017-11-10
8 07_Dicts 2017-11-17
9 08_Classes 2017-11-24
10 09_Overload 2017-12-01
11 10_InheritanceDescriptors 2017-12-08
12 11_Exceptions 2017-12-15
13 '''
14
15 ClTs='''
16 02_Conditionals HelloWorld
17 02_Conditionals AndOr
18 02_Conditionals DotsInCircle
19 02_Conditionals IntPalindrome
20 02_Conditionals AnyPower
21 03_DataTypes ParallelSegments
22 03_DataTypes SectionShuffle
23 03_DataTypes SecondMax
24 03_DataTypes PaidStairs
25 04_Functions Det4x4
26 04_Functions EvalFunction
27 04_Functions IterPi
28 04_Functions GenTriseq
29 05_Lists FilterList
30 05_Lists LookSay
31 05_Lists DodgsonDet
32 05_Lists SpiralDigits
33 06_Strings YieldFrom
34 06_Strings MaxInt
35 06_Strings PatternFind
36 07_Dicts ThreeSquares
37 07_Dicts MostPopular
38 07_Dicts DungeonMap
39 07_Dicts FarGalaxy
40 08_Classes DummyClass
41 08_Classes CountInt
42 08_Classes SharedBrain
43 08_Classes NormalDouble
44 09_Overload SimpleVector
45 09_Overload StrangeDots
46 09_Overload UnaryNumber
47 09_Overload TrianglesCmp
48 10_InheritanceDescriptors MegaStroka
49 10_InheritanceDescriptors GuessABC
50 10_InheritanceDescriptors SemDescriptor
51 11_Exceptions BoldCalc
52 '''
53 # ~/Загрузки/contest_86_20171219131616.tgz
54 # argv: ~/Загрузки/contest_86_20171221183309.tgz
55
56 # Run selection
57 # Download all runs
58 # Download selected runs (20)
59 # X Download OK runs
60 # Download OK and PR runs
61 # Download OK, PR, RJ, IG, PD, DQ runs
62 #File name pattern
63 # Use Contest Id
64 # X Use run number
65 # Use user Id
66 # X Use user Login
67 # Use user Name
68 # X Use problem short name
69 # Use programming language short name
70 # X Use submit time
71 # X Use source language or content type suffix
72
73 import time
74 def mkt(st):
75 return time.mktime(time.strptime(st,"%Y%m%d%H%M%S"))
76
77 ClDt = {l:mkt(d[:4]+d[5:7]+d[8:10]+"000000") for l,d in (s.split() for s in ClDt.split("\n") if s)}
78 TsCl = {t:l for l,t in (s.split() for s in ClTs.split('\n') if s)}
79 TsDt = {t:ClDt[l] for t,l in TsCl.items()}
80
81 import sys
82 import os
83 import pickle
84 from collections import defaultdict as table
85
86 def table_list(): return table(list)
87 def table_dict(): return table(dict)
88 def table_set(): return table(set)
89
90 CF = sys.argv[1]
91 for sfx in sys.argv[2:]:
92 CFDELETE = "{}.{}.tmp".format(CF,sfx)
93 if os.path.isfile(CFDELETE):
94 os.unlink(CFDELETE)
95
96 CFRes = CF+".All.tmp"
97 if os.path.isfile(CFRes):
98 with open(CFRes,"rb") as f:
99 Res = pickle.load(f)
100 else:
101 import tarfile
102 Res = table(set)
103 with tarfile.open(CF,"r") as f:
104 for o in f:
105 if o.isfile():
106 s = o.name
107 # contest_86_20171219131616/000064-Nikscorp-HelloWorld-20170930113002.py
108 ID, *Nick, Task, Date = s.split("/")[-1][:-3].split("-")
109 Nick = "-".join(Nick)
110 Res[Nick].add(Task)
111 with open(CFRes,"wb") as f:
112 pickle.dump(Res,f)
113 Users = {N for N,V in Res.items() if 3*len(V)>2*len(TsDt)}
114 print("# Users: {} total / {} allowed".format(len(Res), len(Users)))
115
116 CFSrc = CF+".Source.tmp"
117 if os.path.isfile(CFSrc):
118 with open(CFSrc,"rb") as f:
119 IDs = pickle.load(f)
120 Src = pickle.load(f)
121 Tab = pickle.load(f)
122 else:
123 import tarfile
124 Src = {}
125 IDs = {}
126 with tarfile.open(CF,"r") as f:
127 for o in f:
128 if o.isfile():
129 s = o.name
130 # contest_86_20171219131616/000064-Nikscorp-HelloWorld-20170930113002.py
131 ID, *Nick, Task, Date = s.split("/")[-1][:-3].split("-")
132 Nick, ID, Date = "-".join(Nick), int(ID), mkt(Date)
133 if Nick not in Users: continue
134 with f.extractfile(o) as df:
135 txt = df.read().decode()
136 Src[ID], IDs[ID] = txt, (Nick, Task, Date)
137 Tab = table(table_set)
138 for ID, (Nick, Task, Date) in IDs.items():
139 Tab[Task][Nick].add(ID)
140
141 with open(CFSrc,"wb") as f:
142 pickle.dump(IDs,f)
143 pickle.dump(Src,f)
144 pickle.dump(Tab,f)
145 print("# Tasks: {}/{}".format(len(IDs),max(IDs)))
146
147 CFPrep = CF+".Prep.tmp"
148 if os.path.isfile(CFPrep):
149 with open(CFPrep,"rb") as f:
150 Prep = pickle.load(f)
151 else:
152 import ast
153 import re
154 import autopep8
155 ra=re.compile(r"'[^']*'")
156 rb=re.compile(r"[\[\]\{\}\(\)\,\ ]+")
157 AstK = ['None ']+[s+' ' for s in dir(ast) if s[0].isalpha()]
158 Prep = {}
159 c, M = -1, int(max(IDs))
160 for ID in sorted(Src):
161 src = Src[ID]
162 if c != int(ID)//100:
163 print(ID)
164 c = int(ID)//100
165 prep = rb.sub(" ",ra.sub("@",ast.dump(ast.parse(src,"ex.py"),annotate_fields=False)))
166 txt = autopep8.fix_code(src)
167 for i,p in enumerate(AstK):
168 prep = prep.replace(p,chr(i+0x21)+" ")
169 Prep[ID] = txt, prep.replace(" ","")
170 with open(CFPrep,"wb") as f:
171 pickle.dump(Prep,f)
172 print("# Total code/prepared: {}/{}".format(sum(len(t) for t,p in Prep.values()), sum(len(p) for t,p in Prep.values())))
173
174 def getdist(id1, id2):
175 return editdistance.eval(Prep[id1][1], Prep[id2][1])*2/(len(Prep[id1][1])+len(Prep[id2][1]))
176
177 def cluster(Heap):
178 l=-1
179 while l!=len(Heap):
180 l = len(Heap)
181 Heap={frozenset.union(*(b for b in Heap if a&b)) for a in Heap}
182 return Heap
183
184 CFPaste = CF+".Paste.tmp"
185 cPaste = 0.01
186 cRew = 0.1
187 minCommon = 7
188 if os.path.isfile(CFPaste):
189 with open(CFPaste,"rb") as f:
190 Paste = pickle.load(f)
191 else:
192 import editdistance
193 Paste = {}
194 for T in Tab:
195 print(T)
196 Us = sorted(Tab[T])
197 P = set()
198 for i in range(len(Us)-1):
199 for j in range(i+1,len(Us)):
200 for ID1 in Tab[T][Us[i]]:
201 for ID2 in Tab[T][Us[j]]:
202 ID1, ID2 = sorted((ID1, ID2))
203 dist = getdist(ID1, ID2)
204 if dist<cPaste:
205 P.add((ID1, ID2, dist))
206 #Paste[T] = {i:min((i1,d) for i1,i2,d in P if i2==i) for i in {j2 for j1,j2,dd in P }}
207 Paste[T] = P,cluster({ frozenset({ i, j }) for i, j, d in P })
208 with open(CFPaste,"wb") as f:
209 pickle.dump(Paste,f)
210
211 def tpasters(T):
212 P = {}
213 for C in Paste[T][1]:
214 H, *L = sorted(C)
215 U, L = IDs[H][0], {IDs[l][0] for l in L if IDs[l][0]!=IDs[H][0]}
216 if not L: continue
217 if len(L) >= minCommon:
218 return None
219 P[(U,H)] = L
220 else:
221 return P
222
223 def ftpasters(T):
224 P = {}
225 for C in Paste[T][1]:
226 H, *L = sorted(C)
227 if {IDs[l][0] for l in L} == {IDs[H][0]}:
228 continue
229 if len(L) >= minCommon:
230 return {}
231 P[(IDs[H][0],H)] = [(IDs[l][0],l) for l in L if IDs[l][0]!=IDs[H][0]]
232 return P
233
234 def fpasters(T):
235 P = {}
236 for C in Paste[T][1]:
237 H, *L = sorted(C)
238 if {IDs[l][0] for l in L} == {IDs[H][0]}:
239 continue
240 P[(IDs[H][0],H)] = [(IDs[l][0],l) for l in L]
241 return P
242
243 print("# Pasters:")
244
245 #{"HelloWorld","DummyClass", "NormalDouble","YieldFrom","SharedBrain","SectionShuffle","ParallelSegments","EvalFunction","CountInt","AndOr","DotsInCircle"}:
246
247 import difflib
248 import editdistance
249
250 def shortest(T,U1,U2):
251 I1 = {int(U1)} if U1.isdigit() else Tab[T][U1]
252 I2 = {int(U2)} if U2.isdigit() else Tab[T][U2]
253 I1,I2 = min(((i1,i2) for i1 in I1 for i2 in I2), key=lambda a: getdist(*a))
254 U1, U2 = IDs[I1][0], IDs[I2][0]
255 return (I1,U1),(I2,U2),getdist(I1,I2)
256
257 def Allpasters():
258 for T in sorted(Paste):
259 P = tpasters(T)
260 print("## {}: {}{}".format(T,sum(len(s) for s in Paste[T][1]),P and "." or "!"))
261 if P:
262 for (U,H),L in sorted(P.items()):
263 print("{} ({}): {}".format(U,H," ".join(L)))
264
265 def Taskpasters(T):
266 for (U,H),L in fpasters(T).items():
267 LL = " ".join("{}({})".format(*l) for l in L)
268 print("{}({}): {}".format(U,H,LL))
269
270 def Taskids(T,U=None):
271 UU = [U] if U else Tab[T]
272 print("# {}: {}".format(T, " ".join("{}({})".format(u,i) for i,u in sorted((i,IDs[i][0]) for U in UU for i in Tab[T][U]))))
273
274 def Userpastes(UU,TT=None):
275 for T in ([TT] if TT else Paste):
276 if not tpasters(T): continue
277 for (U,H),L in fpasters(T).items():
278 for u,i in L:
279 if UU == u:
280 print("{} {}: {}({}) → {}({})".format(T,getdist(H,i),U,H,u,i))
281
282 def Usertasks(U):
283 print(" ".join(sorted(T for T in Tab if Tab[T][U])))
284
285 def Diffsrc(T,U1,U2):
286 (I1,U1),(I2,U2),d = shortest(T,U1,U2)
287 print("{} ({}) / {} ({}): {}\n".format(U1,I1,U2,I2,d),"\n".join(difflib.ndiff(Src[I1].splitlines(),Src[I2].splitlines())))
288
289 AuthIDs = set()
290 TaskExs = set()
291 def Mkpenalty(TaskEx=set(), addAUI=set()):
292 Pen = {}
293 AIDs = AuthIDs | addAUI
294 for T in Tab:
295 if T in TaskEx | TaskExs:
296 Pen[T] = {}
297 continue
298 FP = ftpasters(T)
299 #print(*(i for U,I in FP for u,i in FP[U,I] if u!=U))
300 Pen[T]=set(i for U,I in FP for u,i in FP[U,I])
301 return Pen
302 Penalty = Mkpenalty()
303
304 UP,MD,LW = 4,2,1
305 Div = (24*60*60,UP), (7*24*60*60,MD), (14*24*60*60,LW),
306 def score(ID):
307 U, T, D = IDs[ID]
308 if ID in Penalty[T]: return LW
309 for dd, sc in Div:
310 if TsDt[T]+dd>=D:
311 break
312 return sc
313
314 def Userscore(U):
315 scores = [max(score(i) for i in Tab[T][U]) for T in Tab if Tab[T][U]]
316 All = len(scores)
317 Full = scores.count(4)
318 return sum(scores), All, Full
319
320 Mx = UP*len(Tab)
321 Mn = Mx * 2 // 3
322 def grade(M, g=("Отл","Хор","Удовл")):
323 if M<=Mn: return ""
324 return g[int((Mx-M)*len(g)/(Mx-Mn))]
325
326 def isID(i):
327 if type(i) is int and i in IDs or type(i) is str and i.isdigit() and int(i) in IDs:
328 return int(i)
329 else:
330 return None
331
332 import os
333 import readline
334 import atexit
335
336 C = []
337
338 def dumpargs(*ap, **an):
339 print("##",ap,an)
340
341 def completer(text, state):
342 U = [u for u in Users if u.startswith(text)]
343 return U[state] if len(U)>state else None
344
345 def lister(st, matches, maxlen):
346 w = os.get_terminal_size().columns-2-len(prompt)
347 sub = readline.get_line_buffer()
348 res = " ".join(matches)[len(st):w+len(st)-1]
349 print(" ".join(matches)[len(st):],prompt+sub,sep="\n",end="")
350 sys.stdout.flush()
351
352 def DoCalc():
353 if "/" in C:
354 Mkpenalty(set(C[1:C.index("/")]),set(C[C.index("/")+1:]))
355 else:
356 Mkpenalty(set(C[1:]))
357
358 def DoTable():
359 print("|| № || '''Ник''' || '''Всего''' || '''Вовремя''' || '''Баллы''' || '''Оценка''' ||")
360 Res = sorted(((Userscore(U),U) for U in Users),reverse=1)
361 for i,((sc, a, f),U) in enumerate(Res,1):
362 print("|| {} || {} || {} || {} || {} || {} ||".format(i,U,a,f,sc,grade(sc)))
363
364 def UserCalc():
365 sc, a, f = Userscore(C[1])
366 print("{}: ({}/{}) {} = {}".format(C[1],a,f,sc,grade(sc) or "Неуд"))
367
368 def DoTaskpasters():
369 Taskpasters(C[0])
370
371 def DoUserpastes():
372 if len(C)<2:
373 Userpastes(C[0])
374 else:
375 Userpastes(C[1], C[0])
376
377 def ShowSource():
378 print("{}({}):".format(*IDs[int(C[0])][:2]))
379 print(Src[int(C[0])])
380
381 def DoDiffsrc():
382 Diffsrc(*C)
383
384 def DoUsertasks():
385 Usertasks(C[1])
386
387 def DoTaskids():
388 if len(C)<3:
389 Taskids(C[1])
390 else:
391 Taskids(C[1],C[2])
392
393 def DoUsage():
394 print("Usage: {? [user] | ! [task] | id | user | task [user] | task user-or-id-1 user-or-id2}")
395
396 readline.set_completer(completer)
397 readline.set_completion_display_matches_hook(lister)
398
399 HFile = CF+"history.tmp"
400 if os.path.isfile(HFile):
401 readline.read_history_file(HFile)
402 atexit.register(readline.write_history_file, HFile)
403 cmd, prompt = "/", "GRR> "
404 while True:
405 C[:] = cmd.split()
406 if len(C)>0 and C[0]=="/":
407 DoCalc()
408 elif len(C)==1 and C[0]=="!":
409 Allpasters()
410 elif len(C)==1 and C[0]=="?":
411 DoTable()
412 elif len(C)==2 and C[0]=="?" and C[1] in Users:
413 UserCalc()
414 elif len(C)==1 and C[0] in Tab:
415 DoTaskpasters()
416 elif len(C)==1 and C[0] in Users:
417 DoUserpastes()
418 elif len(C)==2 and C[0] in Tab and C[1] in Users:
419 DoUserpastes()
420 elif len(C)==1 and isID(C[0]):
421 ShowSource()
422 elif len(C)==3 and C[0] in Tab:
423 DoDiffsrc()
424 elif len(C)==2 and C[0]=="!" and C[1] in Users:
425 DoUsertasks()
426 elif len(C)==2 and C[0]=="!" and C[1] in Tab:
427 DoTaskids()
428 elif len(C)==3 and C[0]=="!" and C[1] in Tab and C[2] in Users:
429 DoTaskids()
430 elif C:
431 DoUsage()
432 try:
433 cmd = input(prompt)
434 except EOFError:
435 break
Прикреплённые файлы
Для ссылки на прикреплённый файл в тексте страницы напишите attachment:имяфайла, как показано ниже в списке файлов. Не используйте URL из ссылки «[получить]», так как он чисто внутренний и может измениться.- [получить | показать] (2018-01-17 22:56:09, 6.5 KB) [[attachment:CtrlC-CtrlV.jpg]]
- [получить | показать] (2019-12-25 17:39:02, 12.7 KB) [[attachment:contest.py]]
- [получить | показать] (2018-01-15 22:49:23, 12.2 KB) [[attachment:contest_86.n.py]]
- [получить | показать] (2023-03-07 13:14:41, 33.7 KB) [[attachment:ejst.py]]
- [получить | показать] (2020-12-28 17:58:46, 28.5 KB) [[attachment:ejstat.py]]
Вам нельзя прикреплять файлы к этой странице.