1919
2020parser .add_argument ('--solutions' ,
2121 '-s' ,
22+ nargs = '*' ,
2223 default = '' ,
23- help = 'Filename of AI solutions to add to README, if any.' )
24+ help = 'Filename(s) of AI solutions to add to README, if any.' )
2425
2526parser .add_argument ('--json' ,
2627 '-j' ,
5051
5152
5253def rename_src_var (orig , new , src , count = 0 ):
54+ if orig == new :
55+ return
56+
5357 def helper (s ):
5458 return re .sub (r'\b' + orig + r'\b(?!["\'])' , new , s , count )
5559
@@ -73,22 +77,38 @@ def indent(x, spaces=4):
7377 return (" " * spaces + x .replace ("\n " , "\n " + " " * spaces ))[:- spaces if x .endswith ("\n " ) else None ]
7478
7579
76- def save_readme (gen_modules , filename , sol_filename ):
77- ai_sols = run_name = run_desc = None
78- if sol_filename :
80+ def save_readme (gen_modules , filename , sol_filenames ):
81+ ai_sols = {}
82+ for sol_filename in sol_filenames :
7983 sols_js = utils .load_json (sol_filename )
80- run_name = sols_js ["run_name" ]
81- run_desc = sols_js ["run_desc" ]
82- ai_sols = {}
83- for f , entry in sols_js ["sols" ].items ():
84- assert f .startswith ("def " )
85- f_name = f [len ("def " ):f .index ("(" )].strip ()
86- f2 = rename_src_var (f_name , "sat" , f , 1 )
87- entry2 = ai_sols [f2 ] = entry .copy ()
88- # g = entry2["sol"]
89- g_name = "g" # g[len("def "):f.index("(")].strip()
90- entry2 ["sol" ] = rename_src_var (g_name , "sol" , rename_src_var (f_name , "sat" , entry2 ["sol" ]))
91- entry2 ["longest_sol" ] = rename_src_var (g_name , "sol" , rename_src_var (f_name , "sat" , entry2 ["longest_sol" ]))
84+ for experiment in sols_js :
85+ if "short" in experiment ["experiment" ]:
86+ continue # skip short experiments
87+ for s_s in experiment ["sat_sols" ]:
88+ f = s_s ["sat" ]
89+ assert f .startswith ("def " )
90+ f_name = f [len ("def " ):f .index ("(" )].strip ()
91+ f2 = rename_src_var (f_name , "sat" , f , 1 )
92+ if f2 not in ai_sols :
93+ ai_sols [f2 ] = dict (n_sols = 0 , n_attempts = 0 , sols = set ())
94+ if "failures" in s_s : # bootstrap
95+ ai_sols [f2 ]["n_attempts" ] += s_s ["failures" ]
96+ if s_s .get ("sol" ):
97+ ai_sols [f2 ]["n_sols" ] += 1
98+ ai_sols [f2 ]["n_attempts" ] += 1
99+ cur_sols = [s_s .get ("sol" )]
100+ else :
101+ ai_sols [f2 ]["n_attempts" ] += experiment ["n" ]
102+ ai_sols [f2 ]["n_sols" ] += s_s ["n_sols" ]
103+ cur_sols = [s_s [k ] for k in s_s if k .endswith ("_sol" )]
104+ if "example_sols" in s_s :
105+ cur_sols += s_s ["example_sols" ]
106+ ai_sols [f2 ]["sols" ].update (rename_src_var (f_name , "sat" , sol ) for sol in cur_sols if sol )
107+
108+ for entry in ai_sols .values ():
109+ entry ["sol" ] = (min (entry ["sols" ], key = len ) if entry ["sols" ] else "" )
110+ entry ['longest_sol' ] = (max (entry ["sols" ], key = len ) if len (entry ["sols" ]) > 1 else "" )
111+ entry ["success_rate" ] = entry ["n_sols" ]/ entry ["n_attempts" ]
92112
93113 table = ""
94114 content = ""
@@ -106,7 +126,7 @@ def py(src):
106126 puzzles = module_stuff ['examples' ]
107127 if ai_sols :
108128 puzzles = sorted (puzzles ,
109- key = lambda f : ( ai_sols . get ( f ['sat' ]) or {}). get ( "num_sols" , 0 ) ,
129+ key = lambda f : ai_sols [ f ['sat' ]][ "success_rate" ] if f [ 'sat' ] in ai_sols else 0 ,
110130 reverse = True )
111131 n = len (puzzles )
112132 link = f"[{ sec_name } ](#{ anchor (sec_name )} )"
@@ -124,10 +144,10 @@ def py(src):
124144 if ai_sols :
125145 sol_entry = ai_sols .get (f )
126146 if sol_entry :
127- num_ai_sols = sol_entry ['num_sols ' ]
128- puzzle_text += f"{ num_ai_sols :, } AI solution { 's' if num_ai_sols != 1 else '' } , "
147+ num_ai_sols = sol_entry ['n_sols ' ]
148+ puzzle_text += f"{ sol_entry [ 'success_rate' ] * 100 :.2g } % Codex success rate , "
129149 else :
130- puzzle_text += f"{ run_name } was not run on this puzzle, "
150+ puzzle_text += f"Codex was not run on this puzzle, "
131151 sol_bodies = puzzle ['sol_bodies' ]
132152 n_sols = len (sol_bodies )
133153 puzzle_text += f"{ n_sols :,} hand-written solution{ 's' if n_sols != 1 else '' } "
@@ -137,10 +157,14 @@ def py(src):
137157 puzzle_text += "Solution docstring (*not* usually provided)\n \n "
138158 puzzle_text += py (puzzle ['sol_docstring' ])
139159 if num_ai_sols :
140- puzzle_text += f"Shortest solution from { run_name } :\n "
141- puzzle_text += py (sol_entry ['sol' ])
142- puzzle_text += f"Longest solution from { run_name } :\n "
143- puzzle_text += py (sol_entry ['longest_sol' ])
160+ if sol_entry ['longest_sol' ]:
161+ puzzle_text += f"Shortest Codex solution:\n "
162+ puzzle_text += py (sol_entry ['sol' ])
163+ puzzle_text += f"Longest Codex solution:\n "
164+ puzzle_text += py (sol_entry ['longest_sol' ])
165+ else :
166+ puzzle_text += f"Codex solution:\n "
167+ puzzle_text += py (sol_entry ['sol' ])
144168 if n_sols :
145169 for body in sol_bodies :
146170 puzzle_text += "Hand-written solution:\n "
@@ -155,14 +179,14 @@ def py(src):
155179 table += f"\n Total ({ tot_puzzles :,} problems, { tot_instances :,} instances)\n "
156180
157181 content = TOP .format (table ) + content
158- if run_name :
182+ if ai_sols :
159183 content = content .replace (
160184 "Summary of Puzzles" ,
161- f"Summary of Puzzles and { run_name } solutions\n { run_desc } " ,
185+ f"Summary of Puzzles and Codex solutions" ,
162186 1
163187 ).replace (
164188 "----" ,
165- f"----\n \n The puzzles in each module are sorted by number of { run_name } solutions\n \n " ,
189+ f"----\n \n The puzzles in each module are sorted by percent of Codex correct solutions\n \n " ,
166190 1
167191 )
168192
0 commit comments