With Alex’s introduction, my first time to play Advent of Code, it’s a lot of fun. Login to this website recall me my good old date of running my BBS – Beta Version BBS. As I am not professional enough, just try to solve daily quiz with basic Python coding and try not using external libraries, I would like to share my coding logic with you.
Merry Christmas and Happy New Year!!
2025 All the best!
Day 7
https://adventofcode.com/2024/day/6
Part 1
input = open("Day 7 - input.txt", "r")
result = 0
for a in input:
target, v = a.strip().split(': ')
target = int(target)
values = v.split(' ')
values = list(map(int,values))
s_formula = ''
for i in range(len(values)-1):
s_formula += '('
s_formula += str(values[0])
formula = s_formula
for i in range(2**(len(values)-1)):
b = bin(i)[2:].zfill(len(values)-1)
operator = ''
for digit in b:
if digit == '1':
operator += '*'
else:
operator += '+'
for j in range(len(values)-1):
formula += operator[j]+str(values[j+1])+')'
if eval(formula) == target:
result += target
break
formula = s_formula
print(result)
PythonHighlight
For this quiz, I am trying to use eval() to calucalte the formula when store in string. Since eval() is taking multiple (*) the first priority, I added ‘()’ for each operator, e.g. ((81+40)*27), so that it can be always evaluated left-to-right. Then, I was using the numbers of operators required and convert this into binary, i.e. 00, 01, 10, 11, and mapped this into ++, +*, *+, **. Finally, joinned the bracket, numbers and operator together as a string and calculate the result with eval().
** When I did part 2, I found myself overthinking again, I didn’t need to add bracket and using eval(). But anyway, it was a good example to share. Please check part two for how I simplified this.
03-07 : Get the target and values from the file line by line.
09-13 : Determine how many ‘(‘ bracket in the beginning and combine with the first number as a s_formula.
15-22 : Base on the number of numbers to determine how many operators need, convert this into current bit of binarry (line #16). Then, mapped 0 to ‘+’ and 1 to ‘*’
24-25 : Joinned the rest numbers with the operator and the closing bracket.
27-28 : Used eval() to calculate the string and compare with the target result
Part 2
input = open("Day 7 - input.txt", "r")
result = 0
for a in input:
target, v = a.strip().split(': ')
target = int(target)
values = v.split(' ')
values = list(map(int,values))
for i in range(3**(len(values)-1)):
ternary = ""
d = i
if d == 0:
ternary = '0'
while d > 0:
ternary = str(d % 3) + ternary
d //= 3
t = ternary.zfill(len(values)-1)
operator = ''
for digit in t:
if digit == '2':
operator += 'X'
elif digit == '1':
operator += '*'
else:
operator += '+'
formula = values[0]
for j in range(len(values)-1):
if operator[j] == '+':
formula += values[j+1]
elif operator[j] == '*':
formula *= values[j+1]
else:
formula *= 10**len(str(values)) + values[j+1]
if formula == target:
result += target
break
print(result)
PythonHighlight
Same concept as part 1, but change binary to ternary (3 based) and used the operators pattern (i.e. array) to complete the calculations instead of adding bracket and solving with eval().
09-26 : Same concept as part 1 but used ternary for ‘+’, ‘*’ & ‘H’ (concatenation), i.e. 021221 is +H*HH+. Used % & // to convert a decimal into ternary.
28-35 : Since I already defined the operators pattern, we just started from the first numeber with the corresponding operator with the next number to calculate the result. If the operator is ‘H’, just combined two numbers at line #35.
Day 6
https://adventofcode.com/2024/day/6
Part 1
input = open("Day 6 - input.txt", "r")
room = []
guard_position = [-1,-1]
guard_face_space_x = guard_face_space_y = 0
start_x = start_y = 0
for a in input:
room.append(a.strip())
if guard_position == [-1,-1]:
start_x = a.find('^')
if start_x != -1:
guard_position = [start_x, start_y]
else:
start_y += 1
guard_direction = [0,-1] #North
while True:
room[guard_position[1]] = list(room[guard_position[1]])
room[guard_position[1]][guard_position[0]] = 'X'
room[guard_position[1]] = ''.join(room[guard_position[1]])
guard_face_space_x = guard_position[0] + guard_direction[0]
guard_face_space_y = guard_position[1] + guard_direction[1]
if guard_face_space_y < 0 or guard_face_space_y == len(room) or guard_face_space_x < 0 or guard_face_space_x == len(room[0]):
break
elif room[guard_face_space_y][guard_face_space_x] == '#':
if guard_direction == [0,-1]:
guard_direction = [1,0]
elif guard_direction == [1,0]:
guard_direction = [0,1]
elif guard_direction == [0,1]:
guard_direction = [-1,0]
else:
guard_direction = [0,-1]
else:
guard_position[0] += guard_direction[0]
guard_position[1] += guard_direction[1]
count = 0
for i in room:
count += i.count('X')
print(count)
PythonHighlight
07-14 : Get all the data into room and find the guard_position
18-19 : Put ‘X’ to the guard existing position in room and move the guard according to guard_face_space
24-25 : Detect whether the guard exit the room, i.e. out of the room boundaries. If yes, exit the loop.
26-34 : If ‘#’ in front of the guard, make him turn right. I define the guard_direction in X, Y, North – [0, -1], East – [1,0], South[0,1], West[-1,0]. So, when we moved the guard_position, just adding the direction to this.
39-41 : Report the number of ‘X’, i.e. guard stepped spece, in the room.
Part 2
Highlight
I have not yet finished this because I was thinking about to make it easier by detecting all the ‘#’ location and record the stepped space to represent 4 direction – NESW. However, making this too complicate, going to use the most basic method and try one by one, but still challenge….. Finally, I made the code but it take way too too long to run..
Day 5
https://adventofcode.com/2024/day/5
Part 1
f = open("Day 5 - input.txt", "r")
o = [[] for _ in range(100)]
total = 0
for a in f:
if a == '\n':
break
i = int(a[:2])
j = int(a[3:5])
o[i].append(j)
for a in f:
p = list(map(int, a.strip().split(',')))
v = True
for i in range(len(p)):
for j in range(i+1, len(p)):
try:
o[p[i]].index(p[j])
v = True
except:
v = False
break
if i > 0 and v:
for j in range(i-1, -1, -1):
try:
o[p[i]].index(p[j])
v = False
break
except:
v =True
if not v:
break
if v:
r = p[len(p) // 2]
total += r
print(total)
PythonHighlight
05-10 : My thinking logic was trying to put the ordering rules into the corresponding array, so that I could compare the page order directly with the ordering rules. (Later on, I knew that I can use dictionary, it is much better, faster and memory saving)
12-23 : If the page could be found in the corresponding page ordering rules, then it was good order. This time, I used Try & Except to handle the error in case the page cannot be found from the rules, i.e. it was bad order. For any bad order found, quit the loop and classified failed.
25-32 : Did the check with the reserved order, if the previous page can be found in the page ordering rules, it was bad order as well.
Part 2
f = open("Day 5 - input.txt", "r")
o = [[] for _ in range(100)]
total = 0
for a in f:
if a == '\n':
break
i = int(a[:2])
j = int(a[3:5])
o[i].append(j)
for a in f:
p = list(map(int, a.strip().split(',')))
v = True
p1 = False
i = 0
while i < len(p):
i += 1
for j in range(i+1, len(p)):
try:
o[p[i]].index(p[j])
v = True
except:
v = False
p1 = True
p[i], p[j] = p[j], p[i]
i -= 1
break
if i > 0 and v:
for j in range(i-1, -1, -1):
try:
o[p[i]].index(p[j])
v = False
p1 = True
p[i], p[j] = p[j], p[i]
i -= 1
break
except:
v =True
if not v and not p1:
break
if v and p1:
r = p[len(p) // 2]
total += r
print(total)
PythonHighlight
21,29-31,39-41 : Exactly same as part 1 but added these lines to swap pages when bad order found. Then, re-run the loop with i -= 1.
Day 4
https://adventofcode.com/2024/day/4
Part 1
f = open("Day 4 - input.txt", "r")
a = []
w = ['']*8
total = 0
for i in f:
a.append(i.strip())
s = 'Z' * (len(a[0])+6)
for i in range(len(a)):
a[i] = 'ZZZ' + a[i] + 'ZZZ'
for i in range(3):
a.insert(0, s)
a.append(s)
for y in range(len(a)):
for x in range(len(a[y])):
if a[y][x] == 'X':
w[0] = a[y][x:x+4]
w[1] = a[y][x]+a[y+1][x+1]+a[y+2][x+2]+a[y+3][x+3]
w[2] = a[y][x]+a[y+1][x]+a[y+2][x]+a[y+3][x]
w[3] = a[y][x]+a[y+1][x-1]+a[y+2][x-2]+a[y+3][x-3]
w[4] = a[y][x]+a[y][x-1]+a[y][x-2]+a[y][x-3]
w[5] = a[y][x]+a[y-1][x-1]+a[y-2][x-2]+a[y-3][x-3]
w[6] = a[y][x]+a[y-1][x]+a[y-2][x]+a[y-3][x]
w[7] = a[y][x]+a[y-1][x+1]+a[y-2][x+2]+a[y-3][x+3]
total += w.count('XMAS')
print(total)
PythonHighlight
09-15 : Not to deal with index out of range error, I did a short cut by adding boundries ‘ZZZ’ to the matrix (I thought I was smart to think about this method. But lastly, I learnt that this is a common practice calls ‘Padding’ )
17-28 : With the help of Padding, it is easily for me to solve this by check ‘XMAS’ in eight directions.
Part 2
f = open("Day 4 - input.txt", "r")
a = []
w = ['']*2
total = 0
for i in f:
a.append(i.strip())
s = 'Z' * (len(a[0])+2)
for i in range(len(a)):
a[i] = 'Z' + a[i] + 'Z'
for i in range(3):
a.insert(0, s)
a.append(s)
for y in range(len(a)):
for x in range(len(a[y])):
if a[y][x] == 'A':
w[0] = a[y-1][x-1]+a[y][x]+a[y+1][x+1]
w[1] = a[y+1][x-1]+a[y][x]+a[y-1][x+1]
if w.count('MAS')+w.count('SAM') == 2:
total += 1
print(total)
PythonHighlight
09-15 : Add Padding as well but with on layer (‘Z’) only.
17-23 : Check both diagonal to check again ‘SAM’ and ‘MAS’.
Day 3
https://adventofcode.com/2024/day/3
Part1
f = open("Day 3 - input.txt", "r")
i = f.read().strip()
r = 0
while True:
a = i.find("mul(")
if a == -1:
break
i = i[a:]
z = ['','']
x = 0
y = 0
p = 0
j = 4
while True:
if i[j].isdigit():
z[p] += i[j]
j += 1
elif i[j] == ',' and p == 0:
j += 1
p = 1
elif i[j] == ')' and p == 1:
x = int(z[0])
y = int(z[1])
j += 1
break
else:
break
i = i[j:]
r += x * y
print(r)
PythonHighlight
05-08 : Found “mul(“. If no more can be found, end the loop and print the result.
10-29 : Removed the found “mul(” and read the next data, compare if it were in format “number x,number y)”. If yes, put those numbers into x and y, otherwise keep x and y as ‘0’.
31-32 : Deleted the verified information. Add x * y into the record, and retested the loop until “mul” not found.
Part2
f = open("Day 3 - input.txt", "r")
i = f.read().strip()
r = 0
just_start = True
while True:
a = i.find("mul(")
b = i.find("don't()")
c = i.find("do()")
if b < a and b < c:
i = i[c:]
elif a == b == c == -1:
break
else:
i = i[a:]
z = ['','']
x = 0
y = 0
p = 0
j = 4
while True:
if i[j].isdigit():
z[p] += i[j]
j += 1
elif i[j] == ',' and p == 0:
j += 1
p = 1
elif i[j] == ')' and p == 1:
x = int(z[0])
y = int(z[1])
j += 1
break
else:
break
r += x * y
i = i[j:]
print(r)
Python07-13 : Found the position of “mul(“, “don’t()” and “do()” and compare which was in the front.
- 11-12 : If “don’t()” was in the front, delete everything until the “do()” position.
- 13-14 : If all of them not found, quite the loop and report the result.
- 15-16: Delete all data before “mul(“
18-38 : Same as part 1
Day 2
https://adventofcode.com/2024/day/2
Part 1
f = open("Day 2 - input.txt", "r")
count = 0
for i in f:
j = list(map(int, i.split()))
if j[0] > j[1]:
m = -1
elif j[0] < j[1]:
m = 1
else:
continue
for x in range(len(j)-1):
if 0 < (j[x+1] - j[x])*m < 4:
t = True
else:
t = False
break
if t:
count += 1
print(count)
PythonHighlight
06-09 : If the levels were decreasing, set m to -1, otherwise m = 1 for increasing.
13-17 : Comparing the level with the next level and timed m. If the result was within 0 – 4, i.e. 1, 2 & 3, made t become True other made it False and ended the loop.
19-20 : We used the t to ensure all levels tested and met the requirement, then count + 1.
Part 2
f = open("Day 2 - input.txt", "r")
count = 0
for i in f:
j = list(map(int, i.split()))
if j[0] > j[1]:
m = -1
elif j[0] < j[1]:
m = 1
else:
m = 0
t = False
for x in range(len(j)-1):
if 0 < (j[x+1] - j[x])*m < 4:
t = True
else:
t = False
break
if not t and x == len(j) -2:
t = True
if not t:
k = j.copy()
del k[x]
if k[0] > k[1]:
m = -1
elif k[0] < k[1]:
m = 1
else:
m = 0
for y in range(len(k)-1):
if 0 < (k[y+1] - k[y])*m < 4:
t = True
else:
t = False
break
if not t:
k = j.copy()
del k[x+1]
if k[0] > k[1]:
m = -1
elif k[0] < k[1]:
m = 1
else:
m = 0
for y in range(len(k)-1):
if 0 < (k[y+1] - k[y])*m < 4:
t = True
else:
t = False
break
if not t and x != 0:
k = j.copy()
del k[x-1]
if k[0] > k[1]:
m = -1
elif k[0] < k[1]:
m = 1
else:
m = 0
for y in range(len(k)-1):
if 0 < (k[y+1] - k[y])*m < 4:
t = True
else:
t = False
break
if t:
count += 1
print(count)
PythonHighlight
04-19 : Completely same logic as part 1.
20-21 : If the test result is failed but it is the second last level, take it as pass since the last level was bad.
22-37 : When we detected a bad level and it was not the second last level, we will re-test it by deleting this level.
38-54 : If still failed, put the level back and deleted the next level and retest.
55-71 : If still failed, put the next level back and deleted the previous level and retest, but need to ensure that the existing level is not the first level,
Day 1
https://adventofcode.com/2024/day/1
Part 1
f = open("Day 1 - input.txt", "r")
l = []
r = []
total = 0
for i in f:
l.append(i[0:5])
r.append(i[8:13])
l.sort()
r.sort()
for x in range(len(l)):
c = abs(int(r[x])-int(l[x]))
total += c
print(total)
PythonHighlight
09-10 : Sorted both left and right data from smallest to biggest
12-14 : Found the different, i.e. absolute value, then added to the total.
Part 2
f = open("Day 1 - input.txt", "r")
l = []
r = []
total = 0
for i in f:
l.append(i[0:5])
r.append(i[8:13])
l.sort()
r.sort()
for x in l:
c = int(x) * r.count(x)
total += c
print(total)
PythonHighlight
09-10 : sorted both left and right data from smallest to biggest
12-14 : Got the number from left one by one and count with right. Then, times the number with numbers of count in right and added to total.
Please give your variables meaningful names, to make your code easier to follow.
Thanks, it is a very good comment. But, somehow when I read the code with full name, it make myself confusing.. But, I am going to share my code, readable is very important. Let me start doing this in Day 6 challenge.