Skip to content

Instantly share code, notes, and snippets.

@ericnormand
Last active February 26, 2021 14:49
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/23195520ccd38d391d6cbcd907c0ab81 to your computer and use it in GitHub Desktop.
Save ericnormand/23195520ccd38d391d6cbcd907c0ab81 to your computer and use it in GitHub Desktop.
412 PurelyFunctional.tv Newsletter

Valid names

This challenge looks like a fun experiment in building a simple rules-based validator.

Definitions:

  1. A name is a sequence of terms separated by a space. It must have at least 2 terms. The last term must be a word.
  2. A term is either an initial or a word.
  3. An initial is a single capital letter followed by a period.
  4. A word is a capital letter followed by one or more letters (upper or lower case).

Write a function that checks whether a string is a valid name.

Examples

Valid names:

  • George R. R. Martin
  • Abraham Lincoln
  • J. R. Bob Dobbs
  • H. G. Wells

Invalid names:

  • J R Tolkien (no periods)
  • J. F. K. (must end in word)
  • Franklin (must have at least two terms)

Thanks to this site for the challenge idea where it is considered Expert in JavaScript. The problem has been modified from the original.

Please submit your solutions as comments on this gist.

@sztamas
Copy link

sztamas commented Feb 14, 2021

@andyfry01 Yes, I thought spec can be used nicely for this kind of problem!

@pmonks
Copy link

pmonks commented Feb 23, 2021

@pieterbreed you're too kind; in the real world I would absolutely use a solution closer to yours than the one I posted. Regexes are awesome! 😉

@galuque
Copy link

galuque commented Feb 26, 2021

Spec really is shining in this one wow

(ns pftv.challenges.412
  (:require [clojure.spec.alpha :as spec]
            [clojure.string :as str]))

(spec/def ::initial (partial re-matches #"[A-Z]\."))

(spec/def ::word (partial re-matches #"[A-Z][A-Za-z]+"))

(spec/def ::term (spec/or :initial ::initial :word ::word))

(spec/def ::name (spec/cat
                  :terms (spec/+ ::term)
                  :ends-in-word ::word))

(defn valid-name? [name]
  (let [name-vec (str/split name #" ")]
    (spec/valid? ::name name-vec)))

(def valid-names ["George R. R. Martin"
                  "Abraham Lincoln"
                   "J. R. Bob Dobbs"
                  "H. G. Wells"])

(def invalid-names ["J R Tolkien"
                      "J. F. K."
                      "Franklin"])
(every? true?
        (map valid-name? valid-names))
;; => true

(every? false?
        (map valid-name? invalid-names))
;; => true

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