Skip to main content
saved 3 chars and outmoded an ugly explanation
Source Link
algorithmshark
  • 8.8k
  • 2
  • 33
  • 55

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 of 4>]input (i.e. whether or not the one digit is less than 4mod 100) and multiplies it by the result of tens ~: (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 is 1 (we are in the teens) and ones~: is less than 4not-equals, so tens ~|~: (4>])-~ is false andif the result is 0*1 = 0.
    • If we are any other one of {X0, X1, X2, X3}, then clearly tens ~: (4>])tens digit is true1 and we get out 1*1 = 1true otherwise.
    • If ones* is greater than fourjust multiplication, then 4>] was 0 and it doesn't matter what happens toso we're taking the test anymoreinput mod 10 and multiplying by a boolean, wewhich will get 0zero it out regardlessif false.
    • So to summarize, [(~:*])4>] The result of this is 1 if we are in {X0, X1, X2"input mod 10, X3} but not inexcept 0 on the teens, and 0 otherwisetens".
  • ]*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>])/@#:])

J - 44 char

(":,th`st`nd`rd{::~10 10(]*[(~:*])4>])/@#:])
  • 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.
   (":,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|
+----+----+----+----+----+----+----+----+----+----+

J -  44  41 char

(":,th`st`nd`rd{::~4|4<.10(|*|~:-~)100&|)
  • 100&| - First, reduce the input modulo 100.
  • 10(|*|~:-~) - In this subexpression, | is the input mod 10 and -~ is the input (mod 100) minus 10. You don't get many trains as clean as this one in J, so it's a treat to see here!
    • ~: is not-equals, so |~:-~ is false if the tens digit is 1 and true otherwise.
    • * is just multiplication, so we're taking the input mod 10 and multiplying by a boolean, which will zero it out if false. The result of this is "input mod 10, except 0 on the tens".
  • 4|4<. - Min (<.) the above with 4, to clamp down larger values, and then reduce modulo 4 so that they all go to zero.
  • th`st`nd`rd{::~ - Use that as an index into the list of suiffixes. Numbers ending in X1 or X2 or X3, but not in 1X, will find their suffix, and everything else will take the 0th suffix th.
  • ":, - Finally, take the original input, convert it to a string (":), and append the suffix.
   (":,th`st`nd`rd{::~4|4<.10(|*|~:-~)100&|) 112         NB. single use
112th
   (":,th`st`nd`rd{::~4|4<.10(|*|~:-~)100&|) 1 2 3 4 5   NB. doing it wrong
|length error
|       (":,th`st`nd`rd{::~4|4<.10(|*|~:-~)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{::~4|4<.10(|*|~:-~)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>])/@#:])
saved 3 char: 47 -> 44
Source Link
algorithmshark
  • 8.8k
  • 2
  • 33
  • 55

J - 4744 char

(":,(4 2$'thstndrd')th`st`nd`rd{::~10 10(]*[(~:*])4>])/@#:])
  • 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. ThisSo this product will be 0 if the number deserves a 'th' suffix, else its value.
  • 4 2$'thstndrd' - This creates a 4-item list of the suffixes, each two characters wide.
  • (...)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.
   (":,(4 2$'thstndrd')th`st`nd`rd{::~10 10(]*[(~:*])4>])/@#:]) 112         NB. single use
112th
   (":,(4 2$'thstndrd')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
st
nd
rd
th
th
   NB. i.5 10   makes a 5x10 grid of increasing integers
   NB. &.>      to operate on each integer separately, and box the result after
   (":,(4 2$'thstndrd')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|
+----+----+----+----+----+----+----+----+----+----+

J - 47 char

(":,(4 2$'thstndrd'){~10 10(]*[(~:*])4>])/@#:])
  • 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. This product will be 0 if the number deserves a 'th' suffix, else its value.
  • 4 2$'thstndrd' - This creates a 4-item list of the suffixes, each two characters wide.
  • (...){~ - 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.
   (":,(4 2$'thstndrd'){~10 10(]*[(~:*])4>])/@#:]) 112         NB. single use
112th
   (":,(4 2$'thstndrd'){~10 10(]*[(~:*])4>])/@#:]) 1 2 3 4 5   NB. doing it wrong
1 2 3 4 5
st
nd
rd
th
th
   NB. i.5 10   makes a 5x10 grid of increasing integers
   NB. &.>      to operate on each integer separately, and box the result after
   (":,(4 2$'thstndrd'){~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|
+----+----+----+----+----+----+----+----+----+----+

J - 44 char

(":,th`st`nd`rd{::~10 10(]*[(~:*])4>])/@#:])
  • 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.
   (":,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|
+----+----+----+----+----+----+----+----+----+----+
Source Link
algorithmshark
  • 8.8k
  • 2
  • 33
  • 55

J - 47 char

Nothing in J? This is an outrage!

(":,(4 2$'thstndrd'){~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. This product will be 0 if the number deserves a 'th' suffix, else its value.
  • 4 2$'thstndrd' - This creates a 4-item list of the suffixes, each two characters wide.
  • (...){~ - 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.

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