Skip to content

Instantly share code, notes, and snippets.

@tzach
Created September 11, 2012 11:29
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 tzach/3697720 to your computer and use it in GitHub Desktop.
Save tzach/3697720 to your computer and use it in GitHub Desktop.
Solution to KataBankOCR in Clojure
;; Almost a full solution to KataBankOCR
;; taken from http://codingdojo.org/cgi-bin/wiki.pl?KataBankOCR
(ns dojo.core
(:require
[clojure.string :as str]
[clojure.set :as set]))
;; User Story 1
(def *dic*
{
'(\space \_ \space \| \space \| \| \_ \|) 0
'(\space \space \space \space \space \| \space \space \|) 1
'(\space \_ \space \space \_ \| \| \_ \space) 2
'(\space \_ \space \space \_ \| \space \_ \|) 3
'(\space \space \space \| \_ \| \space \space \|) 4
'(\space \_ \space \| \_ \space \space \_ \|) 5
'(\space \_ \space \| \_ \space \| \_ \|) 6
'(\space \_ \space \space \space \| \space \space \|) 7
'(\space \_ \space \| \_ \| \| \_ \|) 8
'(\space \_ \space \| \_ \| \space \_ \|) 9
})
(def *rev-dic* (set/map-invert *dic*))
(defn break-to-9 [c]
(map #(partition 3 %) c))
(defn conv [e]
(if (empty? (flatten e))
nil
(concat
(map first e)
(conv
(map rest e)))))
(defn break-to-pics [s]
(->> s
break-to-9
conv
(partition 3)
(map flatten)))
(defn proc-str [s]
(map #(get *dic* %) (break-to-pics s)))
(defn parse-file [f]
(->> f
slurp
str/split-lines
(partition 3)
(map proc-str)))
;; User Story 2
(defn checksum [col]
(mod
(->>
col
reverse
(map * (range 1 (inc (count col))))
(apply +))
11))
(defn checksum? [col]
(if (some nil? col)
false
(zero? (checksum col))))
;; User Story 3
(defn check-number [c]
(cond
(some nil? c) "ILL"
(not (checksum? c)) "ERR"
:else nil))
(defn print-account-line [c]
(let [suf (check-number c)]
(->>
c
(map (fnil str "?"))
(reduce str)
( #(str % " " suf))
str/trim)))
(defn convert-file [f]
(let [new-name (str f ".new")]
(spit new-name "")
(doseq [l
(map
print-account-line
(parse-file f))]
(spit new-name (str l "\n") :append true))))
;; User Story 4 (missing the print part)
(defn distance [x y]
"return the distance, in number of leds, between two numbers"
(count (filter false? (map = x y))))
(defn scanning-error? [x y]
(= (distance x y) 1))
(defn alts-pic [pic]
"retrun alternative results for a scanning error"
(map *dic* (filter #(scanning-error? pic %) (keys *dic*))))
(defn alts-accounts-pos [c n alts]
"return all valid alternative of replacing digit at position n with alts"
(filter checksum?
(for [a alts]
(assoc (vec c) n a))))
(defn alts-accounts [s]
(filter (comp not empty?)
(let [pics (break-to-pics s)
c (map #(get *dic* %) pics)]
(for [i (range 9)]
(->> i
(nth pics)
alts-pic
(alts-accounts-pos c i)
flatten)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment