From: Clint Hyde
Subject: RE: manipulating integers as strings
Date: 
Message-ID: <3o35qm$nm2@info-server.bbn.com>
In article <··········@infa.central.susx.ac.uk> ·····@cogs.susx.ac.uk (John Williams) writes:
--> >Can someone tell me how I can take an integer, reverse its digits, and then use
--> >it as an argument to a function which requires a numeric argument? The function
--> >which does the reversal should be efficient as it will have to work with
--> >arbitrarily large integers. I tried converting the integer using the pack
--> >function (explode) and was then able to use reverse but getting the result back
--> >to an integer has so far eluded me.
--> 
--> 
--> Ira, how about using a function like the one below, which reverses
--> the digits without creating any intermediate strings? (It does build
--> a list though!).
--> 
--> John
--> ----
--> 
--> (defun REV-DIGITS (n &optional (base 10))
-->     ;; First create list of digits in "n"
-->     (let (digits)
-->         (loop
-->             (multiple-value-bind (quot rem) (truncate n base)
-->                 (push rem digits)
-->                 (if (zerop quot)
-->                     (return)
-->                     (setq n quot))))
-->         ;; Now build the "reversed" integer
-->         (let ((pow 1) (result 0))
-->             (dolist (d digits result)
-->                 (setq result (+ result (* d pow)))
-->                 (setq pow (* pow base))))))

that seems unnecessarily complex. 

this doesn't make a list, but does make a string. no math involved at
all.

(defun do-it1 (num)
  (let ((str (prin1-to-string num))
	len result)
    (setq len (length str))
    (setq result (make-string len))
    (dotimes (i len)
      (setf (aref result i) (aref str (- len i 1)))
      )
    (parse-integer result)
    )
  )
(do-it1 1234)		--> 4321
(do-it1 1234567890987)  --> 7890987654321

nice and short.  and the intermediate strings could be eliminated by
introducing the math.  as a string is probably an array in the typical
Lisp, this is likely more space efficient than the above version.  this
version is going to be WAY faster than the above one, too.  you allocate
(for example) 20 bytes, and flip some array elements around.

a trickier version would eliminate one string and use a bubble-sort
variation to swap elements end-for-end:

(defun do-it2 (num)
  (let* ((str (prin1-to-string num))
	 temp
	 (len (length str)))
    (dotimes (i (ash len -1) ;(/ len 2)
		)
      (setf temp (aref str i)
	    (aref str i) (aref str (- len i 1))
	    (aref str (- len i 1)) temp)
      )
    (parse-integer str)
    )
  )
(do-it2 12345)
(do-it2 1234567890987)

again, no math involved, I used ASH instead of (/ len 2). the only
annoying features are the prin1-to-string and the parse-integer. there
are a couple of further efficiencies achievable, but they're small. and
I wrote this on my Explorer 2, so they aren't even used...

 -- clint