I know what you're thinking right now - a monarch problem? How did Raymond know I had a monarch problem? What can I say, with great age comes great wisdom, or, more likely, random code challenges. I've mentioned "rendezvous with cassidoo" before as one of the newsletters I subscribe to. Authored by the very interesting Cassidy Williams, this short and sweet newsletter always has interesting content and always ends with a basic code challenge, what she calls her 'interview question of the week'. This weeks question was pretty fun:

Given an array of strings representing the names of monarchs and their ordinal numbers, write a function that returns the list of names sorted first by name and then by their ordinal value (in Roman numerals), in ascending order.

Here's two examples:

> sortMonarchs(["Louis IX", "Louis VIII", "Philip II", "Philip I"])
> ["Louis VIII", "Louis IX", "Philip I", "Philip II"]

> sortMonarchs(["George VI", "George V", "Elizabeth II", "Edward VIII"])
> ["Edward VIII", "Elizabeth II", "George V", "George VI"]

I decided to take a stab at this with BoxLang and in doing so, ran into some interesting tidbits I thought I'd share. First, let's handle the Roman problem.

Those Pesky Romans

Quick trivia question for you. What is the only number you can't represent in Roman numerals?

Zero.

Ok, that being said, my first task was to build a generic "roman numeral to integer" conversion method, and for that, I totally cheatedwent to AI for a bit of help. I knew I was going to be writing in script, and with BoxLang still being kinda new, simply asked for a JavaScript solution:

"write javascript code to convert roman numerals to integers"

I used Google Gemini for this, and one of the things I like about their code solutions is that they almost always provide test calls with expected solutions. Here is their solution. (The original solution made use of console.log, so to make it easier for you, dear reader, I made it output to the DOM.)

See the Pen Roman to Int by Raymond Camden (@cfjedimaster) on CodePen.

The solution seems sensible enough, although I would not have bothered making a variable for the uppercase version of the input. I'd just have done: s = s.toUpperCase(). Outside of that, the logic makes sense to me.

Ok, so now to convert this to BoxLang. I'll share the complete rewrite below, but let me share the interesting bits first.

  • Arrays in BoxLang start with 1, not 0.
  • An interesting part of the JS code is that nextVal will, one time, reference an index past the end of the length of the string, which is null, and check against romanMap, which is basically asking the map for a null key. JavaScript handled that, still returning null, but I had to break that apart a bit in BoxLang.
  • BoxLang automatically scopes variables defined in a method to the method itself, so I was able to get rid of let and const.
  • In the original code, you can see where Gemini mentioned you could throw an error on invalid input instead of NaN. I did that in BoxLang.

And that's basically it. I also changed the console logs to println statements instead. You can test this out here:

Cool. The Roman problem is solved! Now to sorting.

Putting On Our Sorting Hat

Sorting now comes down to a simple callback function provided to the built-in sort method. Here's how I did it:

function sortMonarchs(arr) {
  return arr.sort((a, b) => {
    if(a === b) return 0;
    // split into names if necessary
    parts = a.listToArray(" "); 
    alpha.roman = romanToInt(parts.last());
    alpha.name = parts.slice(1, parts.len())[1];
    parts = b.listToArray(" "); 
    beta.roman = romanToInt(parts.last());
    beta.name = parts.slice(1, parts.len())[1];

    if(alpha.name < beta.name) return -1;
    if(alpha.name > beta.name) return 1;
    if(alpha.name === beta.name) {
      return alpha.roman - beta.roman;
    }
    return 1;
  });
}

As per the requirements, I sort by name first, then the value of the roman numeral. I tested like so:

println( sortMonarchs(["Louis IX", "Louis VIII", "Philip II", "Philip I"]));
// should be:  ["Louis VIII", "Louis IX", "Philip I", "Philip II"]

println(sortMonarchs(["George VI", "George V", "Elizabeth II", "Edward VIII"]));
// should be: ["Edward VIII", "Elizabeth II", "George V", "George VI"]

You can see the output below:

Let me know what you think. Most likely, the code I wrote could be written any "tighter" and if you do end up rewriting it, share a link below!