Skip to content

Instantly share code, notes, and snippets.

@jarsen
Created March 28, 2019 15:25
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 jarsen/25510929a470c1aedda1fe87b7d8fa94 to your computer and use it in GitHub Desktop.
Save jarsen/25510929a470c1aedda1fe87b7d8fa94 to your computer and use it in GitHub Desktop.
defmodule MarkovChain do
def create_chain(source, ngram_length) do
source
|> Stream.chunk_every(ngram_length + 1, 1)
|> Stream.map(fn chunk -> Enum.split(chunk, ngram_length) end)
|> Stream.scan(%{}, fn {ngram, word}, acc ->
Map.update(acc, ngram, word, fn val -> val ++ word end)
end)
end
def next_element(chain, preceding) do
chain
|> Map.get(preceding, [])
|> Enum.random()
end
end
defmodule MarkovChainTest do
use ExUnit.Case
doctest MarkovChain
describe "create_chain" do
test "returns correct map for names" do
words = "Tom Bombadil" |> String.graphemes()
assert %{
["a"] => ["d"],
[" "] => ["B"],
["B"] => ["o"],
["T"] => ["o"],
["b"] => ["a"],
["d"] => ["i"],
["i"] => ["l"],
["l"] => [],
["m"] => [" ", "b"],
["o"] => ["m", "m"]
} == MarkovChain.create_chain(words, 1) |> Enum.to_list() |> List.last()
end
test "returns correct map for words" do
words = "a long time ago in a galaxy far far away" |> String.split()
assert %{
["a"] => ["long", "galaxy"],
["long"] => ["time"],
["time"] => ["ago"],
["ago"] => ["in"],
["in"] => ["a"],
["galaxy"] => ["far"],
["far"] => ["far", "away"],
["away"] => []
} == MarkovChain.create_chain(words, 1) |> Enum.to_list() |> List.last()
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment