Author Topic: < Challenge > Integers into words / Ordinal Numbers into words  (Read 23317 times)

0 Members and 2 Guests are viewing this topic.

Lee Mac

  • Seagull
  • Posts: 12912
  • London, England
Re: < Challenge > Integers into words / Ordinal Numbers into words
« Reply #15 on: February 12, 2013, 07:31:04 AM »
Lee, I discovered that:
 (LM:int->words 12300120123010211)
"twelve quadrillion three hundred trillion one hundred twenty billion
one hundred twenty three million ten thousand two hundred ten"

Doubles can only hold about 16 significant figures of precision.

Lee Mac

  • Seagull
  • Posts: 12912
  • London, England
Re: < Challenge > Integers into words / Ordinal Numbers into words
« Reply #16 on: February 12, 2013, 09:09:54 AM »
Here is another for conversion to roman numerals (for integers < 4000):
Code: [Select]
(defun LM:int->roman ( n / f )
    (defun f ( n r )
        (cond
            ((or (< n 1) (null r)) "")
            ((<= (caar r) n) (strcat (cadar r) (f (- n (caar r)) r)))
            ((f n (cdr r)))
        )
    )
    (f n '((1000 "M") (900 "CM") (500 "D") (400 "CD") (100 "C") (90 "XC") (50 "L") (40 "XL") (10 "X") (9 "IX") (5 "V") (4 "IV") (1 "I")))
)

Code: [Select]
_$ (LM:int->roman 3886)
"MMMDCCCLXXXVI"

Marc'Antonio Alessi

  • Swamp Rat
  • Posts: 1451
  • Marco
Re: < Challenge > Integers into words / Ordinal Numbers into words
« Reply #17 on: February 12, 2013, 12:30:39 PM »
Here is another for conversion to roman numerals (for integers < 4000):
...
Thanks. I see that recursion is your passion!
Cheers.


Lee Mac

  • Seagull
  • Posts: 12912
  • London, England
Re: < Challenge > Integers into words / Ordinal Numbers into words
« Reply #19 on: February 12, 2013, 01:01:42 PM »
Here is another for conversion to roman numerals (for integers < 4000):
...
Thanks. I see that recursion is your passion!
Cheers.

Indeed, I love the elegance and concision of recursive solutions  :-)

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: < Challenge > Integers into words / Ordinal Numbers into words
« Reply #20 on: February 13, 2013, 12:15:28 AM »
Here is another for conversion to roman numerals (for integers < 4000):
...
Thanks. I see that recursion is your passion!
Cheers.

Indeed, I love the elegance and concision of recursive solutions  :-)
Exactly! Just look at the monster I had in one of my old addons - using only iteration (AInc:Num2Roman):
http://sourceforge.net/p/caddons/code/67/tree/General/AutoIncr.LSP

Lee's is literally less than a 1/10th of the coding I needed. 10 lines instead of 130!
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

Marc'Antonio Alessi

  • Swamp Rat
  • Posts: 1451
  • Marco
Re: < Challenge > Integers into words / Ordinal Numbers into words
« Reply #21 on: February 13, 2013, 04:22:38 AM »

> "Indeed, I love the elegance and concision of recursive solutions  :-)"

Exactly! Just look at the monster I had in one of my old addons - using only iteration (AInc:Num2Roman):
http://sourceforge.net/p/caddons/code/67/tree/General/AutoIncr.LSP
Lee's is literally less than a 1/10th of the coding I needed. 10 lines instead of 130!
Recursion is elegant, concise but often is slower and cause problems with long lists of data. If I must do a very frequently-used function I prefer the classic form... maybe I will say this because my mind is not well suited to recursive thinking! (Lee is a monster)
I have downloaded your file, interesting, I put it in my collection of Lisp.

Question: I seem to have noticed that in the files "Lisp" original Autodesk (see also ExpressTools) does not makes heavy use of recursion. This is due to the lack of skill of the Autodesk programmers?

My apologies for my english.

; Benchmark.lsp | © 2005 Michael Puckett | All Rights Reserved
; Elapsed milliseconds / relative speed for 32768 iteration(s):
;    (ALE_INT->ROMAN 3886).....1123 / 2.35 <fastest>
;    (LM:INT->ROMAN 3886)......2637 / 1    <slowest>

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: < Challenge > Integers into words / Ordinal Numbers into words
« Reply #22 on: February 13, 2013, 06:13:47 AM »
Question: I seem to have noticed that in the files "Lisp" original Autodesk (see also ExpressTools) does not makes heavy use of recursion. This is due to the lack of skill of the Autodesk programmers?
I would really not know, but I doubt it's a case of not knowing recursion. It's probably more a case of knowing iteration better.

Same principle as you can see a C++ programmer declaring & initializing local variables needlessly in a functional program. That's also quite prevalent in the express tools. It doesn't mean they don't know how to use functional programming, it's more a case of they know imperative a lot better and are used to variable declaration & initialization at the start of the function (which is generally a good idea in languages like C++).

That code of mine is also written more imperatively centric, since then I've learnt to embrace the functional way a lot more. And in lisp it's not extremely bad to go with functional and/or recursive, it's sometimes not even less efficient than an imperative & iterative method. Not to mention, the time you waste in typing all the code and then debugging the inevitable typo is greatly reduced when using recursion / functional.

You and me are in the same boat about recursion though. I know how, it's just that the recursive solution isn't the first one I think of. My mind seems to be iterative - but perhaps since I come from a C++/Pascal/Delphi/Java background. What i do miss greatly in AutoLisp is Object Orientation - sometimes that can also reduce coding a lot and make your programs a lot more robust.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

Lee Mac

  • Seagull
  • Posts: 12912
  • London, England
Re: < Challenge > Integers into words / Ordinal Numbers into words
« Reply #23 on: February 13, 2013, 07:29:45 AM »
If you prefer iteration:

Code: [Select]
(defun LM:int->roman2 ( n / s )
    (setq s "")
    (mapcar (function (lambda ( d r ) (while (<= d n) (setq s (strcat s r) n (- n d)))))
       '(1000 900 500 400 100 90 50 40 10 9 5 4 1)
       '("M" "CM" "D" "CD" "C" "XC" "L" "XL" "X" "IX" "V" "IV" "I")
    )
    s
)

Marc'Antonio Alessi

  • Swamp Rat
  • Posts: 1451
  • Marco
Re: < Challenge > Integers into words / Ordinal Numbers into words
« Reply #24 on: February 13, 2013, 08:45:49 AM »
If you prefer iteration:

Code: [Select]
(defun LM:int->roman2 ( n / s )
    (setq s "")
    (mapcar (function (lambda ( d r ) (while (<= d n) (setq s (strcat s r) n (- n d)))))
       '(1000 900 500 400 100 90 50 40 10 9 5 4 1)
       '("M" "CM" "D" "CD" "C" "XC" "L" "XL" "X" "IX" "V" "IV" "I")
    )
    s
)
Meraviglioso.  :kewl: I think this is the best in elegance, concision and performance.  :kewl: :kewl: :kewl:

Lee Mac

  • Seagull
  • Posts: 12912
  • London, England
Re: < Challenge > Integers into words / Ordinal Numbers into words
« Reply #25 on: February 13, 2013, 09:07:38 AM »
Thank you Marc :-)

hmspe

  • Bull Frog
  • Posts: 362
Re: < Challenge > Integers into words / Ordinal Numbers into words
« Reply #26 on: February 13, 2013, 09:47:36 AM »
My guess on the original lisp routines from Autocad is that they were written quickly and that the authors stopped when the code was "good enough" rather than take the time to optimize the code.  Back when I was programming for a living (Turbo/Borland Pascal and Borland C++) I generally wanted to write everything twice.  I'd get the first pass code working and relatively bug free, then I would want to do a complete re-write to make the code faster and more elegant.  I seldom got the chance to re-write.  Most of the Express Tools code looks to me like the same thing happened there.
"Science is the belief in the ignorance of experts." - Richard Feynman

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: < Challenge > Integers into words / Ordinal Numbers into words
« Reply #27 on: February 13, 2013, 03:32:38 PM »
Wow ... once I saw your code I though: How simple! (read as compliment  ;) ) I could've kicked myself for not getting to that half-functional / half-imperative but iterative method! It's a perfect example of how to make use of mapcar in a way not strictly as intended. You could've done the same using foreach I guess, but then your list should look similar to your previous recursive method:
Code - Auto/Visual Lisp: [Select]
  1. (defun Int->Roman  (num / result)
  2.   (setq result "")
  3.   (foreach code  '((1000 "M") (900 "CM") (500 "D") (400 "CD") (100 "C") (90 "XC")
  4.                    (50 "L") (40 "XL") (10 "X") (9 "IX") (5 "V") (4 "IV") (1 "I"))
  5.     (while (<= (car code) num) (setq result (strcat result (cadr code)) num (- num (car code)))))
  6.   result)

I'm now thinking, what about other more convoluted numbering systems? Say the Babilonian system? A mix of decimal and senary written in binary (edit: make that ternary, since zero is represented by a space) forming a base 60 numbering system.
Code - Auto/Visual Lisp: [Select]
  1. (defun Int->Babilonian (num / item result bases)
  2.   (setq bases '((10 "T") (6 "<")) result "")
  3.   (while (> num 0)
  4.     (setq item "")
  5.     (repeat (rem num (caar bases)) (setq item (strcat (cadar bases) item)))
  6.     (repeat (- (caar bases) (strlen item)) (setq item (strcat " " item)))
  7.     (setq result (strcat item result)
  8.           num (fix (/ num (caar bases)))
  9.           bases (reverse bases)))
  10.   result)
« Last Edit: February 13, 2013, 05:42:13 PM by irneb »
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: < Challenge > Integers into words / Ordinal Numbers into words
« Reply #28 on: February 13, 2013, 04:12:16 PM »
Actually a more strictly "correct" algorithm for the Babilonian system would be:
Code - Auto/Visual Lisp: [Select]
  1. (defun Int->Babilonian (num / digit item result bases)
  2.   (setq bases '((10 "T") (6 "<")))
  3.   (while (or (> num 0) (= (caar bases) 6))
  4.     (setq item "")
  5.     (repeat (rem num (caar bases)) (setq item (strcat (cadar bases) item)))
  6.     (repeat (- (caar bases) (strlen item) 1) (setq item (strcat " " item)))
  7.     (cond ((= (caar bases) 6) (setq result (cons (strcat item digit) result)))
  8.           (t (setq digit item)))
  9.     (setq num (fix (/ num (caar bases)))
  10.           bases (reverse bases)))
  11.   result)
Some "nifty" samples:
Code: [Select]
_$ (Int->Babilonian 62)
("             T" "            TT")
_$ (Int->Babilonian 79)
("             T" "    <TTTTTTTTT")
_$ (Int->Babilonian 19)
("    <TTTTTTTTT")
_$ (Int->Babilonian 11)
("    <        T")
_$ (Int->Babilonian 600)
("    <         " "              ")
_$ (Int->Babilonian 3600)
("             T" "              " "              ")
_$ (Int->Babilonian 3599)
("<<<<<TTTTTTTTT" "<<<<<TTTTTTTTT")
BTW, this is apparently where the concept of 360 degrees in a circle comes from. Notice the "pattern":
Code: [Select]
_$ (Int->Babilonian 30)
("  <<<         ")
_$ (Int->Babilonian 60)
("             T" "              ")
_$ (Int->Babilonian 90)
("             T" "  <<<         ")
_$ (Int->Babilonian 120)
("            TT" "              ")
_$ (Int->Babilonian 150)
("            TT" "  <<<         ")
_$ (Int->Babilonian 180)
("           TTT" "              ")
_$ (Int->Babilonian 210)
("           TTT" "  <<<         ")
_$ (Int->Babilonian 240)
("          TTTT" "              ")
_$ (Int->Babilonian 270)
("          TTTT" "  <<<         ")
_$ (Int->Babilonian 300)
("         TTTTT" "              ")
_$ (Int->Babilonian 330)
("         TTTTT" "  <<<         ")
_$ (Int->Babilonian 360)
("        TTTTTT" "              ")
The "circle's" degrees would be the sidereal turns of the earth in a year. I.e. around 366, and the Babilonians then used the closest "round" number in their system = 360. since then we're stuck with it. http://www.physlink.com/education/askexperts/ae373.cfm

And for what it's worth the 60 seconds, 60 minutes was also from them. You can thank the Egyptians for the 24 hours: http://www.abc.net.au/science/articles/2011/11/15/3364432.htm
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: < Challenge > Integers into words / Ordinal Numbers into words
« Reply #29 on: February 13, 2013, 05:26:45 PM »
As for the reverse of this challenge (words into numbers), I think I've got it:
Code - Auto/Visual Lisp: [Select]
  1. (defun word->int  (words / fact)
  2.   (setq fact 1)
  3.   (apply '+
  4.               (lambda (sym / pos)
  5.                 (cond ((setq pos (vl-position sym
  6.                                    '(nil       One       Two       Three     Four      Five      Six       Seven
  7.                                      Eight     Nine      Ten       Eleven    Twelve    Thirteen  Fourteen  Fifteen
  8.                                      Sixteen   Seventeen Eighteen  Nineteen)))
  9.                        (* fact pos))
  10.                       ((setq pos (vl-position sym '(nil nil Twenty Thirty Fourty Fifty Sixty Seventy Eighty Ninety)))
  11.                        (* fact pos 10))
  12.                       ((= sym 'Hundred) (setq fact (* fact 100)) 0)
  13.                       ((setq pos (assoc sym '((thousand 1000) (million 1e6) (billion 1e9) (trillion 1e12) (quadrillion 1e15) (quintillion 1e18))))
  14.                        (setq fact (if (>= fact (cadr pos)) (* fact 1000) (cadr pos)))
  15.                        0)
  16.                       (t 0))))
  17.             (reverse (read (strcat "(" words ")"))))))
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.