-
-
Save semperos/4e51aa26470c3120dfd5 to your computer and use it in GitHub Desktop.
Readability
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defn digits | |
"Generate a list of digits contained in the number" | |
[number] | |
(loop [found-digits '() base (quot number 10) digit (rem number 10)] | |
(let [found-digits (conj found-digits (if (neg? digit) (- digit) digit))] | |
(if (zero? base) | |
found-digits | |
(recur found-digits (quot base 10) (rem base 10)))))) | |
(defn divisible-digits | |
"Return the count of digits that evenly divide into the given number" | |
[number] | |
(let [divisible (filter (fn [n] (and (not (zero? n)) (= 0 (rem number n)))) (digits number))] | |
(count divisible))) | |
(map divisable-digits '(1024 2048 64)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def digits(base) | |
[].tap { |digits| | |
begin | |
base, digit = base.divmod(10) | |
digits << digit | |
end while base != 0 | |
} | |
end | |
def divisible_digits(number) | |
digits(number).count { |d| !d.zero? && (number % d == 0) } | |
end | |
[1024, 2048, 64].map { |n| divisible_digits(n) } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; See http://clojure.org/transducers for more information | |
(def digits | |
"A transducer that calls `Character/getNumericValue` on each item." | |
(map #(Character/getNumericValue %))) | |
(def not-zero? | |
"A transducer that drops items equal to zero." | |
(remove zero?)) | |
;; NOTE the `defn` here as opposed to `def` above. | |
(defn divisible? | |
"A function which returns a transducer that filters by items evenly divisible by the given `number`." | |
[number] | |
(filter #(zero? (rem number %)))) | |
;; USAGE | |
;; Transducers work with sequential things, which numbers are not: | |
(sequence digits 5430) | |
;=> EXCEPTION: IllegalArgumentException Don't know how to create ISeq from: java.lang.Long clojure.lang.RT.seqFrom (RT.java:528) | |
;; But make that number a string and you have something you can work with: | |
(sequence digits (str 5430)) | |
;=> (5 4 3 0) | |
;; Now lets combine our transducer for more interesting effects: | |
(sequence (comp digits not-zero?) (str 5430)) | |
;=> (5 4 3) | |
;; If you're used to using `comp`, you'll notice that worked _in reverse_. | |
;; For transducers, `comp` reads from left-to-right instead of right-to-left. | |
;; How does our `divisible?` function work? | |
(sequence (divisible? 12) [3 4 5 6]) | |
;=> (3 4 6) | |
;; Ok, it'll require one extra set of parentheses because instead of _being_ a transducer, | |
;; our `divisible?` function _returns_ a transducer that's custom-built for the `number` we input. | |
;; We can use `(divisible? number)` just like `digits` and `not-zero?`: | |
(sequence (comp digits not-zero? (divisible? 5430)) (str 5430)) | |
;=> (5 3) | |
;; Now we can just call `count` on that result and we're done: | |
(count (sequence (comp digits not-zero? (divisible? 5430)) (str 5430))) | |
;=> 2 | |
;; With all that, the `divisible-digits` function could be written like this: | |
(defn divisible-digits | |
[number] | |
(->> (str number) | |
(sequence (comp digits not-zero? (divisible? number))) | |
count)) | |
;; You could also opt to make `divisible-digits` just like `divisible?`, that is a | |
;; function that just returns another transducer. That would allow you to keep composing | |
;; these transducers if you found you needed to add further constraints. | |
;; Read the Clojure documentation at http://clojure.org/transducers | |
;; to understand the benefits of using transducers in general. For this case, | |
;; I think the code is equally readable either way. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment