Skip to content

Instantly share code, notes, and snippets.

@Alwinfy
Last active September 29, 2020 20:37
Show Gist options
  • Save Alwinfy/349012523df9f631a886701113fdc13a to your computer and use it in GitHub Desktop.
Save Alwinfy/349012523df9f631a886701113fdc13a to your computer and use it in GitHub Desktop.
reject modernity embrace FP
(set! *warn-on-reflection* true)
(ns net.alwinfy.isbn
(:require [clojure.string :as str]))
(def checksum-for
{9 (fn [isbn]
(-> (fn [i c]
(-> i
inc
(* c)))
(map-indexed isbn)
((partial reduce +))
(mod 11)))
12 (fn [isbn]
(-> (fn [i c]
(-> i
(bit-and 1)
(* -2)
dec
(* c)))
(map-indexed isbn)
((partial reduce +))
(mod 10)))})
(defn checksum [isbn]
(when-let [cs (checksum-for (count isbn))]
(cs (map #(- (int %) 48) isbn))))
(defn char-for [isbn]
(when-let [cs (checksum isbn)]
(if (= cs 10)
\X
(char (+ 48 cs)))))
(defn wellformed? [isbn]
(and
(checksum-for (count isbn))
(re-matches #"\d+" isbn)))
(defn valid-isbn? [isbn check]
(= (char-for isbn) check))
(defn fixup [isbn]
(if (re-matches #"(\d{3}-)?\d+(-\d+){2}(-[\dX])?" isbn)
(str/replace isbn "-" "")
isbn))
(defn colorize
([string] (colorize string 9))
([string color]
(if (System/console)
(format "\u001b[1;%dm%s\u001b[22;39m" (+ color 30) string)
string)))
(defn process [line]
(when-not (str/blank? line) (let [isbn (fixup line)]
(if (wellformed? isbn)
(str/join " " (list
(colorize "The checksum for")
(colorize line 4)
(colorize "is")
(colorize (char-for isbn) 5)))
(str/join " " (list
(colorize line 4)
(colorize "is")
(if (valid-isbn? (subs isbn 0 (dec (count isbn))) (last isbn))
(colorize "VALID" 2)
(colorize "INVALID" 1))))))))
(defn seq-for [^String file]
(line-seq (java.io.BufferedReader.
(if (= "-" file)
*in*
(java.io.FileReader. file)))))
(defn -main []
(doseq [file (or *command-line-args* '("-"))]
(doseq [line (map (comp process str/upper-case str/trim)
(seq-for file))]
(when line (println line)))))
; vim: ts=2 et
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment