Advent of Code 2025 Day 1

I’ve heard about the Advent of Code before. I have been nervous to attempt it because I struggle with programming problems.

But now that I’ve graduated and have more time on my hands, I can’t find an excuse why I shouldn’t complete an attempt. This year will be much easier too because there are only 12 days rather than 25. I’ve decided to blog about the process so I can reflect on other people’s attempts and see how I can level up as a programmer.

I am also determined to go back and finish the other years too.

With that being said, let’s look at the Day 1 problem.

Part 1

def rotation(origin, rotation):
  position = origin
  dir, amount = rotation[0], int(rotation[1:])
  if dir == "L":
    position = position - amount
  elif dir == "R":
    position = position + amount
  
  if position < 0 or position > 100:
    position = position - math.floor(position / 100) * 100
  
  if position == 100:
    position = 0
      
  return position

I’ve kept it simple here. I add the rotation amount to the original position and then subtract/add multiples of 100.

However, in my other attempts, I’ve noticed that my solution for Day 1 can’t be extended to Day 2. So I spend a few hours having to rethink my logic.

Part 2

This is my original attempt

def rotation(origin, rotation):
    position, past_zero = origin, 0
    dir, amount = rotation[0], int(rotation[1:])
    if dir == "L":
        position = position - amount
    elif dir == "R":
        position = position + amount

    if position < 0 or position > 100:
        past_zero = past_zero + abs(math.floor(position / 100))
        position = position - math.floor(position / 100) * 100

        if origin == 0:
            past_zero = past_zero - 1

        if position == 100 or position == 0:
            past_zero = past_zero + 1
            position = 0

    return [position, past_zero]

So I think my problem is that I don’t try to rewrite the original code and then I’m struggling to work within the constraints I’ve set for myself.

That means I have two options: rethink the problem and tweak it OR commit to the hole that I’ve dug myself into.

Let’s look at both.

Bruteforcing. Rather than trying to think about the final position after each rotation, I can keep it simple and simulate each click. That will just require a simple if statement to see if I passed GO zero.

Then you get this solution.

def rotation(origin, rotation):
    position, past_zero = origin, 0
    dir, amount = rotation[0], int(rotation[1:])

    for _ in range(amount):
        if dir == "L":
            position = (position - 1) % 100
        else:
            position = (position + 1) % 100

        if position == 0:
            past_zero = past_zero + 1

    return [position, past_zero]

Whew! Sometimes I don’t have to work so hard.

Optimised Approach. There was some incorrect logic in my first version which gave a lower value. Sometimes, the syntax can obscure a straightforward solution. I made a few syntactic changes:

  • position - math.floor(position / 100) * 100 is the equivalent of position % 100
  • Python has a floor division expression so math.floor(position / 100) can be changed to position // 100.

One method for calculating whether the zero boundary was crossed is by comparing the previous and final rotations. 1 needs to be subtracted as there can be overcounting while decrementing from 100 to 99. past_zero = (position - 1) // 100 - (position - amount - 1) // 100

This is the final solution:

def rotation(origin, rotation):
    position, past_zero = origin, 0
    dir, amount = rotation[0], int(rotation[1:])
    if dir == "L":
        past_zero = (position - 1) // 100 - (position - amount - 1) // 100
        position = position - amount
    else:
        position = position + amount
        past_zero = position // 100

    return [position % 100, past_zero]

Final thoughts

My takeaway lessons were:

  • Keep things simple. Bruteforcing is always an option.
  • Rewrite Day 2 if you need to. Don’t think that you need to retain the Day 1 code.
  • If the Day 2 solution isn’t easily solvable, then there was a problem with Day 1.
  • I learnt about math expression statements that I don’t use commonly.
post

Front-end Date Pickers

HugoTea:

The Gov.uk design team published research around data entry for dates https://designnotes.blog.gov.uk/2013/12/05/asking-for-a-date… Ultimately they found the best experience was three text boxes, day, month and year. They also have this “pattern” for helping with implementation https://design-system.service.gov.uk/patterns/dates/

joelanman:

(I worked on this pattern) Our guidance is to accept both names and numbers in the back end so people can enter either. In our testing, text inputs (with a numeric keyboard on mobile) is better than selects. Some people struggle with using selects, we don’t see those issues in text inputs. That guidance maybe be about people not knowing the order of the inputs (DD MM YY, MM DD YY) but our pattern is clearly labeled for each input so we don’t get that issue.

link

You Should Write An Agent

Code

The full code from the article:

import json
import subprocess
from openai import OpenAI

client = OpenAI()

tools = [{
    "type": "function",
    "name": "ping",
    "description": "ping some host on the Internet",
    "parameters": {
        "type": "object",
        "properties": {
            "host": {
                "type": "string",
                "description": "hostname or IP",
            },
        },
        "required": ["host"],
    },
}]

context = []

def ping(host=""):
    try:
        result = subprocess.run(
                ["ping", "-c", "5", host],
                text=True,
                stderr=subprocess.STDOUT,
                stdout=subprocess.PIPE)
        return result.stdout
    except Exception as e:
        return f"error: {e}"

def call(tools):
    return client.responses.create(model="gpt-5", tools=tools, input=context)

def tool_call(item):
    result = ping(**json.loads(item.arguments))
    return [item, {
        "type": "function_call_output",
        "call_id": item.call_id,
        "output": result
    }]

def handle_tools(tools, response):
    if response.output[0].type == "reasoning":
        context.append(response.output[0])
    osz = len(context)
    for item in response.output:
        if item.type == "function_call":
            context.extend(tool_call(item))
    return len(context) != osz

def process(line):
    context.append({"role": "user", "content": line})
    response = call(tools)

    while handle_tools(tools, response):
        response = call(tools)
    context.append({"role": "assistant", "content": response.output_text})
    return response.output_text

def main():
    while True:
        line = input("> ")
        result = process(line)
        print(f">>> {result}\n")

if __name__ == "__main__":
    main()

https://transitions.substack.com/p/what-burning-26-billion-prompt-tokens

https://github.com/vinhnx/vtcode

https://ampcode.com/how-to-build-an-agent

https://github.com/gustofied/P2Engine

https://x.com/rerundotio/status/1968806896959402144

https://simonwillison.net/2025/Aug/9/

https://news.ycombinator.com/item?id=45840088

https://news.ycombinator.com/item?id=45891968

link

MC_squaredJL via Reddit:

I think an AI interface could help with the problem. Specific issues:

  • New patients: Not all adult NP need to be scheduled 1 hour with Dr and then 1 hour in hygiene which is normal protocol. We gave them a flowchart and list of questions to determine if they should be scheduled as above or for 90 minutes with the hygienist. Literally 3 questions. I have a 17yo new patient scheduled as an adult. She could have been scheduled 1 hour in hygiene.
  • We have 1 intraoral scanner for 2 docs. We have color coded the appointments that need the scanner and told them how to offset the appointment so assistants do not need the scanner at the same time. My partner and I have crown preps scheduled at the exact same time today. Twice.
  • Last week it was root canals at the same time. Also equipment needed at the same time.
  • They do not get the concept of scheduling for production. I’ve literally had days that my first 3 hours were $0 because they scheduled crown seats, denture appointments, surgical follow-ups.

Reading the comments, it looks like the underlying issue is lack of SOP training. However, despite a lot of training and meetings, it’s understandable that it’s difficult to apply protocols in the moment. Especially because receptionists will lack the understanding of why it’s important to separate appointments so that equipment doesn’t have to be shared.

AI’s Dial-Up Era. The essay argues that AI is in its dial-up era for two reasons:

  1. AI is still in its infancy stage, where the benefits brought by the technology have increased productivity and jobs, rather than decrease/eliminate it. Looking at other industries, it’s because there is still demand and its growth hasn’t been saturated.
  2. AI is showing parallels to the dot-com crash, where a lot of companies jumped on the WWW hype. As the author points out, a lot of companies are becoming overvalued and do not show any Product Market Fit.

The article shows that Automation hasn’t reduced jobs (apart from the tech sector, but that’s a different story) for several reasons:

  • real-world complexity
  • regulatory/insurance hurdles
  • Jevons Paradox: “economic principle that a technological improvement in resource efficiency leads to an increase in the total consumption of that resource, rather than a decrease”.

ByteCoder:

I feel like we’re back in the mainframe era. A lot of software can’t operate without an internet connection. Even if in practice they execute some of the code on your device, a lot of the data and the heavyweight processing is already happening on the server. Even basic services designed from the ground up to be distributed and local first - like email (“downloading”) - are used in this fashion - like gmail. Maps apps added offline support years after they launched and still cripple the search. Even git has GitHub sitting in the middle and most people don’t or can’t use git any other way. SaaS, Electron, …etc. have brought us back to the mainframe era.

