54
\$\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\$ Commented Jan 20, 2012 at 18:26
  • 2
    \$\begingroup\$ Are you looking for smallest algorithm or smallest code? \$\endgroup\$
    – Toto
    Commented Jan 20, 2012 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
    Commented Jan 20, 2012 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
    Commented Jan 20, 2012 at 21:02

49 Answers 49

1
2
1
\$\begingroup\$

Oracle SQL 11.2, 101 bytes

SELECT:1||DECODE(ROUND(MOD(:1,100),-1),10,'th',DECODE(MOD(:1,10),1,'st',2,'nd',3,'rd','th'))FROM DUAL
\$\endgroup\$
1
\$\begingroup\$

Haxe, 83 chars

function o(n:Int){return ['th','st','nd','rd'][n%100>20||n%100<4?n%10>3?0:n%10:0];}

Based on the javascript version, fixed for n > 100 as well.

\$\endgroup\$
3
  • \$\begingroup\$ Two suggestions: 1) Remove all whitespace to save some bytes. Right now, I count 91 total. 2) This doesn't seem to be a full program or a function. Perhaps you should consider turning it into one of those. \$\endgroup\$ Commented Feb 24, 2016 at 17:47
  • \$\begingroup\$ 1) yeah, but thats quite straightforward, so I tried to stay readable. \$\endgroup\$
    – csomakk
    Commented Feb 28, 2016 at 19:21
  • \$\begingroup\$ 2) yeah, you're right, I just pasted it here so anyone can use it without reconverting from another lang. :) \$\endgroup\$
    – csomakk
    Commented Feb 28, 2016 at 19:22
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
    Commented Feb 25, 2016 at 17:06
  • \$\begingroup\$ Ok, I will. Should I also add an un-golfed answer? \$\endgroup\$ Commented Feb 25, 2016 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
    Commented Feb 25, 2016 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
    Commented Feb 25, 2016 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\$
    – Riker
    Commented Sep 23, 2016 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
    Commented Sep 28, 2016 at 6:13
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\$
4
  • 1
    \$\begingroup\$ "The full magic". The one bit I actually wanted to read the comments on :) \$\endgroup\$ Commented May 5, 2020 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
    Commented Jul 12, 2020 at 7:02
  • \$\begingroup\$ 47 \$\endgroup\$
    – l4m2
    Commented Feb 3, 2022 at 5:07
  • \$\begingroup\$ Combining with this is 46 but not not sure which to collect \$\endgroup\$
    – l4m2
    Commented Feb 3, 2022 at 5:09
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
    Commented Jul 13, 2020 at 23:12
  • \$\begingroup\$ @Bubbler I remember without parentesis () does not assign to "h" name \$\endgroup\$
    – user58988
    Commented Jul 15, 2020 at 8:15
  • \$\begingroup\$ for me is ok in that way \$\endgroup\$
    – user58988
    Commented Jul 15, 2020 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
    Commented Mar 25, 2021 at 0:03
  • \$\begingroup\$ @JoKing Thanks for the comment. \$\endgroup\$
    – PkmnQ
    Commented Mar 25, 2021 at 0:07
1
\$\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\$
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\$
1
\$\begingroup\$

Vyxal, 14 bytes

ÞoÞ∞ZƛhṘ2ẎṘntp

Try it Online!

ÞoÞ∞Z          # Zip ordinals with positive integers
     ƛ         # Over each
      hṘ2ẎṘ    # Get the last two characters of the ordinal
           ntp # Append the number
\$\endgroup\$
1
\$\begingroup\$

brainfuck, 313 bytes

This was painful. Setup could probably be golfed better. May write a half-decent explanation later.

++++[>++++++<-]>-[<+++++>-]<[->+>+>+>+>+>+>+>+<<<<<<<<]>->--------------->----->--------------->>+>+>----------->>>>+>+>+>,[.>,]<<<[-]>>>-[>+<-----]>---[-<<-<->>>]<<<-[[-]>[->+>++<<]>+<+++++[->-[>]<<<]>[<<<]>[>>[-<<<<<[<]<<<<<[>]<[[->+<]<]>>>>>>>>>[-<<<<<<<<+>>>>>>>>]>>>>>[>]>>>>]<<<]]<<<[<]<<[<]<<<[<]>>>>>>>.>.

Try it online!

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

Go, 173 110 bytes

import."fmt"
func o(n int){s,k:="th",n%10
if k>0&&k<4&&n/10%10!=1{s=[]string{"st","nd","rd"}[k-1]}
Print(n,s)}

Attempt This Online!

  • -47 bytes from using slice indexing (by @Steffan)
  • -14 bytes from outputting to STDOUT (by @Steffan)
  • -2 bytes from removing duplicate n%10.

Old answer, 173 bytes

import."fmt"
func o(n int)string{s:=Sprint(n)
switch n%100{case 11,12,13:s+="th"
default:switch n%10{case 1:s+="st"
case 2:s+="nd"
case 3:s+="rd"
default:s+="th"}}
return s}

Attempt This Online!

\$\endgroup\$
2
  • \$\begingroup\$ 126 bytes \$\endgroup\$
    – naffetS
    Commented Sep 25, 2022 at 18:44
  • \$\begingroup\$ Or 112 bytes by outputting to stdout. \$\endgroup\$
    – naffetS
    Commented Sep 25, 2022 at 18:44
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\$
2
1
2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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