Compare commits

...

4 commits

Author SHA1 Message Date
078c98ee1d Day 10 of 2020 solved in Python 2020-12-21 22:21:07 +01:00
c9671c5e34 Day 9 of 2020 done in Python 2020-12-21 01:42:23 +01:00
9c2774be19 2020 day 8 : alternative Python solution
Solved with threads, slower by 20-30% for this workload apparently.
Might be because it is the same solution, juste using a new thread for each test
instead of one thread. Early exit does not seem to improve things, as the threads
complete very quickly.
2020-12-21 00:46:50 +01:00
6aca049908 Day 8 of 2020 done in Python
Single threaded brute force for finding the correct fix.
Don't really like it : might be something smarter to do, will try threads.
2020-12-21 00:15:59 +01:00
7 changed files with 2021 additions and 0 deletions

68
2020/Day 10/Solution.py Normal file
View file

@ -0,0 +1,68 @@
input_file = "input.txt"
adapters = []
with open(input_file) as adapter_ratings:
line = adapter_ratings.readline()
while line and line != "\n":
adapters.append(int(line))
line = adapter_ratings.readline()
adapters.sort()
computer_adapter = max(adapters) + 3
# List of couples separated by three, which must be present to have a working chain
fixed_points = []
one_diffs = 0
three_diffs = 1 # As the computer adapter is always the highest one we got plus three
# The charging outlet is 0, compute the difference now
if adapters[0] == 1:
one_diffs += 1
elif adapters[0] == 3:
fixed_points.append((adapters[0], 0))
three_diffs += 1
for index in range(len(adapters)-1):
current_difference = adapters[index+1] - adapters[index]
if current_difference == 1:
one_diffs += 1
elif current_difference == 3:
if (adapters[index], index) not in fixed_points:
fixed_points.append((adapters[index], index))
fixed_points.append((adapters[index+1], index+1))
three_diffs += 1
print(f"The product of one and three differences is : {one_diffs}*{three_diffs} = {one_diffs*three_diffs}")
# The last adapter is always needed as it is the only link possible to the computer adapter
if (adapters[-1], len(adapters)-1) not in fixed_points:
fixed_points.append((adapters[-1], len(adapters)-1))
# Compute the distance separating each fixed point. If they are not successive, it means that there are possible
# permutations between those two fixed points. Store the count of numbers we can choose from
separation_distance = []
for index in range(len(fixed_points) - 1):
if fixed_points[index + 1][1] - fixed_points[index][1] > 1:
separation_distance.append(fixed_points[index + 1][1] - fixed_points[index][1] - 1)
# Distance between 0 and the first fixed point
separation_distance.insert(0, fixed_points[0][1])
total_combinations = 1
# This would probably not work in a general case other than this puzzle, as I only take into account small possible
# separations, which is all I have got.
for separation in separation_distance:
# If we have three numbers, it means that we have at least a separation of 4 jolts between the two fixed points,
# which is not possible to cross if we do not choose any number between those two. So, do not count this choice.
if separation == 3:
# Number of subsets of a set is 2^n where n is the number of elements in the set.
total_combinations *= 2**3 - 1
else:
total_combinations *= 2**separation
print(f"The number of combinations is : {total_combinations}")

110
2020/Day 10/input.txt Normal file
View file

@ -0,0 +1,110 @@
160
34
123
159
148
93
165
56
179
103
171
44
110
170
147
98
25
37
137
71
5
6
121
28
19
134
18
7
66
90
88
181
89
41
156
46
8
61
124
9
161
72
13
172
111
59
105
51
109
27
152
117
52
68
95
164
116
75
78
180
81
47
104
12
133
175
16
149
135
99
112
38
67
53
153
2
136
113
17
145
106
31
45
169
146
168
26
36
118
62
65
142
130
1
140
84
94
141
122
22
48
102
60
178
127
73
74
87
182
35

View file

@ -0,0 +1,73 @@
from threading import Thread, current_thread, main_thread
input_file = "input.txt"
threads = []
def run_file(current_line=0, explored_lines=None, accumulator=0, switch=False):
"""
Run the program contained in the eponymous list. If switch is True, try and correct the program
to be able to complete it on other threads. Otherwise, exit on program end or repeated instruction.
:param current_line: Position to start at in the program (Program Counter)
:param explored_lines: Array of already executed instructions, to detect repeats
:param accumulator: Starting value of the accumulator
:param switch: If True, try to switch a nop to a jmp or vice-versa to fix the program
:return: True if booted successfully or if a correction allowed to boot.
"""
if explored_lines is None:
explored_lines = list()
while current_line <= len(program) - 1:
if current_line in explored_lines:
print(f"Instruciton at line {current_line} would have been executed twice.\n"
f"The accumulator value at this point was {accumulator}")
return False
instruction, argument = program[current_line].split(" ")
explored_lines.append(current_line)
if instruction == "jmp":
if switch:
# Simulate nop by copying the current state and adding one the the current_line
threads.append(Thread(name=str(current_line), target=run_file,
args=(current_line+1, explored_lines.copy(), accumulator)))
threads[-1].start()
current_line += int(argument)
elif instruction == "nop":
if switch:
# Simulate a jump by copying the current state but adding the current argument to the current_line
threads.append(Thread(name=str(current_line), target=run_file,
args=(current_line+int(argument), explored_lines.copy(), accumulator)))
threads[-1].start()
current_line += 1
elif instruction == "acc":
accumulator += int(argument)
current_line += 1
print(f"Booted successfully !\nThe final accumulator value was {accumulator}")
if current_thread() != main_thread():
print(f"The boot was possible thanks to a modification on line {current_thread().name}")
return True
program = []
with open(input_file) as instructions:
line = instructions.readline()
while line and line != "\n":
line = line.strip("\n")
program.append(line)
line = instructions.readline()
run_file(switch=True)
# Wait for children to terminate
for thread in threads:
thread.join()

62
2020/Day 8/Solution.py Normal file
View file

@ -0,0 +1,62 @@
input_file = "input.txt"
def run_file(current_line=0, explored_lines=None, accumulator=0, switch=False):
"""
Run the program contained in the eponymous list. If switch is True, try and correct the program
to be able to complete it. Otherwise, exit on program end or repeated instruction.
:param current_line: Position to start at in the program (Program Counter)
:param explored_lines: Array of already executed instructions, to detect repeats
:param accumulator: Starting value of the accumulator
:param switch: If True, try to switch a nop to a jmp or vice-versa to fix the program
:return: True if booted successfully or if a correction allowed to boot.
"""
if explored_lines is None:
explored_lines = list()
while current_line <= len(program) - 1:
if current_line in explored_lines:
print(f"Instruciton at line {current_line} would have been executed twice.\n"
f"The accumulator value at this point was {accumulator}")
return False
instruction, argument = program[current_line].split(" ")
explored_lines.append(current_line)
if instruction == "jmp":
if switch:
# Simulate nop by copying the current state and adding one the the current_line
if run_file(current_line+1, explored_lines.copy(), accumulator):
print(f"Successful modification at line {current_line}")
return True
current_line += int(argument)
elif instruction == "nop":
if switch:
# Simulate a jump by copying the current state but adding the current argument to the current_line
if run_file(current_line+int(argument), explored_lines.copy(), accumulator):
print(f"Successful modification at line {current_line}")
return True
current_line += 1
elif instruction == "acc":
accumulator += int(argument)
current_line += 1
print(f"Booted successfully !\nThe final accumulator value was {accumulator}")
return True
program = []
with open(input_file) as instructions:
line = instructions.readline()
while line and line != "\n":
line = line.strip("\n")
program.append(line)
line = instructions.readline()
run_file(switch=True)

636
2020/Day 8/input.txt Normal file
View file

@ -0,0 +1,636 @@
acc -13
jmp +37
acc -19
jmp +1
jmp +1
jmp +413
acc +10
jmp +194
jmp +587
jmp +388
acc +48
nop +284
acc +35
jmp +239
acc +0
jmp +58
acc +22
acc +45
acc +25
acc +23
jmp +544
jmp +610
nop +273
jmp +554
jmp +584
acc +30
jmp +481
acc +29
jmp +342
acc +9
acc +23
nop +377
jmp +483
acc +33
jmp +128
nop +560
nop +437
jmp +485
acc +2
acc +30
jmp +456
acc +0
acc -15
nop +126
acc +47
jmp +299
acc +36
acc +9
jmp -21
acc +10
acc +26
acc -3
acc +31
jmp +337
nop +517
jmp +303
acc +20
nop -43
acc +30
acc +24
jmp +348
jmp +158
acc +23
acc +16
acc +40
jmp +1
jmp +465
acc +12
jmp +276
acc +0
acc +32
acc +43
jmp +487
acc +40
acc +49
nop +540
jmp +455
acc +24
jmp +481
acc +30
nop +256
acc +29
acc +14
jmp +390
jmp +1
acc -3
jmp +1
jmp +295
acc +6
acc +46
acc +16
nop +128
jmp -38
acc +0
acc +16
acc +10
jmp +185
acc -19
acc +0
acc +23
acc -16
jmp +180
acc +14
jmp +1
acc +31
acc -4
jmp +439
jmp +204
acc +50
acc +12
nop +154
jmp +474
acc -16
jmp +511
acc +6
acc +32
jmp +504
acc +17
acc +21
acc -18
jmp +298
acc -17
acc +16
acc +4
acc +18
jmp +18
acc -10
acc +26
acc +36
jmp +166
nop -109
jmp +266
acc -9
jmp +306
nop +324
acc +16
acc +33
acc +18
jmp -50
acc +25
jmp +196
acc +21
jmp +308
jmp +38
acc +27
jmp -48
acc +14
acc +46
acc +48
acc +15
jmp +223
acc +0
acc +12
jmp -115
acc +19
acc +27
acc +30
jmp +377
jmp -144
jmp +231
acc +1
jmp +410
acc +41
jmp +138
acc -13
acc -8
acc -7
acc +25
jmp +366
acc +8
jmp +182
acc +2
nop +104
acc +24
acc +21
jmp -43
acc -8
acc +37
acc +23
jmp +292
jmp +365
acc +33
nop -144
acc -10
jmp +387
acc +13
acc -6
acc -12
nop +134
jmp +345
acc +5
acc +16
acc +35
acc +50
jmp +250
acc +46
jmp +105
acc -6
nop -152
jmp +233
jmp -88
acc +39
jmp +59
acc -4
acc +47
jmp +165
acc +32
acc +49
acc +24
jmp +344
acc -5
acc +3
jmp +359
acc +27
jmp +72
acc +0
acc +16
acc +40
jmp +98
acc +2
acc +23
acc +48
acc +2
jmp -33
jmp -186
acc +27
nop -83
acc +2
acc +19
jmp -141
acc +39
acc +34
acc +33
jmp +282
jmp +306
acc +12
jmp +317
acc +32
acc +50
acc +17
jmp +52
acc +3
acc +35
jmp +328
acc +26
nop +163
acc +6
acc +19
jmp +154
acc +4
jmp +1
jmp +373
acc -12
acc +47
jmp +1
jmp -234
acc +45
acc +46
acc -14
acc +50
jmp -134
acc +26
jmp +128
jmp +233
acc +23
nop -133
jmp -154
jmp +260
acc +21
acc +14
nop -89
acc +9
jmp -113
acc +10
acc +5
jmp +127
acc -9
acc +2
jmp +286
nop +274
jmp +93
acc +46
acc +36
jmp +53
acc +30
jmp -126
acc +11
acc +11
acc +23
jmp +296
nop -100
jmp +304
jmp +219
acc +16
jmp -93
acc +12
jmp +1
jmp +205
acc +6
acc -11
jmp +202
jmp +107
jmp +1
jmp -224
acc +24
acc +50
acc +37
jmp +45
acc +25
acc -15
jmp -151
jmp +1
acc +47
jmp -196
jmp +1
jmp +300
jmp +116
acc +39
acc +0
nop -176
acc -7
jmp -53
acc +20
nop -216
nop +291
jmp +38
acc +0
acc +32
acc -19
jmp -28
jmp -176
acc +33
acc +11
acc +47
nop -58
jmp -203
acc +48
acc +50
acc +41
jmp -315
acc -12
acc +23
acc +32
jmp +210
acc +46
acc -11
acc -16
jmp +103
acc +25
nop +95
acc +9
jmp -117
nop +18
acc -19
acc +38
jmp -130
acc +22
jmp +25
nop +201
nop +205
acc +14
jmp -124
jmp -46
acc +9
jmp -257
acc -19
acc -17
acc +36
acc +24
jmp -210
jmp -231
acc +40
jmp +46
nop -192
acc -13
acc +7
acc +33
jmp +103
acc +18
acc +37
acc -14
jmp -11
acc +12
nop -240
acc +35
acc +33
jmp -274
acc -9
acc +24
jmp -128
nop -129
acc -17
jmp -62
acc +0
acc +42
nop +116
jmp -44
acc +16
jmp +179
acc -8
acc +8
jmp -149
acc +39
acc +2
acc +14
acc +12
jmp -373
jmp +76
jmp -232
jmp -385
acc +22
acc +41
acc +28
jmp -179
acc +0
acc +22
acc +15
jmp -291
acc -18
jmp -222
acc +45
acc -15
jmp +61
acc +10
acc +16
acc +43
jmp +177
acc +43
acc -12
acc +20
acc +27
jmp -13
acc -14
jmp -336
nop -158
acc +3
nop -409
acc +17
jmp -257
acc +0
nop +124
jmp +1
jmp +117
jmp -179
acc -17
acc -2
jmp +1
jmp -37
acc +42
jmp +175
acc -9
acc +12
acc +4
jmp +69
acc -7
jmp +1
acc +32
jmp +54
jmp -444
acc +7
jmp -87
acc -6
nop -323
acc +47
acc -5
jmp -143
jmp +1
nop -44
acc +27
acc +21
jmp -184
jmp -404
jmp -70
acc +32
jmp -13
acc +0
nop -452
acc +1
acc +31
jmp -77
jmp -401
acc +42
jmp -428
nop -120
acc -17
nop -75
acc +6
jmp +20
jmp -291
acc +7
jmp +37
acc +10
acc +15
jmp +1
acc +11
jmp -363
acc -14
nop -321
jmp -40
acc +41
acc +31
jmp +58
jmp -493
acc +32
acc -10
acc +44
jmp -211
acc +47
acc +23
jmp -241
jmp -224
acc -1
jmp -350
acc +8
jmp -280
acc -19
acc +0
acc +17
jmp -274
acc +27
acc +11
jmp -82
acc +48
acc +27
jmp -518
acc +3
jmp -124
jmp +1
jmp -490
acc +41
jmp -238
acc -6
jmp -386
jmp -189
acc -11
jmp +80
acc -8
acc +9
nop -99
jmp +56
acc -18
jmp -83
acc +28
acc +13
jmp -228
acc +32
acc +34
acc +3
jmp -272
nop -410
acc +13
acc -17
jmp -236
acc +45
acc +0
acc +19
nop +29
jmp +38
jmp -75
acc +7
acc +33
acc +40
jmp -180
jmp -557
acc +22
jmp -249
acc +44
acc +45
acc +2
acc -19
jmp -537
acc +44
acc +32
acc -14
acc +39
jmp -406
jmp -488
acc +14
acc +41
jmp -327
acc +17
acc +25
nop -573
acc +0
jmp -563
acc +18
nop -282
acc +13
acc +45
jmp -325
acc +41
acc -10
nop -47
nop -223
jmp -155
acc +14
acc +23
jmp +23
acc +21
nop -229
acc +27
acc -5
jmp -95
acc +2
acc -10
nop -451
jmp -393
jmp -406
acc +42
acc +18
acc +49
jmp -307
acc -11
jmp +1
jmp -424
jmp -192
acc +49
acc -1
acc -17
jmp -355
jmp -268
nop -320
acc +1
jmp -134
acc +46
jmp -564
acc +40
acc +29
acc +13
nop -285
jmp -272
acc +19
acc -14
acc +25
acc +18
jmp +1