bccdee:

I find the argument for the bubble to be extremely straightforward.

Currently, investment into AI exceeds the dot-com bubble by a factor of 17. Even in the dot-com era, the early internet was already changing media and commerce in fundamental ways. November is the three-year anniversary of ChatGPT. How much economic value are they actually creating? How many people are purchasing AI-generated goods? How much are people paying for AI-provided services? The value created here would have to exceed what the internet was generating in 2000 by a factor of 17 (which seems excessive to me) to even reach parity with the dot-com bubble.

airspresso:

I keep hearing that LLMs are trained on “Internet crap” but is it true? Karpathy repeated this in a recent interview, that if you’d look at random samples in the pretraining set you’d mostly see a lot of garbage text. And that it’s very surprising it works at all.

The labs have focused a lot more on finetuning (posttraining) and RL lately, and from my understanding that’s where all the desirable properties of an LLM are trained into it. Pretraining just teaches the LLM the semantic relations it needs as the foundation for finetuning to work.

ChatGPT Atlas is an Anti-Web: The Browser That’s Anti-Web. I’m always late to the party, so I haven’t tried out Atlas. I will also never will because I’m pretty anti-Chrome.

But Anil Dash gives it a good review:

  • “searching” will take you a chat session, not the search engine results. Reading this made me realise how much we have taken the URL box for granted. It’s become default UX behaviour to expect search results to appear. Anil searched with the keywords “taylor swift showgirl”. I appreciated that search engine have become so good at recognising intent, because there are various branches to explore from there. Are you looking for informationa about the album? Do you want to buy tickets or merch? Or do you want to read a review? An AI search engine will have to reimagine all these things, which I never had to think about.
  • The UX is a mystery and the only way to discover it is by typing. And typing. And typing. Anil gives the example of Zork. You pick up a rock. You move left. In the OpenAI demo, the team member typed search web history for a doc about atlas core design. It goes back to Point 1, where the AI cannot recognise intent so it has to be clearly spelt out. Also, Anil points out that there is a high risk involved if you forget the correct set of magical incantations, because LLMs have a huge risk of hallunciating.
  • ChatGPT is very obviously hoovering up data. You are the customer. Warning labels are required because regular humans cannot be trusted to use the technology without self-harm. Agree.

I bought a £16 smartwatch just because it used USB-C. If you look in the right places, you will find it. A £16 smart watch is surprisingly capable, and provides the bare functions that a premium watch will.

This article goes into depth, and even hacks it! A great hacker mindset.

Accidentally writing a fast SAT solver

Going back (no pun intended) to the scheduling problem, the solution would be similar. Each “row” would be a class, and from each class, a section would be chosen for the class schedule. By changing is_valid to check for time conflicts instead of queens, the same code can be used to build a schedule.

To determine if a formula is satisfiable, first convert it to conjunctive normal form, then convert the new formula into a course catalog. Put this into a schedule builder, and you know the answer.

DecoPerson:

The attack pattern is:

  1. User goes to BAD website and signs up.

  2. BAD website says “We’ve sent you an email, please enter the 6-digit code! The email will come from GOOD, as they are our sign-in partner.”

  3. BAD’s bots start a “Sign in with email one-time code” flow on the GOOD website using the user’s email.

  4. GOOD sends a one-time login code email to the user’s email address.

  5. The user is very likely to trust this email, because it’s from GOOD, and why would GOOD send it if it’s not a proper login?

  6. User enters code into BAD’s website.

  7. BAD uses code to login to GOOD’s website as the user. BAD now has full access to the user’s GOOD account.

This is why “email me a one-time code” is one of the worst authentication flows for phishing. It’s just so hard to stop users from making this mistake.

“Click a link in the email” is a tiny bit better because it takes the user straight to the GOOD website, and passing that link to BAD is more tedious and therefore more suspicious. However, if some popular email service suddenly decides your login emails or the login link within should be blocked, then suddenly many of your users cannot login.

Passkeys is the way to go. Password manager support for passkeys is getting really good. And I assure you, all passkeys being lost when a user loses their phone is far, far better than what’s been happening with passwords. I’d rather granny needs to visit the bank to get access to her account again, than someone phishes her and steals all her money.