# FORMAT & abbreviated ordinals - lisp

This is a discussion on FORMAT & abbreviated ordinals - lisp ; So if I do (format t &quot;~:R&quot; 4) I get fourth but I want 4th Any of you FORMAT wizards know a simple way to print abbreviated ordinals? -- Don _______________________________________________________________________________ Don Geddis http://don.geddis.org/ don@geddis.org Statisticians are people who like ...

1. ## FORMAT & abbreviated ordinals

So if I do
(format t "~:R" 4)
I get
fourth
but I want
4th

Any of you FORMAT wizards know a simple way to print abbreviated ordinals?

-- Don
_______________________________________________________________________________
Don Geddis http://don.geddis.org/ don@geddis.org
Statisticians are people who like figures, but don't have the personality
skills to become accountants. -- Peter Donnelly, TED (Jun 25, 2007)

2. ## Re: FORMAT & abbreviated ordinals

Don Geddis <don@geddis.org> wrote:
+---------------
| So if I do (format t "~:R" 4)
| I get fourth
| but I want 4th
| Any of you FORMAT wizards know a simple way to print abbreviated ordinals?
+---------------

Not using "~R" per se, but I once had occasion to need the same
thing, and I did it something like this [though ISTR that I may
have used an AREF on a vector of 10 strings instead of the CASE]:

> (defun ordinal-suffix (n)

(let ((n (mod n 100)))
(if (<= 11 n 13) ; special-case English-language rule
"th"
(let ((which (mod n 10)))
(case which
((1) "st")
((2) "nd")
((3) "rd")
(t "th"))))))

ORDINAL-SUFFIX
> (loop for i to 225

collect (format nil "~d~a" i (ordinal-suffix i)))

("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" "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" "201st" "202nd" "203rd"
"204th" "205th" "206th" "207th" "208th" "209th" "210th" "211th"
"212th" "213th" "214th" "215th" "216th" "217th" "218th" "219th"
"220th" "221st" "222nd" "223rd" "224th" "225th")
>

-Rob

-----
Rob Warnock <rpw3@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607

3. ## Re: FORMAT & abbreviated ordinals

rpw3@rpw3.org (Rob Warnock) writes:

> Don Geddis <don@geddis.org> wrote:
> +---------------
> | So if I do (format t "~:R" 4)
> | I get fourth
> | but I want 4th
> | Any of you FORMAT wizards know a simple way to print abbreviated ordinals?
> +---------------
>
> Not using "~R" per se, but I once had occasion to need the same
> thing, and I did it something like this [though ISTR that I may
> have used an AREF on a vector of 10 strings instead of the CASE]:
>
> > (defun ordinal-suffix (n)

> (let ((n (mod n 100)))
> (if (<= 11 n 13) ; special-case English-language rule
> "th"
> (let ((which (mod n 10)))
> (case which
> ((1) "st")
> ((2) "nd")
> ((3) "rd")
> (t "th"))))))
>
> ORDINAL-SUFFIX
> > (loop for i to 225

> collect (format nil "~d~a" i (ordinal-suffix i)))

Ick. Coding things like that not only requires way too much thought
but also ends up way too efficient. The following is easier on the
brain and not so irritatingly conservative about computational and
garbage collection overhead...

(defun abbreviated-ordinal (n)
(let* ((long-ordinal (format nil "~:R" n))
(len (length long-ordinal)))
(format nil "~D~A" n (subseq long-ordinal (- len 2) len))))

(defun show-abbreviated-ordinal (stream n at-sign colon &rest params)
(declare (ignore at-sign colon params))
(write-string (abbreviated-ordinal n) stream))

;; Note that ~/.../ requires a package prefix, it's NOT optional.

(format nil "~/CL-USER::SHOW-ABBREVIATED-ORDINAL/" 3)
=> "3rd"

(format t "~/CL-USER::SHOW-ABBREVIATED-ORDINAL/" 37)
37th
=> NIL

4. ## Re: FORMAT & abbreviated ordinals

