#ProjectEulerPython/Bechmark.py #Matthew Ellison # Created: 07-19-20 #Modified: 06-01-21 #This is the driver function for the Java version of the ProjectEuler project """ Copyright (C) 2021 Matthew Ellison This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . """ from Problems.Problem import Problem from ProblemSelection import ProblemSelection from Stopwatch import Stopwatch class Benchmark: class BenchmarkOptions: runSpecific = 1 runAllShort = 2 runAll = 3 exit = 4 size = 5 __tooLong = [3, 5, 10, 12, 14, 15, 23, 24, 25, 27, 30, 34, 35, 67] #The driver function for the benchmark selection @staticmethod def benchmarkMenu(): Benchmark.printMenu() selection = Benchmark.getMenuSelection() if(selection == Benchmark.BenchmarkOptions.runSpecific): Benchmark.runSpecific() elif(selection == Benchmark.BenchmarkOptions.runAllShort): Benchmark.runAllShort() elif(selection == Benchmark.BenchmarkOptions.runAll): Benchmark.runAll() #Print the benchmark menu @staticmethod def printMenu(): print("1. Run a specific problem") print("2. Run all problems that have a reasonably short run time") print("3. Run all problems") print("4. Exit the menu") print() #Returns a valid menu option @staticmethod def getMenuSelection() -> int: selection = int(input("")) while(not Benchmark.isValidMenu(selection)): print("that is an invalid option!\nPress Enter to continue") Benchmark.printMenu() selection = int(input("")) return selection #Determines if a value is a valid menu option. Helper for getBechmarkMenuSelection @staticmethod def isValidMenu(selection: int): if((selection > 0) and (selection < (Benchmark.BenchmarkOptions.size))): return True else: return False #Determines which problem user wants to run and runs it @staticmethod def runSpecific(): #Ask which problem the user wants to run problemNumber = ProblemSelection.getProblemNumber() #Ask how many times to run the problem timesToRun = Benchmark.getNumberOfTimesToRun() #Get the problem and print its description problem = ProblemSelection.getProblem(problemNumber) print(str(problemNumber) + ". " + problem.getDescription()) #Run the problem the specific number of times totalTime = Benchmark.runProblem(problem, timesToRun) #Print the results print(Benchmark.getBenchmarkResults(problem, totalTime, timesToRun)) #Runs all problems except a few that are specified because of run length @staticmethod def runAllShort(): #Ask how many times to run the problems timesToRun = Benchmark.getNumberOfTimesToRun() #Run through all valid problem numbers, skipping a few that are in the tooLong list for cnt in range(1, len(ProblemSelection.problemNumbers)): problemNumber = ProblemSelection.problemNumbers[cnt] #If the problem number is contained in the list of problems that take too long skip it if problemNumber in Benchmark.__tooLong: continue #Get the problem and print its description problem = ProblemSelection.getProblem(problemNumber) print(str(problemNumber) + ". " + problem.getDescription()) #Run each problem the specified number of times totalTime = Benchmark.runProblem(problem, timesToRun) #Print the results print(Benchmark.getBenchmarkResults(problem, totalTime, timesToRun)) #Runs all problems @staticmethod def runAll(): #Ask how many times to run the problem timesToRun = Benchmark.getNumberOfTimesToRun() #Run through all valid problem numbers, skipping a few that are in the tooLong list for cnt in range(1, len(ProblemSelection.problemNumbers)): problemNumber = ProblemSelection.problemNumbers[cnt] #Get the problem and print its description problem = ProblemSelection.getProblem(problemNumber) print(str(problemNumber) + ". " + problem.getDescription()) #Run each problem the specified number of times totalTime = Benchmark.runProblem(problem, timesToRun) #Print the results print(Benchmark.getBenchmarkResults(problem, totalTime, timesToRun)) #Asks how many times a problem is supposed to run and returns the value @staticmethod def getNumberOfTimesToRun() -> int: numOfTimesToRun = int(input("How many times do you want to run this problem? ")) while(numOfTimesToRun < 1): print("That is an invalid number!") numOfTimesToRun = int(input("How many times do you want to run this problem? ")) return numOfTimesToRun #Runs the problem the given number of times @staticmethod def runProblem(problem: Problem, timesToRun: int) -> float: totalTime = 0.0 print("Solving", end='') for cnt in range(0, timesToRun): print('.', end = '', flush = True) #Reset the data so you are actually count the run time an additional time problem.reset() #Solve the problem problem.solve() #Get the time data totalTime += problem.getTimer().getNanoseconds() return totalTime #Prints the benchmark results of a problem @staticmethod def getBenchmarkResults(problem: Problem, totalTime: float, timesRun: int) -> str: #Calculate the average run time of the problem totalTime /= timesRun timeResults = Stopwatch.getStr(totalTime) #Tally the results results = "\n\n" + problem.getResult() + "\nIt took an average of " + str(timeResults) + " to run this problem through " + str(timesRun) + " iterations\n\n" return results