On Thu, Feb 17, 2011 at 1:39 AM, Shantanu Kumar <kumar.shant...@gmail.com> wrote: > On Feb 17, 11:09 am, Ken Wesson <kwess...@gmail.com> wrote: >> On Thu, Feb 17, 2011 at 12:29 AM, Andreas Kostler >> >> <andreas.koestler.le...@gmail.com> wrote: >> > Is there an easy and idiomatic way of getting the digits of a number in >> > clojure? >> >> > (defn explode-to-digits [number] >> > (map #(- (int %) (int \0)) (str number))) >> > (explode-to-digits 123456) >> > => (1 2 3 4 5 6) >> >> > Seems a bit clunky... >> >> How about >> >> (defn explode-to-digits [n] >> (if (= n 0) >> [] >> (let [d (rem n 10) >> r (quot n 10)] >> (conj (explode-to-digits r) d)))) >> >> or if you want to avoid consuming stack >> >> (defn explode-to-digits* [n out] >> (if (= n 0) >> out >> (let [d (rem n 10) >> r (quot n 10)] >> (recur r (cons d out))))) >> >> (defn explode-to-digits [n] >> (explode-to-digits* n nil)) >> >> It should also be possible to make a lazy sequence version, but >> returning the digits in the reverse order. > > A bit shorter: > > (defn digits [n] > (let [r (rem n 10) > q (int (/ n 10)) > _ (println (format "q=%d, r=%d" q r))] > (if (zero? q) [r] > (into [r] (digits q))))) > > Not efficient though.
If you really want efficient: (defn digits [n] (loop [n (int n) out nil] (if (zero? n) out (recur (unchecked-divide n 10) (cons (unchecked-remainder n 10) out))))) If you really /really/ want efficient: (defn digits [n dig-max] (let [a (int-array dig-max)] (loop [n (int n) i (int (dec dig-max))] (when-not (zero? n) (aset a i (unchecked-remainder n 10)) (recur (unchecked-divide n 10) (unchecked-dec i)))) (seq a))) Icky but should be fastest possible in Clojure. This one will throw an exception if dig-max is too small and produce leading zeros if it's bigger than the number of digits of n, and it will truncate inputs that don't fit in a 32-bit signed int. You can wrap in (drop-while zero? ...) to lose the latter behavior but it will slow things down, or use Math/log10 and slow things down even more. All of the variations I've posted will turn negative numbers into seqs of digits that are all negated, e.g. (-1 0 -2 -4 -5 -6) and are liable to hang, blow the heap (pretty slowly), or blow the stack (variously) on fractions of any kind (Ratios, doubles, etc.). In practice, if I needed something like this in production code, I'd probably use one of the nicely idiomatic versions from earlier -- after all, the complexity is logarithmic in the magnitudes of the numbers you're using anyway -- and handle negative and fractional inputs in some more elegant manner. I'd probably also generalize it to accept an arbitrary radix as an optional second parameter. This would simply replace all the literal 10s in the code. It too would need to be sanity checked, for being an integer and >= 2. -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en