Outputting ordinal numbers (1st, 2nd, 3rd)

43

9

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?

Nicole

Posted 2012-01-20T17:57:02.027

Reputation: 533

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? – Ilmari Karonen – 2012-01-20T18:26:14.163

1Are you looking for smallest algorithm or smallest code? – Toto – 2012-01-20T18:31:07.917

@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. – Nicole – 2012-01-20T21:00:23.283

@M42 You know, I'm not really sure. I don't have a strict requirement - but I was probably thinking smallest algorithm. – Nicole – 2012-01-20T21:02:04.170

Answers

30

Perl, 37 + 1 characters

s/1?\d\b/$&.((0,st,nd,rd)[$&]||th)/eg

This is a regexp substitution that appends the appropriate ordinal suffix to any numbers in $_ that are not already followed by a letter. To apply it to file input, use the p command line switch, like this:

perl -pe 's/1?\d\b/$&.((0,st,nd,rd)[$&]||th)/eg'

This is a complete Perl program that reads input from stdin and writes the processed output to stdout. The actual code is 37 chars long, but the p switch counts as one extra character.

Sample input:

This is the 1 line of the sample input...
...and this is the 2.
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
101 102 103 104 105 106 107 108 109 110

Output:

This is the 1st line of the sample input...
...and this is the 2nd.
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
101st 102nd 103rd 104th 105th 106th 107th 108th 109th 110th

Numbers already followed by letters will be ignored, so feeding the output again through the filter won't change it. Spaces, commas and periods between numbers are not treated specially, so they're assumed to separate numbers like any other punctuation. Thus, e.g. 3.14159 becomes 3rd.14159th.

