Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to split a number in Clojure?

Tags:

clojure

I am looking for a nice method to split a number with n digits in Clojure I have these two methods:

 (->> (str 942)
      seq
      (map str)
      (map read-string)) => (9 4 2)

and...

(defn digits [n]
   (cons 
      (str (mod n 10)) (lazy-seq (positive-numbers (quot n 10)))))

(map read-string (reverse (take 5 (digits 10012)))) => (1 0 0 1 2)

Is there a more concise method for doing this type of operation?

like image 511
insudo Avatar asked Apr 28 '15 20:04

insudo


3 Answers

A concise version of your first method is

(defn digits [n]
  (->> n str (map (comp read-string str))))

... and of your second is

(defn digits [n]
  (if (pos? n)
    (conj (digits (quot n 10)) (mod n 10) )
    []))

An idiomatic alternative

(defn digits [n]
  (->> n
       (iterate #(quot % 10))
       (take-while pos?)
       (mapv #(mod % 10))
       rseq))

For example,

(map digits [0 942 -3])
;(nil (9 4 2) nil)
  • The computation is essentially eager, since the last digit in is the first out. So we might as well use mapv and rseq (instead of map and reverse) to do it faster.
  • The function is transducer-ready.
  • It works properly only on positive numbers.
like image 82
Thumbnail Avatar answered Nov 08 '22 23:11

Thumbnail


You could simply do

(map #(Character/digit % 10) (str 942))

EDIT: Adding a function definition

(defn digits [number] (map #(Character/digit % 10) (str number)))

Usage:

(digits 1234)

Note: This is concise, but does use java String and Character classes. An efficient implementation can be written using integer modulo arithmetic, but won't be concise. One such solution similar to Charles' answer would be:

(defn numTodigits
  [num]
  (loop [n num res []]
    (if (zero? n)
      res
      (recur (quot n 10) (cons (mod n 10) res)))))

Source

like image 24
vsnyc Avatar answered Nov 09 '22 00:11

vsnyc


I'm not sure about concise, but this one avoids unnecessary inefficiency such as converting to strings and back to integers.

(defn digits [n]
  (loop [result (list), n n]
    (if (pos? n)
      (recur (conj result (rem n 10))
             (quot n 10))
      result)))
like image 6
Charles Duffy Avatar answered Nov 08 '22 22:11

Charles Duffy