There is a known bug in the Live Code Editor. If you’re not able to see the content, try clicking on another file (like
package.json)to make it work. I’ll address this issue later.
I’ve always enjoyed data structures and problem-solving questions. I’ve been practicing them on and off for quite some time now. Last year, my husband told me about Advent of Code, but it slipped my mind back then. This year, around 16th December, I realised it was still ongoing. Since I was on a Christmas break, I thought I’d give it a try.
I was already late, but I didn’t want to overthink it. I decided to see how many problems I could solve before 1st January 2026. To my surprise, I managed to solve 18 out of 24 problems. I could have pushed a bit more, but once office reopened and the New Year / Christmas break feeling faded, I decided to stop. I didn’t want to force it.
In this blog, I’ll talk about three of my favourite problems from Advent of Code 2025. I’ve shared all the solutions I managed to solve on GitHub.
GitHub repo:
https://github.com/cosmologist10/advent-of-code
The problems I’ll be discussing here are:
Day 7
Day 8
Day 11
Day 7
Question: https://adventofcode.com/2025/day/7
Day 7 started off as an easy problem in Part 1, but Part 2 quickly became tricky. The challenge wasn’t about calculating a single path anymore, it was about finding all possible paths. At first, I instinctively thought about recursion, but the way I had solved Part 1 made it hard to extend that idea cleanly.
Initially, I was literally drawing paths and lines to reason about it, which only made things more confusing. After stepping back and thinking about it carefully, I realised that instead of drawing anything, I could simply move forward and track my position. Wherever I was, the direction was naturally implied. From there, recursively exploring both left and right paths and summing them up gave the correct answer.
This problem is interesting because it’s one of those early Advent of Code questions where brute force almost works, but the moment you try to scale it, you’re forced to rethink how you model the problem, something many people seem to hit around this point in the calendar.
import data from './input.txt'; const main = () => { let input = data.trim().split("\n") input = input.map(e => e.split('')) let height = input.length let width = input[0].length let row = -1; let col = -1 for(let i=0; i < height; i+=1){ for(let j=0; j < width; j+=1){ if(input[i][j] === 'S'){ row = i col = j break } } } let memo = new Map() const ways = (r, c) => { if(r === height) return 1 if(c < 0 || c >= width) return 0 const key = `${r}-${c}` if(memo.has(key)) return memo.get(key) let count = 0 if(input[r][c] === '.'){ count = ways(r+1, c) }else if(input[r][c] === '^'){ count = ways(r+1, c-1) + ways(r+1, c+1) } memo.set(key, count) return memo.get(key) } console.log(ways(row+1, col)) } main()
Day 8
Question: https://adventofcode.com/2025/day/8
When I started Day 8, I was honestly a bit intimidated. It involved straight lines and looked very math-heavy at first glance. My initial reaction was hesitation, but I told myself to give it an honest try instead of assuming it was too hard.
Once I slowed down and understood the math properly, I realised that this problem actually belonged to one of my favourite algorithm families: Union-Find. That made everything click. I implemented it, finished Part 1, and when I moved on to Part 2, the required change was surprisingly small.
That’s when I realised something I really like about Advent of Code, if Part 2 doesn’t require a complete rewrite, it usually means you solved Part 1 in the right way. Many people mention Day 8 as a confidence-building problem once the right abstraction is identified, and I felt the same.
import data from "./input.txt" class UnionFind{ constructor(N){ this.parent = [...new Array(N).keys()] this.size = new Array(N).fill(1) this.last_coordinate = []; } find(node){ if(this.parent[node] !== node){ this.parent[node] = this.find(this.parent[node]) } return this.parent[node] } union(node1, node2){ const node1_parent = this.find(node1) const node2_parent = this.find(node2) if(node1_parent === node2_parent) return false; if(this.size[node1_parent] >= this.size[node2_parent]){ this.parent[node2_parent] = node1_parent this.size[node1_parent] += this.size[node2_parent] }else{ this.parent[node1_parent] = node2_parent this.size[node2_parent] += this.size[node1_parent] } this.last_coordinate.push([node1,node2]) return true } get_lastcordinate(){ return this.last_coordinate.pop() } } const main = () => { const lines = data.trim().split('\n') const pts = lines.map((line) => { const [x,y,z] = line.split(',').map((v) => parseInt(v,10)) return [x,y,z] }) const edges = [] for(let i = 0; i < pts.length; i +=1){ const [x1,y1,z1] = pts[i]; for(let j=i+1; j <pts.length; j +=1){ const [x2,y2,z2] = pts[j]; const dx = x1 - x2; const dy = y1 - y2; const dz = z1 - z2; const d2 = dx*dx + dy*dy + dz*dz; edges.push([d2, i, j]) } } edges.sort((a,b) => a[0] - b[0]) const union_find = new UnionFind(pts.length) for(let k = 0; k < edges.length; k +=1){ const [_,i,j] = edges[k] union_find.union(i,j) } const [x,y] = union_find.get_lastcordinate() console.log(pts[x][0]*pts[y][0]) } main()
Day 11
Question: https://adventofcode.com/2025/day/11
Day 11 felt familiar right from the start. It had a very LeetCode-like feel, and I immediately thought about recursion and memoization. The problem statement also subtly hinted that there wouldn’t be cycles while counting paths, so I initially solved Part 1 using plain recursion.
Part 2 looked very similar on the surface, but there was a small and tricky change. I tried adding memoization and tracking visited indices, but I kept running into infinite loops. I spent quite some time trying to figure out the missing edge case, but nothing worked. Since Advent of Code usually has one long and heavy problem like this, I decided to leave it for the day.
The next day, I came back with a different mindset. Instead of treating it as one big problem, I divided it into three smaller subproblems. I then applied the same logic as Part 1 to each of them. This time, memoization made sense because I didn’t want to recompute the same paths repeatedly, and it finally worked.
Day 11 is a good example of a problem where memoization isn’t optional; it’s the difference between something that runs and something that doesn’t. A lot of people seem to mention this as one of the days where recognizing overlapping subproblems really pays off.
import data from './input.txt' const adjaceny_list = new Map() const memo = new Map() const main = () => { const input = data.trim().split("\n") for(let i =0; i < input.length; i +=1){ adjaceny_list.set(input[i].split(':')[0], input[i].split(':')[1].trim().split(' ')) } console.log(( get_count('svr', 'fft') * (get_count('fft', 'dac')) * (get_count('dac', 'out')) ) + ( get_count('svr', 'dac') * (get_count('dac', 'fft')) * (get_count('fft`', 'out')) ) ); } const get_count = (starting_point, end_point) => { if(memo.has(`${starting_point}-${end_point}`)) return memo.get(`${starting_point}-${end_point}`) if(starting_point === end_point){ return 1; }; const nodes = adjaceny_list.get(starting_point) if(nodes && nodes.length){ let sum = 0 for(let i = 0; i < nodes.length; i += 1){ sum += get_count(nodes[i], end_point) } memo.set(`${starting_point}-${end_point}`, sum) return sum; }else{ memo.set(`${starting_point}-${end_point}`, 0) return 0 } } main()
Final Thoughts
One thing I really liked about Advent of Code is the mindset behind it. Over time, I ended up reading a bit about how the organiser thinks about the event. It’s very clearly not meant to be competitive by default. The idea is to encourage people to try, explore, and enjoy the process of problem solving. If someone wants competition, they can always create a private leaderboard, but that’s optional, and it shouldn’t take away from people who are doing something creative with the problems.
And people really do all kinds of things with it. Some solve the problems using a new programming language they’re learning. Some build interpreters or compilers and run the solutions on top of that. Others focus purely on optimisation, or on writing the cleanest possible code. There’s no single “right” way to do Advent of Code, and I really liked that openness.
Since this was my first time, I kept my goal simple, just try to solve the problems and see how it feels. I didn’t want to optimise for speed or do anything fancy. I just wanted to sit with the problems and enjoy the thinking. If I get a chance to do it again next year, I’d like to try something different, maybe experiment with a new language, or approach the problems in a more structured or creative way.
That freedom to choose your own goal is probably what makes Advent of Code so enjoyable.
A Fun Update
I also got the chance to attend an Advent of Code meetup in Oslo this year. It was a fun session where people shared their solutions and discussed different optimization approaches. I even presented my Day 8 solution on stage and talked through my own approach. It was genuinely enjoyable, and I’m really glad I decided to attend.
