4
\$\begingroup\$

This Common Lisp program is an exercise to print an integer and its digits reversed to the screen:

(defun read-number () (format t "Enter a number: ~%") (read))

(defun reverse-string (the-string) 
  (if (eq (length the-string) 0) 
    "" 
    (concatenate 'string (reverse-string (subseq the-string 1)) (subseq the-string 0 1))))

(defun reverse-digits (the-number) (reverse-string (write-to-string the-number)))

(let ((the-number (read-number)))
  (format t "N->: ~a~%<-N: ~a~%" the-number (reverse-digits the-number)))
\$\endgroup\$
2
  • \$\begingroup\$ Wow, lots of Lisp exercises. Is this for school, or did you just pick it up for the hell of it? :) \$\endgroup\$
    – Inaimathi
    Commented Mar 10, 2011 at 2:24
  • \$\begingroup\$ Just picked it up for the heck of it :) I've always heard Lisp is a good language to learn. \$\endgroup\$
    – jaresty
    Commented Mar 10, 2011 at 6:27

2 Answers 2

4
\$\begingroup\$

This problem is more about numbers than strings, so I felt the need to post a non-string-based solution. I've got my original Scheme version, and a Common Lisp adaptation of same.

Scheme version:

(define (reverse-digits n)
  (let loop ((n n) (r 0))
    (if (zero? n) r
        (loop (quotient n 10) (+ (* r 10) (remainder n 10))))))

Common Lisp translation of the Scheme version:

(defun reverse-digits (n)
  (labels ((next (n v)
             (if (zerop n) v
                 (multiple-value-bind (q r)
                     (truncate n 10)
                   (next q (+ (* v 10) r))))))
    (next n 0)))
\$\endgroup\$
5
  • \$\begingroup\$ I meanwhile wrote my own version of quotient, idiv. remainder and module seem to be synonyms. \$\endgroup\$ Commented Mar 10, 2011 at 4:16
  • \$\begingroup\$ @user unknown: remainder and modulo have different behaviour if the dividend is negative. (remainder -5 3) => -2, whereas (modulo -5 3) => 1. \$\endgroup\$ Commented Mar 10, 2011 at 4:24
  • \$\begingroup\$ Yeah, I didn't test negative values. For such, I would use a wrapper method. (if (< 0 x) (* -1 (redigit (* -1 x) 0))) \$\endgroup\$ Commented Mar 10, 2011 at 7:12
  • \$\begingroup\$ +1 - Just keep in mind that TCO isn't guaranteed in CL the way it is in Scheme. \$\endgroup\$
    – Inaimathi
    Commented Mar 10, 2011 at 15:18
  • 1
    \$\begingroup\$ @Inaimathi: Of course. But how many digits is your number going to have? ;-) \$\endgroup\$ Commented Mar 10, 2011 at 15:19
1
\$\begingroup\$

You're talking about digits and integer, but to me, as an non-lisper, it looks as if you operate on Strings.

  • I would take the number, modulo 10, print that digit.
  • If the rest is > 0 recursively call the function with the (number - digit) / 10.

In most languages with integer-arithmetic you can omit the subtraction, since 37/10 => 3 :==: (37-7)/10 => 3

In scala it would look like this:

def redigit (n: Int, sofar: Int = 0) : Int = { 
     if (n == 0) sofar else                     
     redigit (n / 10, sofar * 10 + n % 10)}

redigit (123)
321 

It uses default arguments. First tests with DrScheme didn't succeed. Here is what I came up with:

;; redigit : number number -> number
(define (redigit in sofar)
  (cond [(< in 1) sofar]
      [else (redigit (/ in 10) (+ (* 10 sofar) (modulo in 10)))]) 
)

(redigit 134 0) 

But the division is precise and doesn't cut off the digits behind the floting point. I get this error:

modulo: expects type as 1st argument, given: 67/5; other arguments were: 10

I looked for a function toInt, asInt, floor, round and so on for the term (/ in 10) but I didn't find something useful. Maybe you know it yourself?

\$\endgroup\$
1
  • \$\begingroup\$ You need to use quotient and remainder. See my answer. :-) \$\endgroup\$ Commented Mar 10, 2011 at 4:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.