Kent M Pitman wrote:
> rpw3@rpw3.org (Rob Warnock) writes:
>
>
>>Don Geddis <don@geddis.org> wrote:
>>+---------------
>>| So if I do (format t "~:R" 4)
>>| I get fourth
>>| but I want 4th
>>| Any of you FORMAT wizards know a simple way to print abbreviated ordinals?
>>+---------------
>>
>>Not using "~R" per se, but I once had occasion to need the same
>>thing, and I did it something like this [though ISTR that I may
>>have used an AREF on a vector of 10 strings instead of the CASE]:
>>
>> > (defun ordinal-suffix (n)

>> (let ((n (mod n 100)))
>> (if (<= 11 n 13) ; special-case English-language rule
>> "th"
>> (let ((which (mod n 10)))
>> (case which
>> ((1) "st")
>> ((2) "nd")
>> ((3) "rd")
>> (t "th"))))))
>>
>> ORDINAL-SUFFIX
>> > (loop for i to 225

>> collect (format nil "~d~a" i (ordinal-suffix i)))

>
>
> Ick. Coding things like that not only requires way too much thought
> but also ends up way too efficient. The following is easier on the
> brain and not so irritatingly conservative about computational and
> garbage collection overhead...
>
> (defun abbreviated-ordinal (n)
> (let* ((long-ordinal (format nil "~:R" n))
> (len (length long-ordinal)))
> (format nil "~D~A" n (subseq long-ordinal (- len 2) len))))
>
> (defun show-abbreviated-ordinal (stream n at-sign colon &rest params)
> (declare (ignore at-sign colon params))
> (write-string (abbreviated-ordinal n) stream))
>
> ;; Note that ~/.../ requires a package prefix, it's NOT optional.
>
> (format nil "~/CL-USER::SHOW-ABBREVIATED-ORDINAL/" 3)
> => "3rd"
>
> (format t "~/CL-USER::SHOW-ABBREVIATED-ORDINAL/" 37)
> 37th
> => NIL
>

Sweet. I had:

(loop for i to 10
for j = (let ((n (mod i 100)))
(if (<= 11 n 13)
4 (min (mod n 10) 4)))
collect (format nil "~d~c~c" i
(schar "tsnrt" j)
(schar "htddh" j)))

kzo

--
http://www.theoryyalgebra.com/

"In the morning, hear the Way;
in the evening, die content!"
-- Confucius

5. ## Re: FORMAT & abbreviated ordinals

On Fri, Nov 02 2007, Kent M Pitman wrote:

> rpw3@rpw3.org (Rob Warnock) writes:
>
>> Don Geddis <don@geddis.org> wrote:
>> +---------------
>> | So if I do (format t "~:R" 4)
>> | I get fourth
>> | but I want 4th
>> | Any of you FORMAT wizards know a simple way to print abbreviated ordinals?
>> +---------------
>>
>> Not using "~R" per se, but I once had occasion to need the same
>> thing, and I did it something like this [though ISTR that I may
>> have used an AREF on a vector of 10 strings instead of the CASE]:
>>
>> > (defun ordinal-suffix (n)

>> (let ((n (mod n 100)))
>> (if (<= 11 n 13) ; special-case English-language rule
>> "th"
>> (let ((which (mod n 10)))
>> (case which
>> ((1) "st")
>> ((2) "nd")
>> ((3) "rd")
>> (t "th"))))))
>>
>> ORDINAL-SUFFIX
>> > (loop for i to 225

>> collect (format nil "~d~a" i (ordinal-suffix i)))

>
> Ick. Coding things like that not only requires way too much thought
> but also ends up way too efficient. The following is easier on the
> brain and not so irritatingly conservative about computational and
> garbage collection overhead...
>
> (defun abbreviated-ordinal (n)
> (let* ((long-ordinal (format nil "~:R" n))
> (len (length long-ordinal)))
> (format nil "~D~A" n (subseq long-ordinal (- len 2) len))))
>
> (defun show-abbreviated-ordinal (stream n at-sign colon &rest params)
> (declare (ignore at-sign colon params))
> (write-string (abbreviated-ordinal n) stream))

