Created
May 1, 2015 22:14
-
-
Save chillitom/19afc0a7383374b31c4f to your computer and use it in GitHub Desktop.
F# Markov chain first attempt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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