Skip to content

Instantly share code, notes, and snippets.

@mudge
Last active July 15, 2016 12:41
Show Gist options
  • Save mudge/ff8da1b92d00a82f3d5ec04e3ad3a7d9 to your computer and use it in GitHub Desktop.
Save mudge/ff8da1b92d00a82f3d5ec04e3ad3a7d9 to your computer and use it in GitHub Desktop.
Markov chain generator in JavaScript (with a Ruby "compiler")
<!doctype html>
<meta charset="utf-8">
<input id="input" type="text"> <a href="#" id="scifi">Sci-Fi it!</a>
<p id="output"></p>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script>
function sampleWithFrequency(coll) {
var choice = Math.random(),
length = coll.length;
for (var i = 0; i < length; i += 1) {
var word = coll[i][0],
frequency = coll[i][1];
if (frequency > choice) {
return word;
}
}
}
function titleize(sentence) {
var words = sentence.split(/\s+/),
output = [],
word;
for (var i = 0, length = words.length; i < length; i += 1) {
word = words[i];
output.push(word.charAt(0).toUpperCase() + word.slice(1));
}
return output.join(' ');
}
function markov(seed, numberOfWords, dict) {
var wordCount = 0,
word = seed,
words = [word],
nextWord;
while (wordCount < numberOfWords) {
if (!dict.words.hasOwnProperty(word)) {
break;
}
nextWord = sampleWithFrequency(dict.words[word]);
words.push(nextWord);
word = nextWord;
wordCount += 1;
}
return words.join(' ');
}
$.getJSON('/wells.json', function (dict) {
$('#output').text(markov(sampleWithFrequency(dict.startWords), 10, dict));
$('#scifi').on('click', function (e) {
e.preventDefault();
var words = $('#input').val().split(/\s+/),
length = words.length,
sentence = [];
for (var i = 0; i < words.length; i += 1) {
var word = words[i],
numberOfWords = Math.floor(Math.random() * 3) + 1;
sentence.push(markov(word, numberOfWords, dict));
}
$('#output').text(titleize(sentence.join(' ')));
});
});
</script>
require 'json'
words = Hash.new { |h, k| h[k] = Hash.new(0) }
start_words = Hash.new(0)
end_words = Hash.new(0)
ARGF.read.split(/\s+/).each_cons(2) do |(word, next_word)|
words[word][next_word] += 1
if word =~ /[.?!]\z/
start_words[next_word] += 1
end_words[word] += 1
end
end
words.each do |word, next_words|
total = next_words.values.inject(:+).to_f
cumulative_frequency = 0
next_words.each do |next_word, count|
cumulative_frequency += count / total
next_words[next_word] = cumulative_frequency
end
words[word] = next_words.to_a
end
total = start_words.values.inject(:+).to_f
cumulative_frequency = 0
start_words.each do |word, count|
cumulative_frequency += count / total
start_words[word] = cumulative_frequency
end
total = end_words.values.inject(:+).to_f
cumulative_frequency = 0
end_words.each do |word, count|
cumulative_frequency += count / total
end_words[word] = cumulative_frequency
end
puts JSON.dump(
words: words,
startWords: start_words.to_a,
endWords: end_words.to_a
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment