in Books, Doing Books, Theory of Computation

Theory of Computation #12

Let’s take the rules from the beginning.

A -> eAee
A -> fBf
B -> g

The result should be:

A -> FI
I -> BF

A -> EJ
J -> AK
K -> EE

B -> g

E -> e
F -> f

Here’s the final code which stitches together all our functions:

(defn shorten-loop
  "Applies shorten-rule on a collection of rules"
  (loop [rest-fix coll
         index (int \I)
         result nil]
    (if (seq rest-fix)
       (rest rest-fix)
       (+ index (dec (count (shorten-rule (first rest-fix) (char index)))))
       (into result (shorten-rule (first rest-fix) (char index))))

(defn to-CNF
  "Takes a vector of rules in context free regular form and returns them
   as a hashmap in Chomsky normal form (CNF)."
  (let [filter-fn #(check-CNF (first (vals %)))
        filter-good (partial filter filter-fn)
        filter-bad (partial remove filter-fn)
        decomposed-input (map decompose-rule input)
        mixed-terminals (set (mapcat transform-terminals
                                     (filter-bad decomposed-input)))]
    (set (reduce into 
                 [(filter-good decomposed-input)
                 (filter-good mixed-terminals)
                 (shorten-loop (filter-bad  mixed-terminals))]))))

  (def input ["A -> eAee"
              "A -> fBf"
              "B -> g"])
  (is (= (to-CNF input)
         #{{:J "AK"} {:I "BF"} {:E "e"} {:K "EE"} {:A "EJ"} {:F "f"} {:A "FI"} {:B "g"}}#{{:J "AK"} {:I "BF"} {:E "e"} {:K "EE"} {:A "EJ"} {:F "f"} {:A "FI"} {:B "g"}})))

And the result is:

{:A "FI"}
{:I "BF"}

{:A "EJ"}
{:J "AK"}
{:K "EE"}

{:B "g"}

{:E "e"}
{:F "f"}

Yay. This took a while.

Write a Comment


This site uses Akismet to reduce spam. Learn how your comment data is processed.