Problem statement
Phone Number
Write a program that cleans up user-entered phone numbers so that they can be sent SMS messages.
The rules are as follows:
- If the phone number is less than 10 digits assume that it is bad number
- If the phone number is 10 digits assume that it is good
- If the phone number is 11 digits and the first number is 1, trim the 1 and use the last 10 digits
- If the phone number is 11 digits and the first number is not 1, then it is a bad number
- If the phone number is more than 11 digits assume that it is a bad number
Proposed Solution
(ns phone-number
(:require [clojure.string :as str]))
(def non-digits #"\D")
(def parts #"^1?(...)(...)(....)$")
(def error-val ["000" "000" "0000"])
(defn- digits [n] (str/replace n non-digits ""))
(defn- trio-h [n]
(if-let [ps (re-find parts n)]
(rest ps)
error-val))
(defn- trio [n] (-> n digits trio-h))
(defn number [n] (-> n trio str/join))
(defn area-code [n] (-> n trio first))
(defn pretty-print [n]
(let [[area exch line] (trio n)]
(format "(%s) %s-%s" area exch line)))
Questions
- In
pretty-print
is the use oflet
necessary? Or is there a way in Clojure to splice in the result of(trio n)
in-place for the call toformat
? The result of(trio n)
is a vector containing three strings and theformat
call is expecting three%s
strings to stick into the format string. If there is an alternative to my use oflet
, which is preferred? - Are the names ok? Do they read like Clojure names? Is there a convention for naming a one-off helper function?
- Is it better to keep
trio-h
a separate helper function, orlet
it inside the using function, or would you just use the code in-place instead? :refer
ingclojure.string/replace
triggers a warning (since it collides withclojure.core/replace
) so I:refer
ed all ofclojure.string
. Is there a way to:refer
as
to avoid the collision?- Do you have other improvements you could suggest?
Tests
See the Exercism page for the Phone Number problem in Clojure
1 Answer 1
I'm still learning clojure, but I'll contribute what I can.
I don't know if it is prefered or not, but if you wanted to get rid of the
let
, you could do something like(apply (partial format "(%s) %s-%s") trio)
or(apply format (concat '["(%s) %s-%s"] trio))
instead.Naming seems ok.
- No comment.
- I don't know.
- Your regex for
parts
is suboptimal.'.'
will pick up any character, but you really only want digits. Something like"^1?(\d{3})(\d{3})(\d{4})$"
would be more accurate.
-
\$\begingroup\$ For 1, even simpler would be
(apply format "(%s) %s-%s" (trio n))
, but it might be better to just use alet
for clarity's sake. \$\endgroup\$Sam Estep– Sam Estep2016年06月05日 14:37:04 +00:00Commented Jun 5, 2016 at 14:37
Explore related questions
See similar questions with these tags.