72
2020/Day 9/Solution.py Normal file
View file

@ -0,0 +1,72 @@
input_file = "input.txt"
# Sum each pair of number available, return True if target can be reached
def is_sum_of_two(available_numbers, target):
for index in range(len(available_numbers)):
for number in available_numbers[index+1:]:
if available_numbers[index]+number == target:
return True
return False
def find_invalid_digit():
sliding_last_digits = []
with open(input_file) as encoded_digits:
line = encoded_digits.readline()
# Read the header data
while len(sliding_last_digits) < 25:
sliding_last_digits.append(int(line))
line = encoded_digits.readline()
while line and line != "\n":
if not is_sum_of_two(sliding_last_digits, int(line)):
print(f"{int(line)} is not the sum of two of the 25 preceding numbers.")
return int(line)
sliding_last_digits.pop(0)
sliding_last_digits.append(int(line))
line = encoded_digits.readline()
def find_vulnerability(invalid_digit=0):
"""
This works by adding every contiguous number until it goes over the target number.
When it goes over, it drops the first number of the contiguous series until it can add the new one.
Thus, the contiguous slice of the main list of number only shrinks on one side and only expands on the other.
"""
currently_summed = []
current_sum = 0
with open(input_file) as encoded_digits:
line = encoded_digits.readline()
next_number = int(line)
while line and line != "\n":
if current_sum == invalid_digit:
print(f"Found contiguous sum : {currently_summed}\n"
f"The vulnerability is : {min(currently_summed)}+{max(currently_summed)} = "
f"{min(currently_summed) + max(currently_summed)}")
break
elif current_sum + next_number < invalid_digit:
currently_summed.append(next_number)
current_sum += next_number
elif current_sum + next_number > invalid_digit:
# Would continue indefinitely if nex_number > invalid_digit. Should not happen.
while current_sum + next_number > invalid_digit:
# Pop the first numbers of the list until we can add the new one
current_sum -= currently_summed.pop(0)
currently_summed.append(next_number)
current_sum += next_number
line = encoded_digits.readline()
next_number = int(line)
find_vulnerability(find_invalid_digit())

1000
2020/Day 9/input.txt Normal file

File diff suppressed because it is too large Load diff