Category Archives: AoC 2024

AoC 2024

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)
Python

Highlight

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)
Python

Highlight

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)
Python

Highlight

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)
Python

Highlight

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)
Python

Highlight

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)
Python

Highlight

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)
Python

Highlight

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)
Python

Highlight

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)
Python

07-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)
Python

Highlight

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)
Python

Highlight

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)
Python

Highlight

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)
Python

Highlight

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.