Skip to content

Commit 843b6d1

Browse files
committed
Improved performance of 2017-15
1 parent d3a46fd commit 843b6d1

File tree

2 files changed

+140
-41
lines changed

2 files changed

+140
-41
lines changed

2017/15-Dueling Generators.py

Lines changed: 45 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -4,90 +4,94 @@
44
test_data = {}
55

66
test = 1
7-
test_data[test] = {"input": """Generator A starts with 65
7+
test_data[test] = {
8+
"input": """Generator A starts with 65
89
Generator B starts with 8921""",
9-
"expected": ['588', 'Unknown'],
10-
}
11-
12-
test = 'real'
13-
input_file = os.path.join(os.path.dirname(__file__), 'Inputs', os.path.basename(__file__).replace('.py', '.txt'))
14-
test_data[test] = {"input": open(input_file, "r+").read().strip(),
15-
"expected": ['597', '303'],
16-
}
10+
"expected": ["588", "Unknown"],
11+
}
12+
13+
test = "real"
14+
input_file = os.path.join(
15+
os.path.dirname(__file__),
16+
"Inputs",
17+
os.path.basename(__file__).replace(".py", ".txt"),
18+
)
19+
test_data[test] = {
20+
"input": open(input_file, "r+").read().strip(),
21+
"expected": ["597", "303"],
22+
}
1723

1824
# -------------------------------- Control program execution -------------------------------- #
1925

20-
case_to_test = 'real'
21-
part_to_test = 2
26+
case_to_test = "real"
27+
part_to_test = 2
2228
verbose_level = 1
2329

2430
# -------------------------------- Initialize some variables -------------------------------- #
2531

26-
puzzle_input = test_data[case_to_test]['input']
27-
puzzle_expected_result = test_data[case_to_test]['expected'][part_to_test-1]
28-
puzzle_actual_result = 'Unknown'
32+
puzzle_input = test_data[case_to_test]["input"]
33+
puzzle_expected_result = test_data[case_to_test]["expected"][part_to_test - 1]
34+
puzzle_actual_result = "Unknown"
2935

3036

3137
# -------------------------------- Actual code execution -------------------------------- #
3238

3339
divisor = 2147483647
34-
factors = {'A': 16807, 'B': 48271}
35-
value = {'A': 0, 'B': 0}
40+
factors = {"A": 16807, "B": 48271}
41+
value = {"A": 0, "B": 0}
3642

3743

38-
def gen_a ():
44+
def gen_a():
45+
x = value["A"]
3946
while True:
40-
value['A'] *= factors['A']
41-
value['A'] %= divisor
42-
if value['A'] % 4 == 0:
43-
yield value['A']
47+
x *= 16807
48+
x %= 2147483647
49+
if x % 4 == 0:
50+
yield x
51+
4452

45-
def gen_b ():
53+
def gen_b():
54+
x = value["B"]
4655
while True:
47-
value['B'] *= factors['B']
48-
value['B'] %= divisor
49-
if value['B'] % 8 == 0:
50-
yield value['B']
56+
x *= 48271
57+
x %= 2147483647
58+
if x % 8 == 0:
59+
yield x
60+
5161

5262
if part_to_test == 1:
53-
for string in puzzle_input.split('\n'):
63+
for string in puzzle_input.split("\n"):
5464
_, generator, _, _, start_value = string.split()
5565
value[generator] = int(start_value)
5666

5767
nb_matches = 0
58-
for i in range (40 * 10 ** 6):
68+
for i in range(40 * 10 ** 6):
5969
value = {gen: value[gen] * factors[gen] % divisor for gen in value}
60-
if '{0:b}'.format(value['A'])[-16:] == '{0:b}'.format(value['B'])[-16:]:
70+
if "{0:b}".format(value["A"])[-16:] == "{0:b}".format(value["B"])[-16:]:
6171
nb_matches += 1
6272

6373
puzzle_actual_result = nb_matches
6474

6575

6676
else:
67-
for string in puzzle_input.split('\n'):
77+
for string in puzzle_input.split("\n"):
6878
_, generator, _, _, start_value = string.split()
6979
value[generator] = int(start_value)
7080

7181
nb_matches = 0
7282
A = gen_a()
7383
B = gen_b()
74-
for count_pairs in range (5 * 10**6):
84+
for count_pairs in range(5 * 10 ** 6):
7585
a, b = next(A), next(B)
76-
if '{0:b}'.format(a)[-16:] == '{0:b}'.format(b)[-16:]:
86+
if a & 0xFFFF == b & 0xFFFF:
7787
nb_matches += 1
7888

79-
8089
puzzle_actual_result = nb_matches
8190

8291

83-
8492
# -------------------------------- Outputs / results -------------------------------- #
8593

8694
if verbose_level >= 3:
87-
print ('Input : ' + puzzle_input)
88-
print ('Expected result : ' + str(puzzle_expected_result))
89-
print ('Actual result : ' + str(puzzle_actual_result))
90-
91-
92-
93-
95+
print("Input : " + puzzle_input)
96+
print("Expected result : " + str(puzzle_expected_result))
97+
print("Actual result : " + str(puzzle_actual_result))

2017/15-Dueling Generators.v1.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# -------------------------------- Input data -------------------------------- #
2+
import os
3+
4+
test_data = {}
5+
6+
test = 1
7+
test_data[test] = {
8+
"input": """Generator A starts with 65
9+
Generator B starts with 8921""",
10+
"expected": ["588", "Unknown"],
11+
}
12+
13+
test = "real"
14+
input_file = os.path.join(
15+
os.path.dirname(__file__),
16+
"Inputs",
17+
os.path.basename(__file__).replace(".py", ".txt"),
18+
)
19+
test_data[test] = {
20+
"input": open(input_file, "r+").read().strip(),
21+
"expected": ["597", "303"],
22+
}
23+
24+
# -------------------------------- Control program execution -------------------------------- #
25+
26+
case_to_test = "real"
27+
part_to_test = 2
28+
verbose_level = 1
29+
30+
# -------------------------------- Initialize some variables -------------------------------- #
31+
32+
puzzle_input = test_data[case_to_test]["input"]
33+
puzzle_expected_result = test_data[case_to_test]["expected"][part_to_test - 1]
34+
puzzle_actual_result = "Unknown"
35+
36+
37+
# -------------------------------- Actual code execution -------------------------------- #
38+
39+
divisor = 2147483647
40+
factors = {"A": 16807, "B": 48271}
41+
value = {"A": 0, "B": 0}
42+
43+
44+
def gen_a():
45+
while True:
46+
value["A"] *= factors["A"]
47+
value["A"] %= divisor
48+
if value["A"] % 4 == 0:
49+
yield value["A"]
50+
51+
52+
def gen_b():
53+
while True:
54+
value["B"] *= factors["B"]
55+
value["B"] %= divisor
56+
if value["B"] % 8 == 0:
57+
yield value["B"]
58+
59+
60+
if part_to_test == 1:
61+
for string in puzzle_input.split("\n"):
62+
_, generator, _, _, start_value = string.split()
63+
value[generator] = int(start_value)
64+
65+
nb_matches = 0
66+
for i in range(40 * 10 ** 6):
67+
value = {gen: value[gen] * factors[gen] % divisor for gen in value}
68+
if "{0:b}".format(value["A"])[-16:] == "{0:b}".format(value["B"])[-16:]:
69+
nb_matches += 1
70+
71+
puzzle_actual_result = nb_matches
72+
73+
74+
else:
75+
for string in puzzle_input.split("\n"):
76+
_, generator, _, _, start_value = string.split()
77+
value[generator] = int(start_value)
78+
79+
nb_matches = 0
80+
A = gen_a()
81+
B = gen_b()
82+
for count_pairs in range(5 * 10 ** 6):
83+
a, b = next(A), next(B)
84+
if "{0:b}".format(a)[-16:] == "{0:b}".format(b)[-16:]:
85+
nb_matches += 1
86+
87+
puzzle_actual_result = nb_matches
88+
89+
90+
# -------------------------------- Outputs / results -------------------------------- #
91+
92+
if verbose_level >= 3:
93+
print("Input : " + puzzle_input)
94+
print("Expected result : " + str(puzzle_expected_result))
95+
print("Actual result : " + str(puzzle_actual_result))

0 commit comments

Comments
 (0)