New exercise: Ordinal numbers

I just learned, that Ordinal Numbers is a PHP only exercise. I searched the forum and the problem-specifications for a discussion mentioning it, but I found nothing. So I propose to add it to problem-specifications.

It is a small exercise with a fair bit of conditions (as natural languages are complicated) and a type conversion. Very well suited for beginners, but there may be some nice advanced tricks a language can use to make it idomatic.

There is no real story yet, only simple instructions. Tests include:

0 -> '0'
1 -> '1st'
2 -> '2nd'
3 -> '3rd'
4 -> '4th'
10 -> '10th'
11 -> '11th'
12 -> '12th'
13 -> '13th'
62 -> '62nd'

I can imagine to add 100, 101, 112, and 123 as these are currently missing to cover all of the exceptional cases in English (as far as I know). And perhaps a bigger number like 3451.

What do you think?

Can you provide a sample solution? Is there anything interesting about this exercise other than a whole bunch of if statements? The solution might be similar to Bob in structure.

No doubt that it is similar in structure to Bob, using numbers and math operators instead of strings and RegExps. And it really is easy, so it might lend itself to a concept exercise.

There are couple of compact solutions like dstockto’s solution :

function toOrdinal(int $number): string
{
    $suffix = match (true) {
        $number === 0 => '',
        in_array($number % 100, [11, 12, 13]) => 'th',
        $number % 10 === 1 => 'st',
        $number % 10 === 2 => 'nd',
        $number % 10 === 3 => 'rd',
        default => 'th'
    };
    return $number . $suffix;
}

and more verbose ones like VickMahase’s solution:

function toOrdinal(int $number): string
{
    if ($number === 0) {
        return '0';
    }

    $lastTwoDigits = $number % 100;
    
    if ($lastTwoDigits >= 11 && $lastTwoDigits <= 13) {
        return $number . 'th';
    }
    
    $lastDigit = $number % 10;
    
    switch ($lastDigit) {
        case 1:
            return $number . 'st';
        case 2:
            return $number . 'nd';
        case 3:
            return $number . 'rd';
        default:
            return $number . 'th';
    }
}

This feels close to, or in the same family as say, but focusing on the regular and irregular ordinal suffixes in English, rather than the names/words representing numbers. So we could perhaps extend or adapt that same idea/story about deli counters and waiting in line?

Something like “Emily is 3rd in line”, “Kitsu is 12th in line” sort of thing?

st → ending in 1
nd → ending in 2 (except for 12)
rd → ending in 3 (except for 13)

th → all other numbers not ending in 1, 2, or 3.

Stand-alone zero is an exception, although I have seen 0th in old-fashioned usage, and some corner cases.

As for larger numbers, maybe we add a few just to help re-enforce the pattern that ordinal suffixes tag off the trailing number (with zero being considered as a unit with the number before it).

I could see this being an easy and nice way to practice match case in Python.

As an internationalization bonus, it seems that many spoken languages follow a similar pattern to English: they have irregular forms for the first few numbers, then a regular suffix for the remainder.

Edited to add

It also feels like (in Python) it could be about assembling strings - so practicing f-strings and if not that, str.format() and/or the older format codes. So … given a number, return a phrase that includes the number with it’s appropriate suffix:

13 → “Jane is the 13th person in line.”
33 → “Greg is the 33rd person in line.”

1 Like

I assembled some texts. The story of a deli does not fit to 0 as a value, so I would remove it. Names are subject to change, but I would rather not use names with non-ASCII characters so it will not be a challenge to handle Unicode where that is not built-in.

Introduction

Your friend Yaʻqūb works the counter at a fast growing deli in town, slicing, weighing, and wrapping orders for a line of hungry customers that gets longer every day.
He sees that waiting customers start to loose track of who is next, so he wants to have numbered tickets for them to pick when they arrive.

He is a nice person, and so he does not want to have only a number on the ticket. They shall get a proper English sentence with their name and number in it.

Instructions

Given a number and a name, your task is to produce a sentence with an ordinal numeral to print onto the ticket.
Yaʻqūb expects to use numbers from 1 up to 999.

Rules:

  • st → ending in 1 (except for 11)
  • nd → ending in 2 (except for 12)
  • rd → ending in 3 (except for 13)
  • th → all other numbers not ending in 1, 2, or 3.

Examples:

  • 'Mary', 1 → 'Mary, you are the 1st customer we serve today. Thank you!'
  • 'John', 12 → 'John, you are the 12th customer we serve today. Thank you!'
  • 'Dahir', 162 → 'Dahir, you are the 162nd customer we serve today. Thank you!'
2 Likes

There was no objection to, but also not much support for adding this. I understand that this is not an “exciting” exercise experienced programmers crave for. But I think it is a good exercise for beginners directly after doing some “math operators”, “string templating” and / or “conditionals” concept exercises.

So I will open a PR this weekend with the required documents.

1 Like

The general guideline is to get support from at least three maintainers prior to opening a PR. If you can’t convince three people here that this exercise adds value, you should probably hold off on moving to the next step.

OK, let’s get an official support voting then. Me, @oxe-b, @BethanyG and @IsaacG already somehow showed support for adding this exercise. Please express your support clearly again.

To all maintainers: May I proceed to add this exercise to the problem-specifications?

I’m not sure of the value here. I questioned the value. That’s not a show of support. Let’s get clear show of support :wink: The proposer can’t approve. I see Bethany’s interest here. That’s one.

I interpreted your liking of my post with the PR announcement as “in support of this”. Same with oxe-b liking the proposal of the texts. I do not count myself as a vote, but I do support it :slight_smile: Waiting for others to express support or objections…

Hi!

This exercise seems very similar to “two-fer” in that both require adding something to the middle of a sentence. However, this exercise here would usually need a modulus operation to decide which should be added, and also to stringify this number. So it’s like a mix between “two-fer” and “leap”.

I’ve been thinking a lot lately on how to create and structure concepts for the x86-64 track. Trying to think as the student, their journey, what they might expect.

Right now most students stop advancing after three or four exercises. This is in part due to the lack of concepts, but the overall “strangeness” and “difficulty” of coding in assembly are probably factors as well.

So, I’ve been thinking that adding a few easier exercises would make for a smoother progression.

This is why I’m generally in support of this exercise here.

1 Like

Somewhat tangential, would you add this as a practice exercise or concept exercise? Typically concept exercises don’t pull from the problem specs, but they can.

Individual tracks are welcome to add the exercise to their track. It is sometimes the case that a few add it, and then Problem Specifications ends up with it.

By the time that happens as well, there is a kind of solidification of what the stories are and the approaches different languages have taken and what works.

1 Like

As a concept exercise, there’s two problems:

  • the exercise depends on two different concepts, “string” and “arithmetic” (or something to that effect); and
  • a good “arithmetic” concept exercise would need to explore other ops and a good “string” concept exercise would need to do some parsing as well.

The second point is not much of an issue because I could use this exercise as just part of a “string” concept exercise, not the whole thing. And then I’d add some parsing as well.

The first point would depend on how concepts are organized. If “arithmetic” is a parent node to “string”, then there wouldn’t be a problem. If it’s a sibling node, however, then I think this exercise would be better as a practice exercise “unlocked” after exploring both concepts.

Right now we are at the point of creating a preliminary list of concepts and deciding “dependencies” between them.

There’s already a wip “basics” concept which explores some arithmetic, so we could add the DIV to the mix and then arithmetic would be a parent node. The problem is that there’s already a lot we need to explain in a basics concept just to get started, since in assembly there aren’t explicit function arguments/variables nor built-in functions.

I’m still thinking about the right approach here.

2 Likes

I’m +1 here. I think there is value in having another easy exercise that practices numbers and strings.

2 Likes

We barely have (true) easy exercises for strings + conditionals, so I am in support of adding this.

4 Likes

That’s three maintainers :grin: Let’s PR this!

Thanks, everyone, for supporting! I hope to find time these days to take this forward.

2 Likes

Comments and corrections welcome:

3 Likes

I’m also in favor

4 Likes