The Rob's solution might be verbose, complex and inefficient, however
it has one big advantage - it's extensible to support other languages.

As you know the multi-language support is an objective reason when
weighting one or another solution.

--
Камен

6. ## Re: FORMAT & abbreviated ordinals

Kamen TOMOV <kamen@cybuild.com> writes:

> The Rob's solution might be verbose, complex and inefficient, however
> it has one big advantage - it's extensible to support other languages.

Good point. I had actually thought of that but forgot to write in
"mine is also harder to internationalize" as one of my touted virtues.

But more seriously, his paradigm certainly is... but the choice points
are all different, of course.

Also, once you start to internationalize you realize that additional
data is needed, since the choice of gender and other such information
plays in. The choice between "6o" and "6a" in some languages, for
example. (And some languages require even more concepts than gender
to play in, I think--aren't there languages that count differently for
objects of different classes, such as whether the thing being couned
is alive or not, no? Japanese maybe? I don't know any Japanese but
for some reason I have it in my head that it has such a distinction
.... I took survey courses on the world languages years ago and we
covered issues like this but the details get fuzzier over time. Maybe
someone will refresh or correct my memory.)

> As you know the multi-language support is an objective reason when
> weighting one or another solution.

Certainly. I have from time to time tried to develop tools that
accommodate that space, and I totally agree it's important. In the
case in question, though, with the dataflow usually given (e.g.,
through format arguments), the problem is arguably theoretically
unsolvable once you go outside the "narrow" region of CL's preferred
language, Federation Standard. One has to relax some constraint
(either more dataflow in [gender, etc], or less flexibility out [works
only in one or a small number of languages]).

7. ## Re: FORMAT & abbreviated ordinals

+ Kent M Pitman <pitman@nhplace.com>:

> Also, once you start to internationalize you realize that additional
> data is needed, since the choice of gender and other such
> information plays in.

Plus, in some languages, there is hardly any tradition for abbreviated
ordinals. I'll stick my neck out and state that I have never seen
them in Norwegian, except possibly in some fairly old literature. But
that is arguably Danish, not Norwegian anyhow. 8-)

--
* Harald Hanche-Olsen <URL:http://www.math.ntnu.no/~hanche/>
- It is undesirable to believe a proposition
when there is no ground whatsoever for supposing it is true.
-- Bertrand Russell

8. ## Re: FORMAT & abbreviated ordinals

Kent M Pitman <pitman@nhplace.com> writes:

> (And some languages require even more concepts than gender
> to play in, I think--aren't there languages that count differently for
> objects of different classes, such as whether the thing being couned
> is alive or not, no? Japanese maybe?

Yes. Japanese uses different "counter" suffixes depending on object
type; in addition, the numbers can change from Chinese to Japanese
numbers (e.g., ni-ban is the ordinal "two", ringo ni-ko is "two
apples", but "futa-tsu" is "two (miscellaneous things)"); the futatsu
comes from the traditional Japanese numbering system).

http://en.wikipedia.org/wiki/Japanese_counter_word goes into some of
the gory details.
--
I'm awfully glad I'm a Beta, because I don't work so hard.

9. ## Re: FORMAT & abbreviated ordinals

>>>Don Geddis <don@geddis.org> wrote:
>>>+---------------
>>>| So if I do (format t "~:R" 4)
>>>| I get fourth
>>>| but I want 4th
>>>| Any of you FORMAT wizards know a simple way to print abbreviated ordinals?
>>>+---------------

>> rpw3@rpw3.org (Rob Warnock) writes:
>>> (defun ordinal-suffix (n)
>>> (let ((n (mod n 100)))
>>> (if (<= 11 n 13) ; special-case English-language rule
>>> "th"
>>> (let ((which (mod n 10)))
>>> (case which
>>> ((1) "st")
>>> ((2) "nd")
>>> ((3) "rd")
>>> (t "th"))))))

> Kent M Pitman wrote:
>> (defun abbreviated-ordinal (n)
>> (let* ((long-ordinal (format nil "~:R" n))
>> (len (length long-ordinal)))
>> (format nil "~D~A" n (subseq long-ordinal (- len 2) len))))
>> (defun show-abbreviated-ordinal (stream n at-sign colon &rest params)
>> (declare (ignore at-sign colon params))
>> (write-string (abbreviated-ordinal n) stream))
>> ;; Note that ~/.../ requires a package prefix, it's NOT optional.
>> (format nil "~/CL-USER::SHOW-ABBREVIATED-ORDINAL/" 3)
>> => "3rd"

Ken Tilton <kennytilton@optonline.net> wrote on Fri, 02 Nov 2007:
> (loop for i to 10
> for j = (let ((n (mod i 100)))
> (if (<= 11 n 13)
> 4 (min (mod n 10) 4)))
> collect (format nil "~d~c~c" i
> (schar "tsnrt" j)
> (schar "htddh" j)))

Thanks, all! While falling asleep last night, I sketched out Rob's solution
to myself, and (the first half of) Kent's solution. Didn't know if there was
a simpler "obvious" way that I was missing.

Kenny's solution I would never have invented in a million years. I am
nonetheless pleased that I am still able to at least understand such sublime
code fragments from His Kennyness. (Kenniness?)

-- Don
_______________________________________________________________________________
Don Geddis http://don.geddis.org/ don@geddis.org
The Creation of the Universe was made possible by a grant from Texas
Instruments. -- PBS

10. ## Re: FORMAT & abbreviated ordinals

On Fri, Nov 02 2007, Kent M Pitman wrote:

> Kamen TOMOV writes:
>
>> The Rob's solution might be verbose, complex and inefficient,
>> however it has one big advantage - it's extensible to support other
>> languages.

>
> Good point. I had actually thought of that but forgot to write in
> "mine is also harder to internationalize" as one of my touted
> virtues.
>
> But more seriously, his paradigm certainly is... but the choice
> points are all different, of course.
>

Sure.

> Also, once you start to internationalize you realize that additional
> data is needed, since the choice of gender and other such
> information plays in.

Right. Even popular languages like French and (I suppose) Spanish have
gender.

> The choice between "6o" and "6a" in some languages, for example.

Hmm what would "6o" or "6a" mean?

> (And some languages require even more concepts than gender to play
> in, I think--aren't there languages that count differently for
> objects of different classes, such as whether the thing being couned
> is alive or not, no? Japanese maybe? I don't know any Japanese but
> for some reason I have it in my head that it has such a distinction
> ... I took survey courses on the world languages years ago and we
> covered issues like this but the details get fuzzier over
> time. Maybe someone will refresh or correct my memory.)

At least Bulgarian and Russian qualify. For example you count:

- one male
- one female
- one thing

and in these languages the word for "one" is different for all
cases. The destinction between "male" and "female" objects is not
always obvious to foreigners studying these languages. The destiction
of "things" include all not living things as well as all animals as
well as the kids.

>> As you know the multi-language support is an objective reason when
>> weighting one or another solution.

>
> Certainly. I have from time to time tried to develop tools that
> accommodate that space, and I totally agree it's important. In the
> case in question, though, with the dataflow usually given (e.g.,
> through format arguments), the problem is arguably theoretically
> unsolvable once you go outside the "narrow" region of CL's preferred
> language, Federation Standard. One has to relax some constraint
> (either more dataflow in [gender, etc], or less flexibility out [works
> only in one or a small number of languages]).

Constraint relaxation is fine - as long as there exist a reasoable
solution like in the current issue. By the way it is very interesting
to me when did multi-language support started to matter during the
development of Lisp?

Best regards,

--
Камен

+ Reply to Thread
Page 1 of 2 1 2 Last