I’ll regularly take a JavaScript problem and work it out in ClojureScript. This will hopefully take away some of the Magic™ of functional programming and show how to solve real problems. I promise you won’t have to learn what a monad is.

Problem

Write a function, persistence, that takes in a positive parameter num and returns its multiplicative persistence, which is the number of times you must multiply the digits in num until you reach a single digit.

For example:

persistence(39) === 3 // 3*9 = 27, 2*7 = 14, 1*4=4
                      // and 4 has only one digit

persistence(999) === 4 // 9*9*9 = 729, 7*2*9 = 126,
                       // 1*2*6 = 12, 1*2 = 2

persistence(4) === 0 // 4 is already a one-digit number

Solutions

;;#cljs
(defn persistence-recursive [n]
  (let [n (str n)]
    (if (= 1 (count n))
      0
      (inc (persistence
             (reduce (fn [a1 a2]
                       (* (js/parseInt a1)
                          (js/parseInt a2)))
                     n)))))

(defn persistence-iterative [n]
  (loop [acc 0
         n (str n)]
    (if (= 1 (count n))
      acc
      (recur (inc acc)
             (str
               (reduce (fn [a1 a2]
                         (* (js/parseInt a1)
                            (js/parseInt a2)))
                       n))))))

Thoughts

persistence-recursive is a linear recursive process while persistence-iterative is a linear iterative process. SICP has a great visual explanation of each.

  • persistence-recursive: Grows the stack and potential stack overflow, but doesn’t need to maintain state.
  • persistence-iterative: Doesn’t grow the stack and no stack overflow, but needs to update state. Additionally, cljs isn’t tail call optimized (TCO), so we need to use loop/recur.

Get access to new content

New posts are at bostonou.com. Go check it out, or you can just subscribe from here.

    Reminder: You're subscribing to bostonou.com