Advent of Code 2023: Pascal, Modula-2 and Aztec C

It's now the end of January and I'm still obsessed. Not so much with the Advent of Code problems themselves, but seeing what solutions might look like in other languages under CP/M 2.2. The two languages I've tried so far are the FTL (HiSoft) Modula-2 compiler, version 1.30 and Manx Software's Aztec C compiler, version 1.06D.

With the sad death of Niklaus Wirth on January 1st, I decided to start with Modula-2 - a language I'd never coded in before. I find that writing a prime number generator(**) is a good way to pick up the basics of a new language, My effort generates the 168 prime numbers less than 1,000 in 17 seconds(*).

A couple of pages from Niklaus Wirth's Programming in Modula-2, third edition.

Moving onto the Day 1 Advent of Code puzzles (**) - part 1 completes in 10 seconds. This is twice as fast as my Turbo Pascal implementation. I'd expected this because Modula-2 has a cardinal (unsigned integer) type, meaning that I didn't need to use an equivalent of my Pascal Big-ish Integer library.

Part 2 was more surprising. My first implementation took 4 minutes 15 seconds to run, versus 47 seconds in Turbo Pascal. Diagnostics demonstrated that the pos function was amazingly slow if the string to be searched was shorter than the substring to be found. Checking for this condition before calling pos reduced the execution time of Day 1, part 2 by around 30% to 2 minutes 58 seconds. Pos is still slow! (and of course, if I do something similar to my Turbo Pascal solution I would almost certainly improve the 47 seconds it currently takes).

    WHILE ((spos > 0) OR (epos > 0)) & (jdx <= ALLD) DO
      (* Avoid pos if the length of the substring is longer than the whole string (llen) *)
      IF (spos > 0) & (Length(fwd[jdx]) < llen) THEN
        fdx := Pos(fwd[jdx],line,0);
        IF fdx # HIGH(line)+1 THEN
          IF fdx < spos THEN
            spos := fdx;
            anss := jdx
          END
        END
      END;

I then moved onto Aztec C. This felt rather more familiar as it's based on Kernighan and Ritchie's original C implementation (before ANSI and others got hold of it ... the rest is history, as they say). The prime number generator churns out the primes less than 1,000 in 35 seconds. Day 1 of Advent of Code takes 16 seconds for part 1 and 1 minute 47 seconds for part 2. I also tried part 1 of day 15 - which completes in 30 seconds (almost twice as fast as my Turbo Pascal solution).

If you compare the execution times there's no clear winner - if you judge the three languages solely by that yardstick. But if I was developing software for CP/M and had a free choice of tool, then Turbo Pascal would win every time. The IDE and compiler work really well, and the code produced seems to execute in a reasonable time. Modula-2 just seems a little to niche for comfort and I'm not convinced that more nasties like the pos issue don't exist. The Aztec C compiler irritates me as there's no integrated editor. Worse, the compilation process involves three separate steps (compiler, assembler and linker) before you get a result. The linker is rather slow, too.

Benchmark Summary(*)

Turbo Pascal 3.01AFTL Modula-2 1.30Aztec C 1.06D
Primes less than 100013 seconds17 seconds35 seconds
Day 1, part 1
(Trebuchet?!)
18 seconds10 seconds16 seconds
Day 1, part 2
(Trebuchet?!)
47 seconds178 seconds107 seconds
Day 15, part 1
(Lens Library)
57 secondsN/A30 seconds
Summary of results discussed in this article

(*) All of these figures were produced on the RC2040 that I built earlier on this month. I'd expect them to be slightly better on the real RC2014 hardware!

(**) Advent of Code 2023 repository and Prime number generator repository