diff --git a/challenges/2023/README.md b/challenges/2023/README.md index 6668edb..20aecf1 100644 --- a/challenges/2023/README.md +++ b/challenges/2023/README.md @@ -6,6 +6,8 @@ Solutions to the [2023 Advent of Code](https://adventofcode.com/2023). --- +![Benchmark graph](./benchmark-graph.png) + | Day | Status | Solutions | Notes | diff --git a/challenges/2023/benchmark-graph.png b/challenges/2023/benchmark-graph.png new file mode 100644 index 0000000..f706399 Binary files /dev/null and b/challenges/2023/benchmark-graph.png differ diff --git a/challenges/2023/benchmarks.jsonl b/challenges/2023/benchmarks.jsonl new file mode 100644 index 0000000..a09b20a --- /dev/null +++ b/challenges/2023/benchmarks.jsonl @@ -0,0 +1,25 @@ +{"day": 1, "part": 1, "runner": "py", "min": 0.02806234359741211, "max": 0.0957028865814209, "avg": 0.033700079917907716, "n": 100} +{"day": 1, "part": 2, "runner": "py", "min": 0.036818742752075195, "max": 0.08628964424133301, "avg": 0.05282108783721924, "n": 100} +{"day": 2, "part": 1, "runner": "py", "min": 0.035996198654174805, "max": 0.16872835159301758, "avg": 0.05545815944671631, "n": 100} +{"day": 2, "part": 2, "runner": "py", "min": 0.03395867347717285, "max": 0.04913759231567383, "avg": 0.04006660461425781, "n": 100} +{"day": 3, "part": 1, "runner": "py", "min": 0.0647578239440918, "max": 0.18926548957824707, "avg": 0.08141623735427857, "n": 100} +{"day": 3, "part": 2, "runner": "py", "min": 0.029996156692504883, "max": 0.04504847526550293, "avg": 0.034812936782836916, "n": 100} +{"day": 4, "part": 1, "runner": "py", "min": 0.041077375411987305, "max": 0.11529421806335449, "avg": 0.06057122230529785, "n": 100} +{"day": 4, "part": 2, "runner": "py", "min": 0.040993690490722656, "max": 0.06064128875732422, "avg": 0.04680403709411621, "n": 100} +{"day": 5, "part": 1, "runner": "py", "min": 0.03789997100830078, "max": 0.17576885223388672, "avg": 0.046078598499298094, "n": 100} +{"day": 6, "part": 1, "runner": "py", "min": 0.01985001564025879, "max": 0.044942378997802734, "avg": 0.028468074798583983, "n": 100} +{"day": 6, "part": 2, "runner": "py", "min": 0.019793033599853516, "max": 0.03257584571838379, "avg": 0.02442594528198242, "n": 100} +{"day": 7, "part": 1, "runner": "py", "min": 0.04590344429016113, "max": 0.13384461402893066, "avg": 0.062185251712799074, "n": 100} +{"day": 7, "part": 2, "runner": "py", "min": 0.05640268325805664, "max": 0.09029102325439453, "avg": 0.07284079790115357, "n": 100} +{"day": 8, "part": 1, "runner": "py", "min": 0.02858424186706543, "max": 0.06758975982666016, "avg": 0.04282158613204956, "n": 100} +{"day": 8, "part": 2, "runner": "py", "min": 0.07455253601074219, "max": 0.1345658302307129, "avg": 0.09417223215103149, "n": 100} +{"day": 9, "part": 1, "runner": "py", "min": 0.032199859619140625, "max": 0.12543773651123047, "avg": 0.044357788562774655, "n": 100} +{"day": 9, "part": 2, "runner": "py", "min": 0.03330564498901367, "max": 0.07211709022521973, "avg": 0.04614929676055908, "n": 100} +{"day": 10, "part": 1, "runner": "py", "min": 0.04725289344787598, "max": 0.08723211288452148, "avg": 0.06157275438308716, "n": 100} +{"day": 10, "part": 2, "runner": "py", "min": 0.05262422561645508, "max": 0.09373903274536133, "avg": 0.06505710601806641, "n": 100} +{"day": 11, "part": 1, "runner": "py", "min": 0.1369001865386963, "max": 0.48844385147094727, "avg": 0.18774306058883666, "n": 100} +{"day": 11, "part": 2, "runner": "py", "min": 0.1357133388519287, "max": 0.24532866477966309, "avg": 0.176527099609375, "n": 100} +{"day": 12, "part": 1, "runner": "py", "min": 0.05989861488342285, "max": 0.13327932357788086, "avg": 0.07568852424621582, "n": 100} +{"day": 12, "part": 2, "runner": "py", "min": 0.904543399810791, "max": 2.621077299118042, "avg": 1.316542136669159, "n": 100} +{"day": 13, "part": 1, "runner": "py", "min": 0.04506516456604004, "max": 0.1567397117614746, "avg": 0.059773361682891844, "n": 100} +{"day": 13, "part": 2, "runner": "py", "min": 0.06211209297180176, "max": 0.12923550605773926, "avg": 0.07918766498565674, "n": 100} diff --git a/generate-benchmark-graph.py b/generate-benchmark-graph.py new file mode 100644 index 0000000..ac2ef54 --- /dev/null +++ b/generate-benchmark-graph.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python3 + +import json +import matplotlib.pyplot as plt +import matplotlib.patches as patches +import os +import sys +from pathlib import Path + +OUTPUT_FILE = sys.argv[1] +BENCHMARK_FILE = Path(sys.argv[2]) + +YEAR = BENCHMARK_FILE.parts[1] + +COLOURS = {"Python": "#3572A5"} + +MAX_Y_VALUE = 1 + +runner_translation = { + "py": "Python", +} + +benchmark_data = { + "Python": {}, +} # adding dicts here sets the order of points being plotted + +with open(BENCHMARK_FILE) as f: + for line in f.readlines(): + d = json.loads(line) + rn = runner_translation[d["runner"]] + benchmark_data[rn][f"{d['day']}.{d['part']}"] = d["avg"] + +all_days = set() + +for lang in benchmark_data: + for key in benchmark_data[lang]: + day = int(key.split(".", 1)[0]) + all_days.add(day) + +figure = plt.figure(figsize=(25 / 2, 5)) +axp1 = figure.add_subplot(1, 2, 1) +axp2 = figure.add_subplot(1, 2, 2, sharey=axp1) + +axp1.axhline(y=15, color="#fc8080", linestyle="--") +axp2.axhline(y=15, color="#fc8080", linestyle="--") + +for i, language in enumerate(benchmark_data): + + data = benchmark_data[language] + part_one_times = [] + part_two_times = [] + + p1days = [] + p2days = [] + + for key in data: + + day = int(key.split(".", 1)[0]) + + if key.endswith(".1"): + if day not in p1days: + p1days.append(day) + part_one_times.append(data[key]) + if key.endswith(".2"): + if day not in p2days: + p2days.append(day) + part_two_times.append(data[key]) + + colour = COLOURS.get(language) + + p1 = axp1.scatter(p1days, part_one_times, color=colour) + p2 = axp2.scatter(p2days, part_two_times, color=colour) + + for i, day in enumerate(p1days): + if i + 1 >= len(p1days): + continue + if p1days[i + 1] == day + 1: + axp1.plot( + (day, p1days[i + 1]), + (part_one_times[i], part_one_times[i + 1]), + "-", + color=colour, + ) + + for i, day in enumerate(p2days): + if i + 1 >= len(p2days): + continue + if p2days[i + 1] == day + 1: + axp2.plot( + (day, p2days[i + 1]), + (part_two_times[i], part_two_times[i + 1]), + "-", + color=colour, + ) + +figure.suptitle(f"Average {YEAR} challenge running time") +axp1.set_title("Part one") +axp2.set_title("Part two") + + +def do_auxillary_parts(axis): + plt.sca(axis) + plt.xticks(list(all_days), [str(y) for y in all_days]) + plt.ylabel("Running time (log seconds)") + plt.yscale("log") + plt.xlabel("Day") + plt.legend( + handles=[patches.Patch(color=COLOURS[label], label=label) for label in COLOURS] + ) + # plt.ylim([0, MAX_Y_VALUE]) + # plt.legend(legends) + + +do_auxillary_parts(axp1) +do_auxillary_parts(axp2) + +plt.tight_layout() +plt.savefig(OUTPUT_FILE)