convert_dp_to_iterative.py 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. from evaluator import *
  2. DESCRIPTION = "Test if the model can understand a DP algorithm and then convert it into an iterative implementation."
  3. TAGS = ['code', 'performance', 'python']
  4. my_code = """
  5. @lru_cache(maxsize=None)
  6. def solve_dp(graph, lines_left, distance_since_last):
  7. if len(graph) < lines_left: return 1e9, []
  8. if lines_left == 0 and len(graph) == 0: return 0, []
  9. # option 1: don't take the line
  10. value = (1e9, [])
  11. if distance_since_last < 10:
  12. value = min(value, solve_dp(graph[1:], lines_left, distance_since_last+1))
  13. # option 2: take the line
  14. if lines_left > 0:
  15. sub, how = solve_dp(graph[1:], lines_left-1, 0)
  16. sub += graph[0] + (distance_since_last-8)**2
  17. value = min(value, (sub, how + [len(graph)]))
  18. return value
  19. """
  20. question = f"""
  21. Explain what this code does. Then, convert this recursive function to an iterative one, making explicit the cubic work that's being done. The functions should return exactly the same output but the iterative one should be faster. Call your function `solve_iterative` and match the type signature of the original function.
  22. {my_code}
  23. """
  24. test_case, answer = make_python_test([(f"""0
  25. import random
  26. mylist = list(range(100))
  27. random.shuffle(mylist)
  28. from functools import lru_cache
  29. {my_code.replace("solve_dp", "my_solve_dp")}
  30. answer = solve_iterative(tuple(mylist), len(mylist)//8, 4)""",
  31. "my_solve_dp(tuple(mylist), len(mylist)//8, 4)")])
  32. def not_recursive(code):
  33. return code.count("solve_iterative") == 1, ""
  34. TestProgramRemoveDP = question >> LLMRun() >> ExtractCode() >> \
  35. (PyFunc(not_recursive) & (PythonRun(test_case) >> SubstringEvaluator(answer)))
  36. if __name__ == "__main__":
  37. print(run_test(TestProgramRemoveDP))