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\$
  • \$\begingroup\$ Wow, lots of Lisp exercises. Is this for school, or did you just pick it up for the hell of it? :) \$\endgroup\$ – Inaimathi Mar 10 '11 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 Mar 10 '11 at 6:27
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\$
  • \$\begingroup\$ I meanwhile wrote my own version of quotient, idiv. remainder and module seem to be synonyms. \$\endgroup\$ – user unknown Mar 10 '11 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\$ – Chris Jester-Young Mar 10 '11 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\$ – user unknown Mar 10 '11 at 7:12
  • \$\begingroup\$ +1 - Just keep in mind that TCO isn't guaranteed in CL the way it is in Scheme. \$\endgroup\$ – Inaimathi Mar 10 '11 at 15:18
  • 1
    \$\begingroup\$ @Inaimathi: Of course. But how many digits is your number going to have? ;-) \$\endgroup\$ – Chris Jester-Young Mar 10 '11 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\$
  • \$\begingroup\$ You need to use quotient and remainder. See my answer. :-) \$\endgroup\$ – Chris Jester-Young Mar 10 '11 at 4:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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