Skip to content

Implemented all "Phone Number" problems from the canonical test data. (#465) #472

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Apr 27, 2025
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 8 additions & 13 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -287,19 +287,6 @@
"number_theory"
]
},
{
"slug": "phone-number",
"name": "Phone Number",
"uuid": "c211045e-da97-479d-9df4-5d812573e2d0",
"practices": [],
"prerequisites": [],
"difficulty": 2,
"topics": [
"interfaces",
"parsing",
"strings"
]
},
{
"slug": "queen-attack",
"name": "Queen Attack",
Expand Down Expand Up @@ -942,6 +929,14 @@
"practices": [],
"prerequisites": [],
"difficulty": 2
},
{
"slug": "phone-number",
"name": "Phone Number",
"uuid": "e123577a-aaf8-4552-98f1-2ef94a7195f7",
"practices": [],
"prerequisites": [],
"difficulty": 1
}
]
},
Expand Down
83 changes: 66 additions & 17 deletions exercises/practice/phone-number/.meta/example.el
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,81 @@

;;; Commentary:

;;; Code:
(defun char-digit-p (x)
(<= ?0 x ?9))

(defun char-lowercase-p (x)
(<= ?a x ?z))

(defun numbers (num)
(let ((number (replace-regexp-in-string "[^0-9]+" "" num)))
(cond
((= (length number) 10) number)
((and (= (length number) 11)
(string-equal (substring number 0 1) "1")) (substring number 1))
(t "0000000000"))))


(defun area-code (num)
(substring (numbers num) 0 3))
(defun char-uppercase-p (x)
(<= ?A x ?Z))

(defun char-alphabetic-p (x)
(or (char-lowercase-p x)
(char-uppercase-p x)))

(defun prefix (num)
(substring (numbers num) 3 6))
(defun char-punctuation-p (x)
(or (<= 33 x 39)
(= x 42)
(= x 44)
(= x 47)
(<= 58 x 64)
(<= 91 x 96)
(<= 123 x 126)))

(defun negate (pred)
(lambda (&rest args) (apply pred args)))

(defun line-number (num)
(substring (numbers num) 6))
(defun string-remove (s pred)
(let* ((n (length s))
(to-str (make-string n ?\0))
(k 0))
(dotimes (i n)
(let ((x (aref s i)))
(when (funcall pred x)
(setf (aref to-str k) x)
(cl-incf k))))
(substring to-str 0 k)))

(defun numbers (num)
"Converts a num string into a string of digits."
(cond
((cl-find-if #'char-alphabetic-p num)
(error "letters not permitted"))
((cl-find-if #'char-punctuation-p num)
(error "punctuations not permitted")))
(let* ((digits (string-remove num (negate #'char-digit-p)))
(n (length digits)))
(cond
((< n 10) (error "must not be fewer than 10 digits"))
((> n 11) (error "must not be greater than 11 digits")))
(if (= n 11)
(if (= (aref digits 0) ?1)
(setf digits (substring digits 1))
(error "11 digits must start with 1")))
(let ((y (aref digits 0)))
(cond
((= y ?0)
(error "area code cannot start with zero"))
((= y ?1)
(error "area code cannot start with one"))))
(let ((y (aref digits 3)))
(cond
((= y ?0)
(error "exchange code cannot start with zero"))
((= y ?1)
(error "exchange code cannot start with one"))))
digits))

(defun area-code (num)
(let ((digits (numbers num)))
(substring digits 0 3)))

(defun pprint (num)
(format "(%s) %s-%s" (area-code num) (prefix num) (line-number num)))
(let ((digits (numbers num)))
(format "(%s) %s-%s" (substring digits 0 3)
(substring digits 3 6)
(substring digits 6 10))))


(provide 'phone-number)
Expand Down
1 change: 1 addition & 0 deletions exercises/practice/phone-number/.meta/tests.toml
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,4 @@ description = "invalid if exchange code starts with 0 on valid 11-digit number"

[57b32f3d-696a-455c-8bf1-137b6d171cdf]
description = "invalid if exchange code starts with 1 on valid 11-digit number"

75 changes: 56 additions & 19 deletions exercises/practice/phone-number/phone-number-test.el
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
;;; phone-number-test.el --- Tests for phone-number (exercism) -*- lexical-binding: t; -*-
;;; phone-number-test.el --- Phone Number (exercism) -*- lexical-binding: t; -*-

;;; Commentary:

Expand All @@ -9,35 +9,72 @@
(declare-function area-code "phone-number.el" (num))
(declare-function pprint "phone-number.el" (num))

(ert-deftest cleans-number-test ()
(should (equal (numbers "(223) 456-7890") "2234567890")))
(ert-deftest cleans-the-number ()
(should (string= (numbers "(223) 456-7890") "2234567890")))

(ert-deftest cleans-numbers-with-dots ()
(should (string= (numbers "223.456.7890") "2234567890")))

(ert-deftest cleans-numbers-with-dots-test ()
(should (equal (numbers "223.456.7890") "2234567890")))
(ert-deftest cleans-numbers-with-multiple-spaces ()
(should (string= (numbers "223 456 7890 ") "2234567890")))

(ert-deftest invalid-when-9-digits ()
(should (string= (cadr (should-error (numbers "123456789")))
"must not be fewer than 10 digits")))

(ert-deftest valid-when-11-digits-and-first-is-1-test ()
(should (equal (numbers "12234567890") "2234567890")))
(ert-deftest invalid-when-11-digits-does-not-start-with-a-1 ()
(should (string= (cadr (should-error (numbers "22234567890")))
"11 digits must start with 1")))

(ert-deftest valid-when-11-digits-and-starting-with-1 ()
(should (string= (numbers "12234567890") "2234567890")))

(ert-deftest invalid-when-11-digits-test ()
(should (equal (numbers "21234567890") "0000000000")))
(ert-deftest valid-when-11-digits-and-starting-with-1-even-with-punctuation ()
(should (string= (numbers "+1 (223) 456-7890") "2234567890")))

(ert-deftest invalid-when-more-than-11-digits ()
(should (string= (cadr (should-error (numbers "321234567890")))
"must not be greater than 11 digits")))

(ert-deftest invalid-when-9-digits-test ()
(should (equal (numbers "123456789") "0000000000")))
(ert-deftest invalid-with-letters ()
(should (string= (cadr (should-error (numbers "523-abc-7890")))
"letters not permitted")))

(ert-deftest invalid-when-more-than-11-digits-test ()
(should (equal (numbers "321234567890") "0000000000")))
(ert-deftest invalid-with-punctuations ()
(should (string= (cadr (should-error (numbers "523-@:!-7890")))
"punctuations not permitted")))

(ert-deftest invalid-with-letters ()
(should (equal (numbers "523-abc-7890") "0000000000")))
(ert-deftest invalid-if-area-code-starts-with-0 ()
(should (string= (cadr (should-error (numbers "(023) 456-7890")))
"area code cannot start with zero")))

(ert-deftest invalid-if-area-code-starts-with-1 ()
(should (string= (cadr (should-error (numbers "(123) 456-7890")))
"area code cannot start with one")))

(ert-deftest invalid-with-punctuations ()
(should (equal (numbers "523-@:!-7890") "0000000000")))
(ert-deftest invalid-if-exchange-code-starts-with-0 ()
(should (string= (cadr (should-error (numbers "(223) 056-7890")))
"exchange code cannot start with zero")))

(ert-deftest invalid-if-exchange-code-starts-with-1 ()
(should (string= (cadr (should-error (numbers "(223) 156-7890")))
"exchange code cannot start with one")))

(ert-deftest invalid-if-area-code-starts-with-0-on-valid-11-digit-number ()
(should (string= (cadr (should-error (numbers "1 (023) 456-7890")))
"area code cannot start with zero")))

(ert-deftest invalid-if-area-code-starts-with-1-on-valid-11-digit-number ()
(should (string= (cadr (should-error (numbers "1 (123) 456-7890")))
"area code cannot start with one")))

(ert-deftest invalid-if-exchange-code-starts-with-0-on-valid-11-digit-number ()
(should (string= (cadr (should-error (numbers "1 (223) 056-7890")))
"exchange code cannot start with zero")))

(ert-deftest invalid-if-exchange-code-starts-with-1-on-valid-11-digit-number ()
(should (string= (cadr (should-error (numbers "1 (223) 156-7890")))
"exchange code cannot start with one")))

(ert-deftest area-code-test ()
(should (equal (area-code "2234567890") "223")))
Expand All @@ -50,6 +87,6 @@
(ert-deftest pprint-full-us-phone-number-test ()
(should (equal (pprint "12234567890") "(223) 456-7890")))


(provide 'phone-number)
(provide 'phone-number-test)
;;; phone-number-test.el ends here

2 changes: 1 addition & 1 deletion exercises/practice/phone-number/phone-number.el
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
;;; phone-number.el --- phone-number Exercise (exercism) -*- lexical-binding: t; -*-
;;; phone-number.el --- phone-number (exercism) -*- lexical-binding: t; -*-

;;; Commentary:

Expand Down