Repository navigation
Expand file tree
/
Copy pathgenerate.py
More file actions
executable file
·123 lines (106 loc) · 4.31 KB
/
Copy pathgenerate.py
File metadata and controls
executable file
·123 lines (106 loc) · 4.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#!/usr/bin/env python3
from datetime import datetime, timedelta
import os
import xml.etree.ElementTree as ET
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
START = datetime(2020, 12, 1, 5)
PUZZLES = 25
DATADIR = '/home/marxin/Downloads/aoc2020'
THRESHOLD = 100
THRESHOLD2 = 1000
puzzles = {}
thresholds = {}
def parse_file(path, offset):
for line in open(path).readlines():
if '/2020/day' in line:
root = ET.fromstring(line)
day = int(root.text)
if not day in puzzles:
puzzles[day] = [(0, 0, 0)]
thresholds[day] = [0, 0, 0, 0]
both = int(root[0].text)
first = int(root[1].text) + both
tick = (offset - timedelta(days=day - 1)).total_seconds() / 60**2
puzzles[day].append((tick, first, both))
if thresholds[day][0] == 0 and first >= THRESHOLD:
thresholds[day][0] = tick
if thresholds[day][1] == 0 and both >= THRESHOLD:
thresholds[day][1] = tick
if thresholds[day][2] == 0 and first >= THRESHOLD2:
thresholds[day][2] = tick
if thresholds[day][3] == 0 and both >= THRESHOLD2:
thresholds[day][3] = tick
def generate_users_for_puzzle(p):
fig, ax = plt.subplots(figsize=(10, 5))
ax.plot([x[0] for x in puzzles[p]], [x[1] for x in puzzles[p]], label='One star')
ax.plot([x[0] for x in puzzles[p]], [x[2] for x in puzzles[p]], label='Two stars')
ax.set_title(f'Day {p} - stars for users')
ax.set_xlabel('Time (in hours)')
ax.set_ylabel('Users')
ylim = ax.get_ylim()[1]
ax.vlines(thresholds[p][0], 0, ylim, colors=['silver'], label='First 100 (one star)', lw=0.4)
ax.vlines(thresholds[p][1], 0, ylim, colors=['gold'], label='First 100 (two stars)', lw=0.4)
ax.grid(True)
ax.legend()
plt.savefig(f'puzzle{p:02d}-users.svg')
def generate_users_for_all_puzzles():
fig, ax = plt.subplots(figsize=(10, 5))
for day in puzzles.keys():
ax.plot([x[0] / 24 + day - 1 for x in puzzles[day]],
[x[1] for x in puzzles[day]],
color='tab:blue',
label='One star' if day == 1 else None)
ax.plot([x[0] / 24 + day - 1 for x in puzzles[day]],
[x[2] for x in puzzles[day]],
color='tab:orange',
label='Two stars' if day == 1 else None)
ax.set_title(f'Users per Puzzle')
ax.set_xlabel('Time (in days) (NOTE: Day 1 puzzle starts at 0)')
ax.set_ylabel('Users')
ax.grid(True)
ax.legend()
plt.savefig(f'puzzles-users.svg')
def generate_first_N(N, index):
width = 0.35
fig, ax = plt.subplots(figsize=(10, 5))
labels = [f'Day {x}' for x in puzzles.keys()]
x = np.arange(len(labels)) # the label locations
ax.set_title(f'Time for first {N} users')
y1 = [x[index] * 60 for x in thresholds.values()]
ax.bar(x - width / 2, y1, width, label=f'First {N} (one star)', color='silver')
y2 = [x[index + 1] * 60 for x in thresholds.values()]
ax.bar(x + width / 2, y2, width, label=f'First {N} (two stars)', color='gold')
ax.set_xticks(x)
ax.set_xticklabels(labels)
ax.legend()
ax.set_ylabel('Time (in minutes)')
ax.grid(True)
filename = f'first-{N}.svg'
plt.savefig(filename)
datafiles = sorted(os.listdir(DATADIR))
print(f'Processing {len(datafiles)} data files')
for f in datafiles:
stamp = f.split('.')[0]
datestamp = datetime.fromisoformat(stamp)
if datestamp > START:
parse_file(os.path.join(DATADIR, f), datestamp - START)
print('Generating graphs')
for puzzle in puzzles.keys():
generate_users_for_puzzle(puzzle)
generate_users_for_all_puzzles()
# generate first N bars
generate_first_N(THRESHOLD, 0)
generate_first_N(THRESHOLD2, 2)
with open('README.md', 'w') as readme:
readme.write('# Advent of Code 2020 Statistics\n')
readme.write('## Starts for users\n')
readme.write('\n')
readme.write('## First 100 users\n')
readme.write('\n')
readme.write('## First 1000 users\n')
readme.write('\n')
for day in puzzles.keys():
readme.write(f'## Day {day}\n')
readme.write(f'\n')