A typical "lost places" photo: The door to the vault of formerly luxurious abandoned bank. The round heavy steel door is standing open and on the inside we see lots of little lockers, most of them open.

Day 1: Secret Entrance

Note: If you’re attempting to read this as a Fediverse post, you might find it rather confusing. I recommend using a web browser to read it properly, following this link.

The challenge

On day 1, we have to open a closed door with a rotary dial and a keypad. The dial has 100 positions from 0 to 99. We have a (long) list with instructions like "L42" or "R4", meaning “turn 42 clicks to the left” or “turn 4 clicks to the right”, respectively.

If we start at position 50, we might sometimes land on position 0 after a turn. The number of times we land on 0, is actually the password to enter on the keypad.

The idea

Having the list of instructions, we apparently need to do the following:

Take our current position, read the instruction, calculate at which position we land, and if it is 0, add 1 to our zero counter.

Turning right, means increasing the position by the given number; turning left, decreasing it.

Obviously, if we pass 99, we start at 0 again. Say, our position is 50 and our instruction is R52. The position would be 102. 100 is zero, 101 is 1, 102 is 2.

The mathematical operation corresponding to this, is called the module.

We write n%k as the rest of the division of n/k.

What happens if we start at 50 and our instruction is L52? Obviously, our new position would be -2, which would translate to 98.

What is n%k if n is negative? Often, n%k is understood as -|n|%k, which in our case would mean: -2%100 = -2. We would have to add 100 if position/100 is negative.

The programming language of my choice, Perl (preinstalled on every UN*X and MacOS machine), does this automatically: The operation n%k will always return a positive number. If n is negative, the result of n%k is k – |n|%k. Exactly what we want.

So, this is the code:

Perl code
Advent Code Day 1, part 1 Actual code (accessible): https://codeberg.org/M1na/AOC25/src/branch/main/aoc2501a.pl

It should be rather self explanatory. I’ll just give a few remarks:

The program expects an input file (with the instructions) as command line parameter. The diamond operator <> reads the file given line by line and stores the current line in the magic variable $_ until there is nothing more to read.

The regular expression m/(/D)(/d+)/ is matched against $_. \D stands for non-digit character, whilst \d+ represents a non-empty sequence of digits.

What is enclosed in the first parenthesis is stored in the special variable $1, what is in the second in $2.

eq is the equality operator for strings. == is reserved for numbers.

Perl interprets every non-zero number as a boolean true, 0 as false.

The expression, a or b means the following:

if a is true, continue, if not, do b!

The updated challenge

Actually, we got it wrong in the first part. We were not only supposed to count the times we land on 0, but also every time, the dial passes that number.

The updated idea

Whilst certainly it would have been possible to use some smart arithmetic, I thought: My time is more valuable than my computer’s, so I decided to take it easy: After each click during dialling, check if the number is zero. So this is the code:

Perl code
Advent Code Day 1, part 2 Actual code (accessible): https://codeberg.org/M1na/AOC25/src/branch/main/aoc2501b.pl

One thing worth mentioning here, might be the range operator (a..b) which simply counts from a to b in steps of 1.

And there is the part $zeroes++ unless $position % 100 which might look rather unusual. unless condition is another way of writing if not condition. You can use both keywords.

In Perl, if an if/unless statement is followed by a single instruction, instead of writing

unless($position % 100) {
    $zeroes++
}

you may use the above notation, which makes it shorter to write and nicer to read.

An alternative idea

OK. After having finished the second part, it kept annoying me that I solved the second part so ungracefully, so I redid it in a nicer fashion:

Perl code

I abbreviated the variable names, as you can see, and I also made heavy use of the ternary operator: condition ? this_if_true : that_if_false

In each iteration, we start with a value of $p between 0 and 99.

Instead of reading an explanation, look at these values for $p and $n and try to figure out, how the expression gives the correct result for the increase in $z:

pnz increase
1001
102302
10-301
10-2303
0-2302

Iโ€™d love to discuss my and your solutions with you!

I have created a โ€œleaderboardโ€ (so far I am the only person in it). Feel free to join it!

Just drop me a personal message to my main Fediverse account or drop me an email (address at the bottom of the page), and I shall send you the join code.

Fediverse Reactions

Comments

17 responses to “Day 1: Secret Entrance”

  1. @AdventOfCode Thanks for your post!
    I realise there's no global leaderboard any more (hurrah), but could you wrap your solution in spoiler tags so that people who want to solve the problem themselves won't accidentally see it?

    1. Mina Avatar
      Mina

      You’re right! I’ll change thatimmefiately!

    2. Minas Advent of Code Avatar
      Minas Advent of Code

      Done! Thank you!

  2. @AdventOfCode Mathematical purists can get very het up by what exactly "modulo" should do when it comes to negative numbers โ€” perhaps like the way there's still argument about whether int(-0.5) should be 0 or -1.
    Rust now gives you both: -5 % 2 = -1 and -5.rem_euclid(2) = 1. Of course you have to be aware that they exist.

    1. @RogerBW

      Smart move by the Rust people!

      Instead of opening a rather pointless discussion, just give options.

      Given the language's rather rigid structure, I find this flexibility quite appealing.

      @AdventOfCode

  3. @AdventOfCode reading your Perl solutions is always a joy!

    1. @hamatti

      So glad to hear that!

      I will definitely try to have learned Python by next year.

      I'm currently trying to get into a paid course in data science. In that area, Python it is.

      @AdventOfCode

      1. @hamatti

        In any case, it was you, who inspired me to try this year to blog about the solutions.

        @AdventOfCode

        1. @mina @AdventOfCode โค๏ธ so happy to hear

  4. @AdventOfCode ah, I remember how much your Perl solutions broke my brain last year. They're so cool. I'm old enough to have used Perl in anger at the very beginning of my career, but I think I've forgotten ~all of it.

    1. @papajohn

      Thanks for compliment!

      @AdventOfCode

  5. @AdventOfCode I rather enjoyed that part 2's password method 0x434C49434B reads as CLICK when you convert it from hex to ASCII. I decided to use Fortran again this year … I wonder how many days it will take before I have to change from f77 to f90 because of recursion!

    1. @psychotimmy

      I should have tried to do the hex conversion, too.

      Regarding the recursion question:

      Recursion always looks so smooth and elegant, but there's always a way to write a recursive algorithms in an iterative way, with the added benefit of not risking to run into some deep recursion.

      So, at least for the last challenges, I'm gonna try to avoid recursion.

      But: does F77 have dynamic arrays?

      @AdventOfCode

      1. @mina @AdventOfCode I rather like using recursion for some algorithms!

        However there was one day last year where most people said recursion was *definitely* required and I'd written an iterative algorithm that was just as good, if not better than most of the recursive solutions I saw!

        Dynamic arrays / dynamic memory in f77 – definitely not (you can simulate them using files if absolutely necessary).

        One other reason to love f77 for AoC is that it has a complex number type (and operators) which is useful for representing coordinates – helpful for a couple of last year's problems.

        1. @psychotimmy

          We shall see, how it goes!

          @AdventOfCode

  6. @AdventOfCode

    I use (x + 100 – y) % 100 because I can't be bothered to memorize which language does what under these circumstances, and just make it explicit how I _want_ it to behave. :-/

    1. @jochie

      Makes total sense to me.

      Better to be explicit than assuming.

      @AdventOfCode

Leave a Reply

Your email address will not be published. Required fields are marked *