How does it work?

  • First, this is a global regexp replacement (s///g). The regexp being matched is 1?\d\b, where \d matches any digit and \b is a zero-width assertion matching the boundary between an alphanumeric and a non-alphanumeric character. Thus, 1?\d\b matches the last digit of any number, plus the previous digit if it happens to be 1.

  • In the substitution, which is evaluated as Perl code due to the /e switch, we take the matched string segment ($&) and append (.) to it the suffix obtained by using $& itself as an integer index to the list (0,st,nd,rd); if this suffix is zero or undefined (i.e. when $& is zero or greater than three), the || operator replaces it with th.


Edit: If the input is restricted to a single integer, then this 35 character solution will suffice:

s/1?\d$/$&.((0,st,nd,rd)[$&]||th)/e

Ilmari Karonen

Posted 2012-01-20T17:57:02.027

Reputation: 19 513

1Should be able to drop the g off the substitution if you specify that each number must be on it's own line. Also, that'd let you change the word boundary to be $. But overall, +1, damn clever solution. – Mr. Llama – 2012-01-20T21:05:11.793

@GigaWatt: Indeed, I wrote the code before NickC answered my question about the input format, so I made it as generic as possible. – Ilmari Karonen – 2012-01-20T21:42:16.323

39

Python 2, 49 bytes

lambda n:`n`+'tsnrhtdd'[n%5*(n%100^15>4>n%10)::4]

An anonymous function. A full program would be counted at 55 bytes.

'tsnrhtdd'[i::4] encodes the suffixes th st nd rd for values of i from 0 to 3. Given this, all we need is a way to map the values of n to the index of the corresponding suffix, i. A straightforward expression that works is (n%10)*(n%10<4 and 10<n%100<14). We can easily shorten this by dropping the first set of parentheses and observing that n%5 gives the same results as n%10 for the values of n with the special suffixes. With a bit of trial and error, one may also shorten 10<n%100<14 to n%100^15>4, which can be chained with the other conditional to save even more bytes.

xsot

Posted 2012-01-20T17:57:02.027

Reputation: 5 069

3this is some black magic right here c: – cat – 2016-02-25T23:33:09.043

I don't get it. Can anyone explain what's happening here? – Pavel – 2016-09-27T17:11:24.607

@Pavel I have updated my answer with an explanation. – xsot – 2016-09-28T08:55:01.990

Awesome! Brilliant way to think... – Benison Sam – 2017-12-05T00:45:56.817

10

Mathematica 39 45 bytes

Note: In recent versions of Mathematica, asking for the nth part of p, where p is undefined, generates an error message, but returns the correct answer anyway. I've added Quiet to prevent the error message from printing.

Quiet@StringSplit[SpokenString[p[[#]]]][[2]]&

Usage

Quiet@StringSplit[SpokenString[p[[#]]]][[2]] &[31]

31st

Quiet@StringSplit[SpokenString[p[[#]]]][[2]] &/@Range[21]

{"1st", "2nd", "3rd", "4th", "5th", "6th", "7th", "8th", "9th", "10th", "11th", "12th", "13th", "14th", "15th", "16th", "17th", "18th", "19th", "20th", "21st"}


How it works

SpokenString writes out an any valid Mathematica expression as it might be spoken. Below are two examples from the documentation for SpokenString,

SpokenString[Sqrt[x/(y + z)]]

"square root of the quantity x over the quantity y plus z" *)

SpokenString[Graphics3D[Sphere[{{0, 0, 0}, {1, 1, 1}}]], "DetailedGraphics" -> True]

"a three-dimensional graphic consisting of unit spheres centered at 0, 0, 0 and 1, 1, 1"


Now, for the example at hand,

Quiet@SpokenString[p[[#]]] &[31]

"the 31st element of p"

Let's represent the above string as a list of words:

StringSplit[%]

{"the", "31st", "element", "of", "p"}

and take the second element...

%[[2]]

31st

DavidC

Posted 2012-01-20T17:57:02.027

Reputation: 24 524

I'm confused; where is p defined? EDIT: never mind, I see how you're using this; unfortunately it does not work on my system. :-/ – Mr.Wizard – 2013-04-06T13:13:45.950

It works on v.9.0.1. (I seem to recall that you are using 7.0.) Yes, p does not need to be defined. – DavidC – 2013-04-06T13:29:47.337

I understand that now. However, in v7 I get from SpokenString @ p[[117]] the output " part 117 of p". – Mr.Wizard – 2013-04-06T13:31:46.240

So SpokenString gets revised from time to time. I wouldn't be surprised it this code (http://codegolf.stackexchange.com/questions/8859/hello-world-in-1024-characters/8869#8869) also doesn't work on v. 7. BTW, it wasn't meant to be an enduring solution.

– DavidC – 2013-04-06T13:37:19.630

Hah, I hadn't seen that answer before. – Mr.Wizard – 2013-04-06T13:44:16.127

Actually, I haven't seen a lot of your contributions to this site. You're really going crazy here! (In a good way.) – Mr.Wizard – 2013-04-06T13:47:00.153

10

Python, 68 characters

i=input()
k=i%10
print"%d%s"%(i,"tsnrhtdd"[(i/10%10!=1)*(k<4)*k::4])

Gareth

Posted 2012-01-20T17:57:02.027

Reputation: 11 678

4This is really late, but you can take off 7 bytes by doing \i`+"tsnrhtdd"`. Otherwise, this is the exact solution I just got. – DLosc – 2015-09-05T20:27:28.413

7

Ruby, 60

It's not as good as the Perl entry, but I figured I'd work on my Ruby skills.

def o(n)n.to_s+%w{th st nd rd}[n/10%10==1||n%10>3?0:n%10]end

Function takes one integer argument, n, and returns a string as the ordinal form.

Works according to the following logic:
If the tens digit is a 1 or the ones digit is greater than 3 use the suffix 'th'; otherwise find the suffix from the array ['th', 'st', 'nd', 'rd'] using the final digit as the index.

Mr. Llama

Posted 2012-01-20T17:57:02.027

Reputation: 2 387

Set a variable to 10? – wizzwizz4 – 2016-02-25T17:57:34.127

I think setting a variable to n%10 is better. – CalculatorFeline – 2016-02-27T20:53:30.527

You can never beat Perl in writing horrible incomprehensible code that's as short as possible :) – jamylak – 2013-04-06T10:25:11.523

o(113) is "113rd", should be "113th". The tens digit check doesn't account for numbers with more than two digits. – hammar – 2012-01-20T23:07:19.253

Ok, pitched in another %10 to compensate. Added 3 characters. (I feel like %10 appears enough where it should be shortened somehow, but I can't think of a solution) – Mr. Llama – 2012-01-20T23:12:00.010

6

Javascript (ES6) 50 44 Bytes (non-competing)

a=>a+=[,"st","nd","rd"][a.match`1?.$`]||"th"

Notes

  • takes imput as a string
  • Removed 6 bytes, thanks @user81655

Shaun H

Posted 2012-01-20T17:57:02.027

Reputation: 732

1a+ -> a+=, remove parentheses, \d -> ., remove [0], and if you take the number as a string: a.match\1?.$`` instead of /1?.$/.exec(a). – user81655 – 2016-02-26T21:49:09.927

You should probably add a notice this answer is non-competing, as ES6 didn't exist when the challenge was posted. – user2428118 – 2016-09-28T12:19:27.933

5

Javascript, 68 71

function o(n){return n+([,'st','nd','rd'][~~(n/10%10)-1?n%10:0]||'th')}

Joint effort with ItsCosmo.

EDIT: Wasn't working properly with numbers > 100

aebabis

Posted 2012-01-20T17:57:02.027

Reputation: 433

You could bring it down to 62 with: function o(n)n+([,'st','nd','rd'][~~(n/10%10)-1?n%10:0]||'th') and you can bring it down further to 54 if you are happy to use fat arrow notation: o=n=>n+([,'st','nd','rd'][~~(n/10%10)-1?n%10:0]||'th') – WallyWest – 2014-03-03T12:04:19.797

@WallyWest For some reason, I really like that my solution works in modern browsers. Feel free to post your own answer; I think its sufficiently different. – aebabis – 2014-03-03T16:33:45.197

No, that's fine! Just providing a few alternatives! – WallyWest – 2014-03-03T23:20:42.647

3

Haskell, 95 chars

h=foldr g"th".show
g '1'"th"="1st"
g '2'"th"="2nd"
g '3'"th"="3rd"
g '1'[x,_,_]='1':x:"th"
g a s=a:s

Testing:

*Main> map h [1..40]
["1st","2nd","3rd","4th","5th","6th","7th","8th","9th","10th","11th","12th","13t
h","14th","15th","16th","17th","18th","19th","20th","21st","22nd","23rd","24th",
"25th","26th","27th","28th","29th","30th","31st","32nd","33rd","34th","35th","36
th","37th","38th","39th","40th"]

Must be loaded with -XNoMonomorphismRestriction.

Will Ness

Posted 2012-01-20T17:57:02.027

Reputation: 352

3

JavaScript, 64 characters (ES3) or 47 characters (ES6)

ES3 (64 characters):

function(n){return n+=[,'st','nd','rd'][n%100>>3^1&&n%10]||'th'}

ES6 (47 characters):

n=>n+=[,'st','nd','rd'][n%100>>3^1&&n%10]||'th'

Explanation

The expression n % 100 >> 3 ^ 1 evaluates to 0 for any positive n ending with digits 0815. Thus, for any n mod 100 ending in 11, 12, or 13, the array lookup returns undefined, leading to a suffix of th.

For any positive n ending in other digits than 0815, the expression n % 100 >> 3 ^ 1 evaluates to a positive integer, invoking the expression n % 10 for array lookup, returning st,nd, or rd for n which ends with 1, 2, or 3. Otherwise, th.

Tomas Langkaas

Posted 2012-01-20T17:57:02.027

Reputation: 324

Save a bytes with n+=[,'st','nd','rd'][n%100>>3^1&&n%10]||'th'. – Shaggy – 2017-05-08T13:29:54.903

@Shaggy, thanks, updated as suggested. – Tomas Langkaas – 2017-05-16T17:14:44.600

@guest271314, fun to see this code being used. Note that it only works for positive numbers, another alternative is n+=[,"st","nd","rd"][(((n<0?-n:n)+90)%100-10)%10]||"th", adapted from this post.

– Tomas Langkaas – 2018-12-20T11:15:38.877

3

Golfscript, 34 characters

~.10/10%1=!1$10%*.4<*'thstndrd'2/=

hammar

Posted 2012-01-20T17:57:02.027

Reputation: 4 011

3

APL (Dyalog Unicode), 38 36 bytes

Thanks to ngn for fixing a bug while maintaining byte count.

Anonymous tacit prefix function. Requires ⎕IO (Index Origin) set to 0, which is default on many systems. Even works for 0!

⍕,{2↑'thstndrd'↓⍨2×⊃⍵⌽∊1 0 8\⊂10↑⍳4}

Try it online!

{} anonymous lambda; is argument:

⍳4 first four ɩndices; [0,1,2,3]

10↑ take first ten elements from that, padding with zeros: [0,1,2,3,0,0,0,0,0,0]

 enclose to treat as single element; [[0,1,2,3,0,0,0,0,0,0]]

1 0 8\ expand to one copy, a prototypical copy (all-zero), eight copies;
  [[0,1,2,3,0,0,0,0,0,0],
   [0,0,0,0,0,0,0,0,0,0],
   [0,1,2,3,0,0,0,0,0,0],
   [0,1,2,3,0,0,0,0,0,0],
   ⋮ (5 more)
   [0,1,2,3,0,0,0,0,0,0]]

ϵnlist (flatten);
  [0,1,2,3,0,0,0,0,0,0,
   0,0,0,0,0,0,0,0,0,0,
   0,1,2,3,0,0,0,0,0,0,
   0,1,2,3,0,0,0,0,0,0,
   ⋮ (50 more)
   0,1,2,3,0,0,0,0,0,0]

⍵⌽ cyclically rotate left as many steps as indicated by the argument

 pick the first number (i.e. the argument-mod-100'th number)

 multiply two by that (gives 0, 2, 4, or 6)

'thstndrd'↓⍨drop that many characters from this string

2↑ take the first two of the remaining characters

⍕, concatenate the stringified argument to that

Adám

Posted 2012-01-20T17:57:02.027

Reputation: 37 779

"31th"?­­­­­­­­ – ngn – 2018-05-03T17:49:53.763

⍕,{2↑'thstndrd'↓⍨2×⊃⍵⌽∊1 0 8\⊂10↑⍳4} – ngn – 2018-05-03T18:23:04.610

sorry, I forgot to mention ⎕io←0. I can see you guessed that, but there are a few 1,2,3,4,0,0... that should be 0,1,2,3,0,0... – ngn – 2018-05-03T19:35:21.213

@ngn Fixed. And happens to work for 0 too! – Adám – 2018-05-03T20:26:17.133

3

C#, 62 bytes

n=>n+(n/10%10==1||(n%=10)<1||n>3?"th":n<2?"st":n<3?"nd":"rd");

Full program and verification:

using System;

namespace OutputOrdinalNumbers
{
    class Program
    {
        static void Main(string[] args)
        {
            Func<int,string>f= n=>n+(n/10%10==1||(n%=10)<1||n>3?"th":n<2?"st":n<3?"nd":"rd");

            for (int i=1; i<=124; i++)
                Console.WriteLine(f(i));
        }
    }
}

adrianmp

Posted 2012-01-20T17:57:02.027

Reputation: 1 592

You can golf it by two bytes by changing the || to |. – Kevin Cruijssen – 2016-11-08T12:39:20.110

2

J - 44 char

Nothing in J? This is an outrage!

(":,th`st`nd`rd{::~10 10(]*[(~:*])4>])/@#:])

Explained (note that 1 is boolean true in J and 0 is false):

  • 10 10(...)/@#:] - First we take the argument (]) and find the tens and ones digit (10 10 #:). Then, we will insert (...) between the two.
  • (]*[(~:*])4>]) - In this subexpression, but not the innermost one, ] will point to the ones digit and [ the tens digit.
  • [(~:*])4>] - ~: is J for "not-equals", so this takes the result of 4>] (i.e. whether or not the one digit is less than 4) and multiplies it by the result of tens ~: (4>]). Why would anyone do this? Consider the following:
    • If we are checking 10, 11, 12, 13, then tens is 1 (we are in the teens) and ones is less than 4, so tens ~: (4>]) is false and the result is 0*1 = 0.
    • If we are any other one of {X0, X1, X2, X3}, then clearly tens ~: (4>]) is true and we get out 1*1 = 1.
    • If ones is greater than four, then 4>] was 0 and it doesn't matter what happens to the test anymore, we will get 0 out regardless.
    • So to summarize, [(~:*])4>] is 1 if we are in {X0, X1, X2, X3} but not in the teens, and 0 otherwise.
  • ]* - Finally we multiply that result by the ones digit. So this product will be 0 if the number deserves a 'th' suffix, else its value.
  • th`st`nd`rd{::~ - We use the modified ones-digit from above to index the list of suffixes. 0 gets 'th', 1 gets 'st', and so on.
  • ":, - Finally, take the original number, convert it to a string (":), and then prepend it to the suffix.

Usage is obvious, though as-is the verb can only take one ordinal, not a list.

   (":,th`st`nd`rd{::~10 10(]*[(~:*])4>])/@#:]) 112         NB. single use
112th
   (":,th`st`nd`rd{::~10 10(]*[(~:*])4>])/@#:]) 1 2 3 4 5   NB. doing it wrong
|length error
|       (":,th`st`nd`rd{::~10 10(]*[(~:*])4>])/@#:])1 2 3 4 5
   NB. i.5 10   makes a 5x10 grid of increasing integers
   NB. &.>      to operate on each integer separately, and box the result after
   (":,th`st`nd`rd{::~10 10(]*[(~:*])4>])/@#:])&.> i.5 10   NB. all better
+----+----+----+----+----+----+----+----+----+----+
|0th |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|
+----+----+----+----+----+----+----+----+----+----+

algorithmshark

Posted 2012-01-20T17:57:02.027

Reputation: 8 144

2

PowerShell, 92

process{"$_$(switch -r($_){"(?<!1)1$"{'st'}"(?<!1)2$"{'nd'}"(?<!1)3$"{'rd'}default{'th'}})"}

Works with one number per line of input. Input is given through the pipeline. Making it work for only a single number doesn't reduce the size.

Joey

Posted 2012-01-20T17:57:02.027

Reputation: 12 260

2

Mathematica 29 + 5 = 34 bytes

SpokenStringDump`SpeakOrdinal

+5 bytes because Speak function must be called before using this built-in.

Usage

SpokenStringDump`SpeakOrdinal[1]

"1st "

SpokenStringDump`SpeakOrdinal[4707]

"4,707th "

JungHwan Min

Posted 2012-01-20T17:57:02.027

Reputation: 13 290

1

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

user80309

Posted 2012-01-20T17:57:02.027

Reputation:

1

R, 79 76 bytes

Since there is no R solution yet... no tricks here, basic vector indexing, golfed down 3 chars thanks to Giuseppe. Previously tried index: [1+(x%%10)-(x%%100==11)] and [1+(x%%10)*(x%%100!=11)].

function(x)paste0(x,c("th","st","nd","rd",rep("th",6))[1+x%%10*!x%%100==11])

Try it online!

With substr, 79 bytes:

function(x,y=1+2*min(x%%10-(x%%100==11),4))paste0(x,substr("thstndrdth",y,y+1))

Try it online!

JayCe

Posted 2012-01-20T17:57:02.027

Reputation: 2 655

11+x%%10*!x%%100==11 for the index? – Giuseppe – 2018-05-03T17:58:25.230

@Giuseppe I need to calm down on the parenthesis :). Clever use of ! in front of expression instead of !=. – JayCe – 2018-05-03T18:13:23.757

1Yeah, the operators have weird precedence; ^ is really high, then %%-type operators, then */ and +- and I think == and &| comes next. ! has quite low precedence so you can use it as a separator between operations. – Giuseppe – 2018-05-03T18:17:44.880

1

K - 44 char

It so happens that this is exactly as long as the J, and works in almost the same way.

{x,$`th`st`nd`rd@{y*(y<4)*~1=x}.-2#0,.:'x$:}

Explained:

  • x$: - First, we convert the operand x into a string, and then assign that back to x. We will need its string rep again later, so doing it now saves characters.
  • .:' - Convert (.:) each (') digit back into a number.
  • -2#0, - Append a 0 to the front of the list of digits (in case of single-digit numbers), and then take the last two.
  • {y*(y<4)*~1=x}. - Use the two digits as arguments x and y to this inner function, which returns y if y is less than 4 and x is not equal to 1, otherwise 0.
  • `th`st`nd`rd@ - Index the list of suffixes by this result.
  • x,$ - Convert the suffix from symbol to string, and append it to the original number.

Usage:

  {x,$`th`st`nd`rd@{y*(y<4)*~1=x}.-2#0,.:'x$:} 3021
"3021st"
  {x,$`th`st`nd`rd@{y*(y<4)*~1=x}.-2#0,.:'x$:}' 1 2 3 4 11 12 13 14  /for each in list
("1st"
 "2nd"
 "3rd"
 "4th"
 "11th"
 "12th"
 "13th"
 "14th")

algorithmshark

Posted 2012-01-20T17:57:02.027

Reputation: 8 144

1

OCaml

I'm pretty new to OCaml, but this is the shortest i could get.

let n x =
   let v = x mod 100 and string_v = string_of_int x in
   let z = v mod 10 in
   if v=11 || v=12 || v=13 then string_v^"th" 
   else if v = 1 || z = 1 then string_v^"st" else if v = 2 || z = 2 then string_v^"nd" else if v = 3 || z = 3 then string_v^"rd" else string_v^"th";;

I created a function n that takes a number as a parameter and does the work. Its long but thought it'd be great to have a functional example.

Joseph Elcid

Posted 2012-01-20T17:57:02.027

Reputation: 111

yeah, you're right.. I've made the correction. Thanks – Joseph Elcid – 2012-02-07T15:42:40.860

I've just tidied up the formatting on your code. Each line needs to be preceded by four spaces in order to be recognized as a code block. – Gareth – 2012-02-07T16:29:10.160

Wouldn't your first if check be shorter as if v>10 && v<14? I'm not familiar with ocaml, but is it necessary to have the string_v variable be so long? – Gaffi – 2012-04-29T03:49:10.457

No its not necessary, I could have chosen w or x. Just wanted something meaningful.
But you're right, it would have made the code a little shorter.
– Joseph Elcid – 2012-05-11T13:32:15.350

Welcome to PPCG! Please include your byte count on the header. (too late?) – Erik the Outgolfer – 2016-09-28T13:32:26.300

input: 11 would yield output: 11st – None – 2012-01-23T02:04:29.260

1

C - 95 83 characters

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

Degolfed:

main(n,k)
{
    scanf("%d",&n);
    k=(n+9)%10; // xx1->0, xx2->1, xx3->2
    printf("%d%s\n",n,k<3?"st\0nd\0rd"+3*k:"th");
}

We could do k=(n-1)%10 instead of adding 9, but for n=0 we would get an incorrect behaviour, because in C (-1)%10 evaluates to -1, not 9.

pawel.boczarski

Posted 2012-01-20T17:57:02.027

Reputation: 1 243

1

Javascript, 75

function s(i){return i+'thstndrd'.substr(~~(i/10%10)-1&&i%10<4?i%10*2:0,2)}

wolfhammer

Posted 2012-01-20T17:57:02.027

Reputation: 1 219

1

PHP, 151

I know that this program is not comparable to the others. Just felt like giving a solution.

<?$s=explode(' ',trim(fgets(STDIN)));foreach($s as$n){echo$n;echo(int)(($n%100)/10)==1?'th':($n%10==1?'st':($n%10==2?'nd':($n%10==3?'rd':'th')))."\n";}

l0n3sh4rk

Posted 2012-01-20T17:57:02.027

Reputation: 1 387

you can save a few characters by using foreach($s as $n){echo$n; – karthik – 2012-04-29T11:24:53.677

1

Scala 86

def x(n:Int)=n+{if(n%100/10==1)"th"else(("thstndrd"+"th"*6).sliding(2,2).toSeq(n%10))}

Scala 102:

def x(n:Int)=if((n%100)/10==1)n+"th"else if(n%10<4)n+("thstndrd".take(n+1)%5*2.drop(n%5*2))else n+"th"

102 as well:

def x(n:Int)=if((n%100)/10==1)n+"th"else if(n%10<4)n+("thstndrd".sliding(2,2).toSeq(n%10))else n+"th"

ungolfed:

def x (n: Int) =
  n + { if (((n % 100) / 10) == 1) "th" 
        else (("thstndrd"  + ("th"  * 6)).sliding (2, 2).toSeq (n % 10))
      }

user unknown

Posted 2012-01-20T17:57:02.027

Reputation: 4 210

1

PHP, 98 bytes

function c($n){$c=$n%100;$s=['','st','nd','rd'];echo$c>9&&$c<14||!$s[$c%10]?$n.'th':$n.$s[$c%10];}

The 11-13 bit is killing me here. Works for any integer $n >= 0.

For any integer $n:

PHP, 103 bytes

function c($n){$c=abs($n%100);$s=['','st','nd','rd'];echo$c>9&&$c<14||!$s[$c%10]?$n.'th':$n.$s[$c%10];}

ricdesi

Posted 2012-01-20T17:57:02.027

Reputation: 499

1

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.

NoOneIsHere

Posted 2012-01-20T17:57:02.027

Reputation: 1 916

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. – wizzwizz4 – 2016-02-25T17:06:35.067

Ok, I will. Should I also add an un-golfed answer? – NoOneIsHere – 2016-02-25T17:31:49.247

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. – wizzwizz4 – 2016-02-25T17:53:50.000

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.

– wizzwizz4 – 2016-02-25T18:08:53.393

0

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.

Harry

Posted 2012-01-20T17:57:02.027

Reputation: 1 189

0

C: 95 characters

A ridiculously long solution:

n;main(){scanf("%d",&n);printf("%d%s",n,n/10%10-1&&(n=n%10)<4&&n?n>2?"rd":n<2?"st":"nd":"th");}

It needs to be mangled more.

Fors

Posted 2012-01-20T17:57:02.027

Reputation: 3 020

A user flagged this saying "is incorrect: doesn't loop at all, i.e. it works just for a given number, not all numbers below it. see ideone.com/pO6UwV ." That's not a reason to flag as moderators do not judge correctness, but it may be an issue. – dmckee --- ex-moderator kitten – 2013-04-11T00:00:38.130

Based upon this comment from the question creator: "@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. – NickC Jan 20 '12 at 21:00" it is doing what it should.

I.e. it only should process a single number. – Fors – 2013-04-11T04:42:21.750

sorry for that flag; I misread the requirement, and didn't have enough rep at the time, to comment directly. Sorry again. :) – Will Ness – 2013-04-13T19:48:11.530

0

Javascript, 75

function o(s){return s+((0|s/10%10)==1?"th":[,"st","nd","rd"][s%10]||"th")}

Inkbug

Posted 2012-01-20T17:57:02.027

Reputation: 468

0

Pyth, 33 bytes

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

Try it online!

clap

Posted 2012-01-20T17:57:02.027

Reputation: 834

0

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].

vasilescur

Posted 2012-01-20T17:57:02.027

Reputation: 341

0

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.

niczky12

Posted 2012-01-20T17:57:02.027

Reputation: 301

0

Python 2.7, 137 chars

def b(n):
 for e,o in[[i,'th']for i in['11','12','13']+list('4567890')]+[['2','nd'],['1','st'],['3','rd']]:
  if n.endswith(e):return n+o

n should be a string

I know I'm beaten by the competition here already, but I thought I'd provide my idea anyways

this just basically generates a list of key, value pairs with number (as a string) ending e and the ordinal o. It attempts to match 'th' first (hence why I didn't use a dictionary), so that it won't accidentally return 'st', for example, when it should be 'th'. This will work for any positive integer

Blazer

Posted 2012-01-20T17:57:02.027

Reputation: 1 902

n[-1]==e is 5 chars shorter than n.endswith(e) – hlt – 2014-02-14T11:30:34.953

0

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.

csomakk

Posted 2012-01-20T17:57:02.027

Reputation: 101

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. – ETHproductions – 2016-02-24T17:47:13.410

>

  • yeah, but thats quite straightforward, so I tried to stay readable.
  • < – csomakk – 2016-02-28T19:21:43.090

    start="2">

  • yeah, you're right, I just pasted it here so anyone can use it without reconverting from another lang. :)
  • < – csomakk – 2016-02-28T19:22:51.237

    0

    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
    

    Jeto

    Posted 2012-01-20T17:57:02.027

    Reputation: 1 601

    0

    Javascript ES6, 52 chars

    n=>n+(!/1.$/.test(--n)&&'snr'[n%=10]+'tdd'[n]||'th')
    

    Qwertiy

    Posted 2012-01-20T17:57:02.027

    Reputation: 2 697

    0

    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")
    

    Abel Terefe

    Posted 2012-01-20T17:57:02.027

    Reputation: 101

    Sorry, but all answers need to be golfed. Please golf this, if not than it's invalid and must be deleted. – Rɪᴋᴇʀ – 2016-09-23T12:53:07.013

    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! – clismique – 2016-09-28T06:13:43.643

    0

    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, 
    

    Kevin Cruijssen

    Posted 2012-01-20T17:57:02.027

    Reputation: 67 575