J - 44 44 41 char
(":,th`st`nd`rd{::~10 ~4|4<.10(]*[(~|*|~:*])4>]-~)/@#:]100&|)
10 10(...)/@#:]100&|
- First we take the argument (]
) and find the tens and ones digit (10 10 #:
). Then, we will insert(...)
betweenreduce the twoinput modulo 100.(]*[10(~|*|~:*])4>]-~)
- In this subexpression, but not the innermost one,]|
will point tois the ones digitinput mod 10 and[
the tens digit.[(~:*])4>]
--~:
is J for "not-equals", so this takes the result of4>]
input (i.e. whether or not the one digit is less than 4mod 100) and multiplies it by the result oftens ~: (4>])
minus 10. Why would anyone doYou don't get many trains as clean as this? Consider the following: one in J, so it's a treat to see here!- If we are checking 10, 11, 12, 13, then
tens
is1
(we are in the teens) andones~:
is less than 4not-equals, sotens ~|~: (4>])-~
is false andif the result is0*1
=0
. - If we are any other one of {X0, X1, X2, X3}, then clearly
tens ~: (4>])
tens digit is true1 and we get out1*1
=1
true otherwise. - If
ones*
is greater than fourjust multiplication, then4>]
was0
and it doesn't matter what happens toso we're taking the test anymoreinput mod 10 and multiplying by a boolean, wewhich will get0
zero it out regardlessif false. - So to summarize,
[(~:*])4>]
The result of this is1
if we are in {X0, X1, X2"input mod 10, X3} but not inexcept 0 on the teens, and0
otherwisetens".
- If we are checking 10, 11, 12, 13, then
]*4|4<.
- Finally we multiply that result by the ones digit. So this product will beMin (0<.
if) the number deserves a'th'
suffixabove with 4, else its valueto clamp down larger values, and then reduce modulo 4 so that they all go to zero.th`st`nd`rd{::~
- We use the modified ones-digit from above to Use that as an index into the list of suffixessuiffixes.0
gets'th'
Numbers ending in X1 or X2 or X3,1
getsbut not in 1X, will find their suffix, and everything else will take the 0th suffix'st'th
, and so on.":,
- Finally, take the original numberinput, convert it to a string (":
), and then prepend it toappend the suffix.
(":,th`st`nd`rd{::~10 ~4|4<.10(]*[(~|*|~:*])4>]-~)/@#:]100&|) 112 NB. single use
112th
(":,th`st`nd`rd{::~10 ~4|4<.10(]*[(~|*|~:*])4>]-~)/@#:]100&|) 1 2 3 4 5 NB. doing it wrong
|length error
| (":,th`st`nd`rd{::~10 ~4|4<.10(]*[(~|*|~:*])4>]-~)/@#:]100&|)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 ~4|4<.10(]*[(~|*|~:*])4>]-~)/@#:]100&|)&.> 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|
+----+----+----+----+----+----+----+----+----+----+
Alternative 41 char solution showing off a couple logical variants:
(":;@;st`nd`rd`th{~3<.10(|+3*|=-~)100|<:)
Previously I had an overlong explanation of this 44 char hunk of junk. 10 10#:
takes the last two decimal digits and /@
puts logic between them.
(":,th`st`nd`rd{::~10 10(]*[(~:*])4>])/@#:])