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)))
-
\$\begingroup\$ Wow, lots of Lisp exercises. Is this for school, or did you just pick it up for the hell of it? :) \$\endgroup\$Inaimathi– Inaimathi2011年03月10日 02:24:08 +00:00Commented 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– jaresty2011年03月10日 06:27:26 +00:00Commented Mar 10, 2011 at 6:27
2 Answers 2
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)))
-
\$\begingroup\$ I meanwhile wrote my own version of
quotient
,idiv
.remainder
andmodule
seem to be synonyms. \$\endgroup\$user unknown– user unknown2011年03月10日 04:16:22 +00:00Commented Mar 10, 2011 at 4:16 -
\$\begingroup\$ @user unknown:
remainder
andmodulo
have different behaviour if the dividend is negative.(remainder -5 3)
=> -2, whereas(modulo -5 3)
=> 1. \$\endgroup\$C. K. Young– C. K. Young2011年03月10日 04:24:27 +00:00Commented 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\$user unknown– user unknown2011年03月10日 07:12:29 +00:00Commented 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– Inaimathi2011年03月10日 15:18:18 +00:00Commented Mar 10, 2011 at 15:18
-
1\$\begingroup\$ @Inaimathi: Of course. But how many digits is your number going to have? ;-) \$\endgroup\$C. K. Young– C. K. Young2011年03月10日 15:19:30 +00:00Commented Mar 10, 2011 at 15:19
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?
-
\$\begingroup\$ You need to use
quotient
andremainder
. See my answer. :-) \$\endgroup\$C. K. Young– C. K. Young2011年03月10日 04:08:09 +00:00Commented Mar 10, 2011 at 4:08