51
\$\begingroup\$

I would like to generate (as a return result of a function, or simply as the output of a program) the ordinal suffix of a positive integer concatenated to the number.

Samples:

1st  
2nd  
3rd  
4th  
...  
11th  
12th  
13th  
...  
20th  
21st
22nd
23rd
24th

And so on, with the suffix repeating the initial 1-10 subpattern every 10 until 100, where the pattern ultimately starts over.

The input would be the number and the output the ordinal string as shown above.

What is the smallest algorithm for this?

\$\endgroup\$
4
  • \$\begingroup\$ Hi, NickC, and welcome to codegolf.SE! Just to clarify, do you mean that we should read a number like 11 as input, and output e.g. 11th? Is each number in the input on a separate line, and should the output numbers be on separate lines too? And do we need to handle more than one line of input? \$\endgroup\$ Jan 20 '12 at 18:26
  • 1
    \$\begingroup\$ Are you looking for smallest algorithm or smallest code? \$\endgroup\$
    – Toto
    Jan 20 '12 at 18:31
  • \$\begingroup\$ @Ilmari I am looking for 11 as input and 11th as output. I don't mind if it processes multiple lines but what I had in mind was processing just a single number. \$\endgroup\$
    – Nicole
    Jan 20 '12 at 21:00
  • \$\begingroup\$ @M42 You know, I'm not really sure. I don't have a strict requirement - but I was probably thinking smallest algorithm. \$\endgroup\$
    – Nicole
    Jan 20 '12 at 21:02

45 Answers 45

1
2
1
\$\begingroup\$

Python, 88 84 bytes

lambda x:x+((('th','st','nd','rd')+('th',)*6)[int(x[-1])]if('0'+x)[-2]!='1'else'th')

Ungolfed:

def y(x):
    return x + (('th', 'st', 'nd', 'rd') + ('th', ) * 6)[int(x[-1])] if ('0' + x)[-2] != '1' else 'th')

lambda x defines an anonymous function with parameter x. ((('th','st','nd','rd')+('th',)*6)[int(x[-1])] defines a tuple of the endings for numbers less than 10, the 0-th element is for 0, and so forth. the if ('0'+x)[-2] != '1' checks if there is 11, 12, or a 13 to fix, and adds then else 'th' adds th instead of st, rd, or nd.

\$\endgroup\$
4
  • \$\begingroup\$ This is a great answer, but it took me a while to go through and understand it. If you could add a code explanation and breakdown below the golfed version of your code, it would help people learn from your code and improve the quality of your answer. \$\endgroup\$
    – wizzwizz4
    Feb 25 '16 at 17:06
  • \$\begingroup\$ Ok, I will. Should I also add an un-golfed answer? \$\endgroup\$ Feb 25 '16 at 17:31
  • \$\begingroup\$ It shouldn't be a different answer... What you've done is fine, well done. If you want any more challenges to do, I could give some recommendations. \$\endgroup\$
    – wizzwizz4
    Feb 25 '16 at 17:53
  • \$\begingroup\$ Ok. You could try... Adjust your chair, or Where will your buddies sit. Or you could try some of my challenges, such as The Knight's Next Tour. If these aren't the sort of challenges you like, just say. \$\endgroup\$
    – wizzwizz4
    Feb 25 '16 at 18:08
1
\$\begingroup\$

Scala 2.11.7, 151 Chars

def o(x:Int*)=x map{
case a if(a%10)==1&&a%100!=11=>a+"st"
case b if(b%10)==2&&b%100!=12=>b+"nd"
case c if(c%10)==3&&c%100!=13=>c+"rd"
case e=>e+"th"
}

Usage

   o(1,2,3,4) -> ArrayBuffer("1st", "2nd", "3rd", "4th")
\$\endgroup\$
2
  • \$\begingroup\$ Sorry, but all answers need to be golfed. Please golf this, if not than it's invalid and must be deleted. \$\endgroup\$ Sep 23 '16 at 12:53
  • \$\begingroup\$ I'm pretty sure you can remove the space between map and {, : and Int*, and remove the newline between "th" and } (I don't know Scala, so I might be completely wrong). Welcome to PPCG! \$\endgroup\$
    – clismique
    Sep 28 '16 at 6:13
1
\$\begingroup\$

Java 7, 91 81 bytes

String d(int n){return n+(n/10%10==1|(n%=10)<1|n>3?"th":n<2?"st":n<3?"nd":"rd");}

Port from @adrianmp's C# answer.

Old answer (91 bytes):

String c(int n){return n+((n%=100)>10&n<14?"th":(n%=10)==1?"st":n==2?"nd":n==3?"rd":"th");}

Ungolfed & test code:

Try it here.

class M{
  static String c(int n){
    return n + ((n%=100) > 10 & n < 14
                ?"th"
                : (n%=10) == 1
                   ? "st"
                   : n == 2
                      ? "nd"
                      : n == 3
                         ? "rd"
                         :"th");
  }

  static String d(int n){
    return n + (n/10%10 == 1 | (n%=10) < 1 | n > 3
                 ? "th"
                 : n < 2
                    ? "st"
                    : n < 3
                       ? "nd"
                       :"rd");
  }

  public static void main(String[] a){
    for(int i = 1; i < 201; i++){
      System.out.print(c(i) + ", ");
    }
    System.out.println();
    for(int i = 1; i < 201; i++){
      System.out.print(d(i) + ", ");
    }
  }
}

Output:

1st, 2nd, 3rd, 4th, 5th, 6th, 7th, 8th, 9th, 10th, 11th, 12th, 13th, 14th, 15th, 16th, 17th, 18th, 19th, 20th, 21st, 22nd, 23rd, 24th, 25th, 26th, 27th, 28th, 29th, 30th, 31st, 32nd, 33rd, 34th, 35th, 36th, 37th, 38th, 39th, 40th, 41st, 42nd, 43rd, 44th, 45th, 46th, 47th, 48th, 49th, 50th, 51st, 52nd, 53rd, 54th, 55th, 56th, 57th, 58th, 59th, 60th, 61st, 62nd, 63rd, 64th, 65th, 66th, 67th, 68th, 69th, 70th, 71st, 72nd, 73rd, 74th, 75th, 76th, 77th, 78th, 79th, 80th, 81st, 82nd, 83rd, 84th, 85th, 86th, 87th, 88th, 89th, 90th, 91st, 92nd, 93rd, 94th, 95th, 96th, 97th, 98th, 99th, 100th, 101st, 102nd, 103rd, 104th, 105th, 106th, 107th, 108th, 109th, 110th, 111th, 112th, 113th, 114th, 115th, 116th, 117th, 118th, 119th, 120th, 121st, 122nd, 123rd, 124th, 125th, 126th, 127th, 128th, 129th, 130th, 131st, 132nd, 133rd, 134th, 135th, 136th, 137th, 138th, 139th, 140th, 141st, 142nd, 143rd, 144th, 145th, 146th, 147th, 148th, 149th, 150th, 151st, 152nd, 153rd, 154th, 155th, 156th, 157th, 158th, 159th, 160th, 161st, 162nd, 163rd, 164th, 165th, 166th, 167th, 168th, 169th, 170th, 171st, 172nd, 173rd, 174th, 175th, 176th, 177th, 178th, 179th, 180th, 181st, 182nd, 183rd, 184th, 185th, 186th, 187th, 188th, 189th, 190th, 191st, 192nd, 193rd, 194th, 195th, 196th, 197th, 198th, 199th, 200th, 
1st, 2nd, 3rd, 4th, 5th, 6th, 7th, 8th, 9th, 10th, 11th, 12th, 13th, 14th, 15th, 16th, 17th, 18th, 19th, 20th, 21st, 22nd, 23rd, 24th, 25th, 26th, 27th, 28th, 29th, 30th, 31st, 32nd, 33rd, 34th, 35th, 36th, 37th, 38th, 39th, 40th, 41st, 42nd, 43rd, 44th, 45th, 46th, 47th, 48th, 49th, 50th, 51st, 52nd, 53rd, 54th, 55th, 56th, 57th, 58th, 59th, 60th, 61st, 62nd, 63rd, 64th, 65th, 66th, 67th, 68th, 69th, 70th, 71st, 72nd, 73rd, 74th, 75th, 76th, 77th, 78th, 79th, 80th, 81st, 82nd, 83rd, 84th, 85th, 86th, 87th, 88th, 89th, 90th, 91st, 92nd, 93rd, 94th, 95th, 96th, 97th, 98th, 99th, 100th, 101st, 102nd, 103rd, 104th, 105th, 106th, 107th, 108th, 109th, 110th, 111th, 112th, 113th, 114th, 115th, 116th, 117th, 118th, 119th, 120th, 121st, 122nd, 123rd, 124th, 125th, 126th, 127th, 128th, 129th, 130th, 131st, 132nd, 133rd, 134th, 135th, 136th, 137th, 138th, 139th, 140th, 141st, 142nd, 143rd, 144th, 145th, 146th, 147th, 148th, 149th, 150th, 151st, 152nd, 153rd, 154th, 155th, 156th, 157th, 158th, 159th, 160th, 161st, 162nd, 163rd, 164th, 165th, 166th, 167th, 168th, 169th, 170th, 171st, 172nd, 173rd, 174th, 175th, 176th, 177th, 178th, 179th, 180th, 181st, 182nd, 183rd, 184th, 185th, 186th, 187th, 188th, 189th, 190th, 191st, 192nd, 193rd, 194th, 195th, 196th, 197th, 198th, 199th, 200th, 
\$\endgroup\$
1
\$\begingroup\$

Common Lisp, 63

(format t"~a~a"i(let((x(format()"~:r"i)))(subseq x(-(length x)2))))

Input is i. There's probably a more clever way to golf this.

\$\endgroup\$
1
\$\begingroup\$

Pyth, 33 bytes

+Q@.>+c"stndrd"2*]"th"7 1?qh`Q\1Z

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Procedural Footnote Language, 39 bytes

[1]
[PFL1.0]
[1] [ORD:[INPUT]]
[PFLEND]

The BODY section of the document contains a reference to footnote [1]; footnote [1] contains the [ORD]inal representation of the [INPUT].

\$\endgroup\$
1
\$\begingroup\$

JavaScript (Node.js), 51 bytes

credit to @KevinCruijssen for improving the answer

n=>n+=[,'st','nd','rd'][~~(n/10%10)-1?n%10:0]||'th'

Try it online!


Explanation :

n =>                      // input
    n+=[,'st','nd','rd']     // the array of suffices add everything to n
        [~~(n/10%10)-1?n%10:0] // the full magic 
    || 'th'               // works for everything except 1 , 2 , 3 just like what you want

\$\endgroup\$
2
  • 1
    \$\begingroup\$ "The full magic". The one bit I actually wanted to read the comments on :) \$\endgroup\$ May 5 '20 at 13:19
  • \$\begingroup\$ @SteveBennett The general logic that if the tens digit ((n/10%10), rounded by the ~~) is a one (-1) then just get the index 0, which maps to th, otherwise get the index of the ones digit, which will be the appropriate suffix for 1,2 and 3, and th otherwise \$\endgroup\$
    – Jo King
    Jul 12 '20 at 7:02
1
\$\begingroup\$

Julia 0.6, 68 bytes

f(x,m=x%10,p=x%100-m)="$x$(["th","st","nd","rd"][m>3||p==10?1:m+1])"

Try it online!

Straightforward remainder rules in Julia.

\$\endgroup\$
1
\$\begingroup\$

05AB1E, 21 bytes

т%T‰ć≠*4ªß…thŠØ3ôs訫

Try it online or verify a few more test cases at once.

Explanation:

Mostly ported from a sub-section of this answer of mine, except with additional leading т%.

т%                     # Take modulo-100 on the (implicit) input-integer
  T‰                   # Take the divmod-10 ([n//10,n%10]) on that
    ć                  # Extract the head: n//10
     ≠                 # Check that it's NOT equal to 1 (0 if 1; 1 otherwise)
      *                # Multiply the [n%10] by this
       4ª              # Append a 4 to this list: [n%10*(n//10!=1),4]
         ß             # Pop and push the smallest number in this list
          …thŠØ        # Push dictionary string "th standards"
               3ô      # Split it into parts of size 3: ["th ","sta","nda","rds"]
                 sè    # Index the calculated minimum into this list
                       # (modular 0-based, so both 0 and 4 will index into "th ")
                   ¨   # Remove the last character
                    «  # And append it to the (implicit) input-integer
                       # (after which the result is output implicitly)

See this 05AB1E tip of mine (section How to use the dictionary?) to understand why …thŠØ is "th standards".

\$\endgroup\$
1
\$\begingroup\$

APL(NARS), 38 chars, 76 bytes

(⍕,{((⍳3)⍳10∣⍵×3≠⌊√⍵)⊃'snrt',¨'tddh'})

test:

  h←(⍕,{((⍳3)⍳10∣⍵×3≠⌊√⍵)⊃'snrt',¨'tddh'})
  h¨0..19
 0th 1st 2nd 3rd 4th 5th 6th 7th 8th 9th 10th 11th 12th 13th 14th 15th 16th 17th 18th 19th 
  h¨20..31
 20th 21st 22nd 23rd 24th 25th 26th 27th 28th 29th 30th 31st 
  ⎕fmt h¨100..104
┌5───────────────────────────────────────────┐
│┌5─────┐ ┌5─────┐ ┌5─────┐ ┌5─────┐ ┌5─────┐│
││ 100th│ │ 101st│ │ 102nd│ │ 103rd│ │ 104th││
│└──────┘ └──────┘ └──────┘ └──────┘ └──────┘2
└∊───────────────────────────────────────────┘
\$\endgroup\$
3
  • 1
    \$\begingroup\$ I don't think you need the outermost parens (or is it a weak point of NARS?) \$\endgroup\$
    – Bubbler
    Jul 13 '20 at 23:12
  • \$\begingroup\$ @Bubbler I remember without parentesis () does not assign to "h" name \$\endgroup\$
    – user58988
    Jul 15 '20 at 8:15
  • \$\begingroup\$ for me is ok in that way \$\endgroup\$
    – user58988
    Jul 15 '20 at 8:17
1
\$\begingroup\$

FEU, 41 bytes

m/1.$/\0th/1$/1st/2$/2nd/3$/3rd/\d$/\0th/

Try it online!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ This doesn't work for numbers that end in th unless they have a one as the second last digit. I think you can solve this by adding /\d$/\0th/ to the end. You can also golf the first part to be /1.$/\0th/ \$\endgroup\$
    – Jo King
    Mar 25 at 0:03
  • \$\begingroup\$ @JoKing Thanks for the comment. \$\endgroup\$
    – PkmnQ
    Mar 25 at 0:07
1
\$\begingroup\$

Bash, 58 bytes

Just a modification of @stephanmg's post in Bash. Output is on STDERR as in "command not found".

case $1 in
*1?|*[04-9])$1th;;*1)$1st;;*2)$1nd;;*)$1rd
esac

Try it online!

This program completely relies on the limitation that the input is a non-negative decimal integer.

\$\endgroup\$
1
\$\begingroup\$

Vyxal, 23 bytes

₀%:4<?₀ḭċ∧*4«∨¦İk√«/$i+

Try it Online!

Explanation:
₀%:4<?₀ḭċ∧*4«∨¦İk√«/$i+    # full program

₀%:                         # push input mod 10 twice
   4<                       # less than 4
     ?₀ḭ                    # input floor div 10
        ċ                   # != 1
         ∧*                 # and both bools, then multiply by initial mod 10
            4«∨¦İk√«/       # "thstndrd" split into 4 parts
                      $i    # indexed by input mod 10
                        +   # concat
\$\endgroup\$
0
\$\begingroup\$

C, 87 bytes (correct teen handling)

This C solution is longer than the current shortest 83 byte C solution posted, but as of writing, that 83 byte solution is incorrect and prints numbers like 11st, 12nd, and 13rd.

Here is my solution, which correctly handles teen numbers:

main(n){scanf("%d",&n);printf("%d%s",n,"th\0st\0nd\0rd"+(n%10<4&&n/10%10-1?n%10*3:0));}

Degolfed:

main(n) {
    scanf("%d", &n);
    printf("%d%s", n, "th\0st\0nd\0rd" + (n%10 < 4 && n/10%10 - 1 ? n%10*3 : 0));
}
\$\endgroup\$
0
\$\begingroup\$

Scratch, idk bytes

Scratch!

I tried to convert it to sb syntax, but it did not work

Try it!

Please comment if you know a way to golf, or byte-count this

\$\endgroup\$
1
2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.