aboutsummaryrefslogtreecommitdiff
path: root/challenge-106/tyler-wardhaugh/clojure/src/tw/weekly/c106/t2.clj
blob: d48c6e3b0e850a5f131313f14261d51ffe8a6384 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
(ns tw.weekly.c106.t2
  (:require [clojure.edn :as edn]
            [clojure.math.numeric-tower :refer [abs]]))

;;;
; Task description for TASK #2 › Decimal String
;;;
(def DEFAULT-INPUT [1 3])

(defn- decimal-string-recurring
  "Covert the given n[umerator] and d[enominator] (which must be known to
  have a recurring fractional result) into a decimal string where the recurring
  fractional is put in parenthesis."
  [n d]
  (loop [remainder (abs (rem n d))
         cache {}
         result []]
    (if (not (or (zero? remainder) (cache remainder)))
      (recur (rem (* 10 remainder) d)
             (assoc cache remainder (count (apply str result)))
             (conj result (quot (* 10 remainder) d)))
      (let [[lead recurrence] (->> result (split-at (get cache remainder 0)))
            whole (quot n d)
            pieces (concat [whole \.] lead [\(] recurrence [\)])]
        (apply str pieces)))))

(defn decimal-string
  "Covert the given n[umerator] and d[enominator] into a decimal string where any
  recurring fractional is put in parenthesis."
  [n d]
  (try (str (/ (bigdec n) d))
       (catch ArithmeticException _
         ; BigDecimal throws this exception when the result cannot be
         ; represented with the 'UNLIMITED' precision (the default), i.e.,
         ; there is a recurring fractional result
         (decimal-string-recurring n d))))

(defn -main
  "Run Task 2 with a given N and D, defaulting to the example given in the task
  description."
  [& args]
  (let [[N D] (or (some->> args (take 2) (map edn/read-string)) DEFAULT-INPUT)]
    (println (decimal-string N D))))