Skip to content

Instantly share code, notes, and snippets.

@chillitom
Created May 1, 2015 22:14
Show Gist options
  • Save chillitom/19afc0a7383374b31c4f to your computer and use it in GitHub Desktop.
Save chillitom/19afc0a7383374b31c4f to your computer and use it in GitHub Desktop.
F# Markov chain first attempt
open System
open System.IO
open System.Text.RegularExpressions
let inputText = File.ReadAllText(__SOURCE_DIRECTORY__ + "/frankenstein.txt")
type Prefix = string list
type Suffix = string
type Chain = Map<Prefix, Suffix list>
let shift words word = if List.length words = 2 then List.tail words @ [word] else words @ [word]
let toWords s =
Regex.Split(inputText, @"\b")
|> Seq.filter (fun w -> String.IsNullOrWhiteSpace(w) = false)
|> Seq.toList
let rec addWords chain prefix (words: string list) : Chain =
match words with
| [] -> chain
| _ ->
let word = List.head words
let suffixes = defaultArg (Map.tryFind prefix chain) []
let nextSuffix = word :: suffixes
let nextChain = Map.add prefix nextSuffix chain
let nextPrefix = shift prefix word
addWords nextChain nextPrefix (List.tail words)
let buildChain words = addWords Map.empty [] words
let rand = new Random()
let rec pickWords chain prefix n words =
if n = 0
then words
else
match Map.tryFind prefix chain with
| None -> []
| Some c ->
let choice = List.nth c (rand.Next(0, List.length c))
let words' = words @ [choice]
let prefix' = shift prefix choice
pickWords chain prefix' (n - 1) words'
let generate chain n = pickWords chain [] n []
[<EntryPoint>]
let main argv =
let input = toWords inputText
let chain = buildChain input
printf "%A" <| generate chain 100
0 // return an integer exit code
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment