Skip to content

Instantly share code, notes, and snippets.

@ocanbascil
Created August 25, 2015 20:38
Show Gist options
  • Save ocanbascil/0afffbcab6ec43a4f7b1 to your computer and use it in GitHub Desktop.
Save ocanbascil/0afffbcab6ec43a4f7b1 to your computer and use it in GitHub Desktop.
Clojure Dojo London, August 25 2015, Simple Markov Chain
(require '[clojure.string :as str])
(def test-tweets [
"Saturday night is all right for sonnets."
"530 years ago today, Richard III tried to trade his kingdom for a horse. Turned out stock in his kingdom had dropped below mule.'"
"I never stay in London during August. Tis plague season."
"Nay, Falstaff doth not overeat. That is not where the calories come from."
"If you ask Polonius a question, you deserve the answer you get."
"Tragedy, for me, is when the best actress in a generation has his voice change."
"Fancy costumes, not much plot, cheesy moral tacked on at the end: superhero movies are just court masques."
"I stole some of these tweets from Plautus. No one notices if they're in English."
"I want to find the lost Roanoke colonists, too. One of them still owes me five quid."
"I see that you've gotten rid of the kings in your politics but kept the clowns. One out of two, I suppose."
"I wanted to give Beatrice her own series, 'Sex and the City-State."
])
(defn clean-word
[word]
(str/replace (str/lower-case word) #"[^0-9a-z.?!]" ""))
(defn tup-pred [acc [word follow]]
"creates or append to a list of words"
(let [v (get acc word [])]
(assoc acc word (conj v follow))))
(defn word-follows [sentence]
"Build a hash-map for a sentence, with keys as unique words and values being a list of words that follow the key"
(->> sentence
(#(str/split % #" "))
(map clean-word)
(partition 2 1)
(reduce tup-pred {})))
(defn create-model [tweets]
"Build mapping for each sentence and merge them"
(apply merge-with concat (map word-follows tweets)))
(defn markov-step [model word]
"Randomly gets a word that follows the given word. If no word is found just returns a random word."
(let [words (get model word (get model (rand-nth (keys model))))]
(rand-nth words)))
(defn create-tweet
([model] (create-tweet [] model (+ 15 (rand-int 10))))
([acc model max-words]
(let [word (markov-step model (last acc))
acc (conj acc word)]
(if (or
(zero? max-words)
(re-matches #".*[\!\?\.]" word))
(str/join " " acc)
(recur acc model (dec max-words))))))
; Uncomment to run
;(def test-model (create-model test-tweets))
;(create-tweet test-model)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment