Skip to content

Instantly share code, notes, and snippets.

@ericnormand
Last active December 12, 2020 23:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ericnormand/e7cedc7c528505af54072cb39ca77fb9 to your computer and use it in GitHub Desktop.
Save ericnormand/e7cedc7c528505af54072cb39ca77fb9 to your computer and use it in GitHub Desktop.

Factors to string

Any integer can be written as a product of prime numbers. This is called the number's prime factorization. For instance, 24's prime factorization is 24 = 2 x 2 x 2 x 3 or even better 24 = 2 ^ 3 x 3. For this exercise, we are given the prime factorization. We have to construct the string representation.

Examples:

(factors->string [2 2 2 3]) ;=> "24 = 2^3 x 3"
(factors->string [7]) ;=> "7 = 7"
(factors->string [2 2 7]) ;=> "28 = 2^2 x 7"

Just for clarity, here are the rules:

  • If the prime factor appears only once, just use the number by itself (i.e., "2")
  • If the prime factor appears more than once, use the exponent notation (i.e., "2^3")
  • If there is more than one prime factor, separate them with an "x" for multiplication (i.e., "3 x 7")
  • Start the string with "n =" where n is the number that has been factorized. You can calculate this by multiplying all the factors together.

Thanks to this site for the challenge idea where it is considered Hard level in Ruby.

Email submissions to eric@purelyfunctional.tv before August 29, 2020. You can discuss the submissions in the comments below.

(defn factors->string [factors]
(let [number (reduce * 1 factors)
groups (partition-by identity factors)
exprs (map (fn [[n :as group]]
(let [exp (count group)]
(if (= 1 exp)
n
(str n "^" exp))))
groups)]
(str number " = " (clojure.string/join " x " exprs))))
(defn factors->string
[coll]
(when (seq coll)
(str (reduce * coll) " = " (clojure.string/join " x "
(for [[k v] (frequencies coll)]
(if (> v 1) (str k "^" v) k))))))
(factors->string [2 2 2 3])
;; => "24 = 2^3 x 3"
(factors->string [7])
;; => "7 = 7"
(factors->string [2 2 7])
;; => "28 = 2^2 x 7"
(factors->string [])
;; => nil
(require '[net.cgrand.xforms :as x])
(defn- factor->str [[b :as coll]]
(let [e (count coll)]
(if (= e 1)
(str b)
(str b \^ e))))
(defn- lhs [factors]
(reduce * factors))
(defn- rhs [factors]
(let [xf (comp (partition-by identity)
(map factor->str)
(interpose " x "))]
(x/str xf factors)))
(defn factors->string [factors]
(if (empty? factors) ""
(str (lhs factors) " = " (rhs factors))))
(deftest factors->string-test
(are [out in] (= out in)
"" (factors->string [])
"" (factors->string [])
"7 = 7" (factors->string [7])
"28 = 2^2 x 7" (factors->string [2 2 7])
"24 = 2^3 x 3" (factors->string [2 2 2 3])))
(defn factors->strings
"Given a number's prime factors returns a string representation of the number and it's factorization such as:
[2 2 2 3] => \"24 = 2^3 * 3\"."
[prime-factors]
(let [n (apply * prime-factors)
factors-string (->> (frequencies prime-factors)
;; using sorted map to make sure we start with the lowest factor
(into (sorted-map))
(map (fn [[factor freq]]
(str factor (when (> freq 1) (str "^" freq)))))
(string/join " x "))]
(format "%d = %s" n factors-string)))
(defn factors->string
[factors]
(let [product (reduce * 1 factors)]
(->> factors
(partition-by identity)
(map
(fn [[factor :as repeats]]
(let [n (count repeats)]
(if (= n 1)
factor
(str factor "^" n)))))
(str/join " x ")
(str product " = "))))
(factors->string [2 2 2 3]) ;=> "24 = 2^3 x 3"
(factors->string [7]) ;=> "7 = 7"
(factors->string [2 2 7]) ;=> "28 = 2^2 x 7"
(defn factors->string [s]
(letfn [(rtp [c] (if (= (count c) 1) (str (first c))
(apply str ((juxt first (constantly "^") count) c))))]
(str (apply * s) " = " (str/join " X " (map rtp (partition-by identity s))))))
(ns pftv.factors-to-string
(:require [clojure.pprint :as pprint]))
(defn factors->string
[pfs]
(let [n (apply * pfs)
base-exponent-pairs (seq (frequencies pfs))]
(pprint/cl-format nil "~d = ~{~{~d~[~;~:;~:*^~d~]~}~^ x ~}" n base-exponent-pairs)))
(comment
;; Progressively developing with cl-format
(pprint/cl-format nil "~d = ~{~d~^ x ~}" 24 [2 2 2 3])
(map #(pprint/cl-format nil "~{~d~[~;~:;~:*^~d~]~}" [2 %]) (range 1 4)))
(comment
(= "24 = 2^3 x 3" (factors->string [2 2 2 3]))
(= "7 = 7" (factors->string [7]))
(= "28 = 2^2 x 7" (factors->string [2 2 7])))
(defn factors->string [factors]
(->> (frequencies factors)
(map (fn [[n exp]]
(if (= 1 exp) (str n) (str n "^" exp))))
(interpose " x ")
(cons (str (apply * factors) " = "))
(apply str)))
(defn factors->string [factors]
(let [freqs (into (sorted-map) (frequencies factors))
term (fn [[x power]] (apply str (if (= 1 power) [x] [x "^" power])))
terms (clojure.string/join " x " (map term freqs))]
(str (reduce * factors) " = " terms)))
(defn- count-elements [xs]
(reduce #(assoc % %2 (inc (get %1 %2 0))) {} xs))
(defn- format-prime [[prime count]]
(if (= count 1) (str prime) (str prime "^" count)))
(defn factors->string [primes]
(let [i (reduce * primes)
formatted (->> primes
count-elements
(map format-prime)
(interpose " x ")
(apply str))]
(str i " = " formatted)))
@KingCode
Copy link

KingCode commented Dec 12, 2020

(defn factors->string [factors]
  (transduce 
   (comp (partition-by identity)
         (map (fn [xs]
                [(apply * xs), (first xs), (count xs)]))),

   (completing (fn [[acc, fact-strs] [factor, base, exp]]
                 [(* acc factor), 
                  (conj fact-strs 
                        (str base (if (= 1 exp) 
                                    "" 
                                    (str "^" exp))))]) 
               (fn [[product fact-strs]]
                 (str product " = " (clojure.string/join " x " fact-strs)))),

   [1 []],
   factors))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment