├── .gitignore
├── Markov Chain Sentence Generator
├── App.config
├── App.xaml
├── App.xaml.cs
├── MainWindow.xaml
├── MainWindow.xaml.cs
├── Markov Chain Sentence Generator.csproj
├── Markov.cs
└── Trigram.cs
├── README.md
├── Resources
├── markov-example.png
├── markov1.PNG
├── markov2.PNG
└── markov3.PNG
└── text files
├── A Descent Into The Maelstorm.txt
├── Mesmeric Revelation.txt
├── The Facts in the Case of M Valdemar.txt
└── harrypotter4.txt
/.gitignore:
--------------------------------------------------------------------------------
1 | /.vs
2 | *sln
3 | Markov Chain Sentence Generator/bin
4 | Markov Chain Sentence Generator/obj
5 | Markov Chain Sentence Generator/Properties
--------------------------------------------------------------------------------
/Markov Chain Sentence Generator/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Markov Chain Sentence Generator/App.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Markov Chain Sentence Generator/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration;
4 | using System.Data;
5 | using System.Linq;
6 | using System.Threading.Tasks;
7 | using System.Windows;
8 |
9 | namespace Markov_Chain_Sentence_Generator
10 | {
11 | ///
12 | /// Interaction logic for App.xaml
13 | ///
14 | public partial class App : Application
15 | {
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Markov Chain Sentence Generator/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/Markov Chain Sentence Generator/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows;
7 | using System.Windows.Controls;
8 | using System.Windows.Data;
9 | using System.Windows.Documents;
10 | using System.Windows.Input;
11 | using System.Windows.Media;
12 | using System.Windows.Media.Imaging;
13 | using System.Windows.Navigation;
14 | using System.Windows.Shapes;
15 | using Microsoft.Win32;
16 | using System.IO;
17 |
18 | namespace Markov_Chain_Sentence_Generator
19 | {
20 | public partial class MainWindow : Window
21 | {
22 | Markov mk = null;
23 | string text = null;
24 | List number_of_words = new List() {10, 20, 30, 40, 50};
25 |
26 | public MainWindow()
27 | {
28 | InitializeComponent();
29 | numberWords_comboBox.ItemsSource = number_of_words;
30 | }
31 |
32 | private void SelectFile(object sender, RoutedEventArgs e)
33 | {
34 | mk = null; // ensure no old models are used with a new file
35 | OpenFileDialog openFileDailog = new OpenFileDialog();
36 | openFileDailog.FileName = ""; // Default file name
37 | openFileDailog.DefaultExt = ".txt"; // Default file extension
38 | openFileDailog.Filter = "Text documents (.txt)|*.txt"; // Filter files by extension
39 | Nullable result = openFileDailog.ShowDialog();
40 | if (result == true)
41 | {
42 | // Open document
43 | string filepath = openFileDailog.FileName;
44 | try
45 | {
46 | text = File.ReadAllText(filepath);
47 | filepath_textBox.Text = filepath;
48 | }
49 | catch (IOException ioEx)
50 | {
51 | MessageBox.Show("There was a problem reading the slected file. Error: " + ioEx.Message);
52 | text = null;
53 | filepath_textBox.Text = "";
54 | }
55 | }
56 | } // end SelectFile()
57 |
58 | private void TrainModel(object sender, RoutedEventArgs e)
59 | {
60 | if (text == null)
61 | {
62 | MessageBox.Show("There is no text available for training.");
63 | return;
64 | }
65 | mk = new Markov(text);
66 | try
67 | {
68 | mk.Train();
69 | MessageBox.Show("Successfully Trained Markov model. You can now generate sentences.");
70 | trainingStatus_label.Content = "Trained";
71 | }
72 | catch (Exception ex)
73 | {
74 | MessageBox.Show(ex.Message);
75 | trainingStatus_label.Content = "Not Trained";
76 | }
77 | } // end TrainModel()
78 |
79 | private void GenerateText(object sender, RoutedEventArgs e)
80 | {
81 | generatedText_textBlock.Text = "";
82 | if (mk == null)
83 | {
84 | MessageBox.Show("You must first select a text file and click train before generating text.");
85 | return;
86 | }
87 | if ((string)trainingStatus_label.Content != "Trained")
88 | {
89 | MessageBox.Show("There was a problem during loading and training the model. Please try again.");
90 | return;
91 | }
92 | try
93 | {
94 | generatedText_textBlock.Text = mk.GenerateText(length: (int)numberWords_comboBox.SelectedValue);
95 | }
96 | catch (Exception ex)
97 | {
98 | MessageBox.Show("Problem with generating text. Error: " + ex.Message);
99 | }
100 | } // end GenerateText()
101 | } // END MainWindow{}
102 | }
103 |
--------------------------------------------------------------------------------
/Markov Chain Sentence Generator/Markov Chain Sentence Generator.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {392157B1-A30A-4103-B155-1B78ED75E4FF}
8 | WinExe
9 | Properties
10 | Markov_Chain_Sentence_Generator
11 | Markov Chain Sentence Generator
12 | v4.6
13 | 512
14 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
15 | 4
16 | true
17 |
18 |
19 | AnyCPU
20 | true
21 | full
22 | false
23 | bin\Debug\
24 | DEBUG;TRACE
25 | prompt
26 | 4
27 |
28 |
29 | AnyCPU
30 | pdbonly
31 | true
32 | bin\Release\
33 | TRACE
34 | prompt
35 | 4
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | 4.0
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | MSBuild:Compile
56 | Designer
57 |
58 |
59 | MSBuild:Compile
60 | Designer
61 |
62 |
63 | App.xaml
64 | Code
65 |
66 |
67 | MainWindow.xaml
68 | Code
69 |
70 |
71 |
72 |
73 |
74 |
75 | Code
76 |
77 |
78 | True
79 | True
80 | Resources.resx
81 |
82 |
83 | True
84 | Settings.settings
85 | True
86 |
87 |
88 | ResXFileCodeGenerator
89 | Resources.Designer.cs
90 |
91 |
92 | SettingsSingleFileGenerator
93 | Settings.Designer.cs
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
108 |
--------------------------------------------------------------------------------
/Markov Chain Sentence Generator/Markov.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace Markov_Chain_Sentence_Generator
9 | {
10 | class Markov
11 | {
12 | private string text; // full text read in from file
13 | private Dictionary model; // {"Hello my": {prefix=["Hello", "my], suffix=List()},...}
14 | private bool trained;
15 |
16 | static Random random = new Random();
17 |
18 | public Markov(string text)
19 | {
20 | this.text = text;
21 | model = new Dictionary();
22 | this.trained = false;
23 | }
24 |
25 | public void Train()
26 | {
27 | this.trained = false;
28 | text = CleanText(text);
29 | string[] sentences = text.Split('.');
30 | if (sentences.Length < 2) // too few fullstops
31 | {
32 | throw new FormatException("The text provided has no periods('.'). Please use a text with sentences seperated with periods.");
33 | }
34 | for (int i = 0; i != sentences.Length; i++)
35 | {
36 | string[] words = sentences[i].Split(' ');
37 | if (words.Length < 3) { break; } // not enough words in sentence, skip sentence
38 | for (int j = 0; j != words.Length - 2; j++)
39 | {
40 | string index = words[j] + words[j + 1]; // bi-gram prefix to 1 word suffix
41 | if (!model.ContainsKey(index))
42 | {
43 | model[index] = new Trigram(words[j], words[j+1]); // create entry for current word and add the preceding word to its list
44 | }
45 | model[index].Add(words[j + 2]); // e.g. k:v -> "Hello my": {prefix=["Hello", "my], suffix=List()}
46 | }
47 | }
48 | trained = true;
49 | } // end Train()
50 |
51 | public string GenerateText(int length = 20)
52 | {
53 | if (!trained)
54 | {
55 | throw new Exception("The model has not been trained yet.");
56 | }
57 | List keyList = new List(model.Keys); // list of all keys in model [["Hello my"], ["my name"], ["name is"]...]
58 | List sentence = new List(); // words used in generated sentence, to be returned
59 | string[] index = model[keyList[random.Next(keyList.Count)]].prefixWords; // get array of words used in the current index
60 | sentence.Add(index[0]); // Must ensure the sentence starts with 2 words before the rest of the text commences
61 | sentence.Add(index[1]);
62 | for (int i = 1; i != length; i++)
63 | {
64 | index[0] = sentence[i - 1]; // get previous 2 words in an array to find the next word
65 | index[1] = sentence[i];
66 | try
67 | {
68 | List suffixes = model[index[0] + index[1]].suffixes;
69 | string choice = suffixes[random.Next(suffixes.Count)];
70 | sentence.Add(choice); // get a random suffix using the index (i.e. last 2 words)
71 | }
72 | catch (KeyNotFoundException) // If no prefix pair found select a whole new pair
73 | {
74 | index = model[keyList[random.Next(keyList.Count)]].prefixWords;
75 | sentence.Add(index[0]);
76 | sentence.Add(index[1]);
77 | }
78 | }
79 | return string.Join(" ", sentence);
80 | } // GenerateText()
81 |
82 | private string CleanText(string text)
83 | { // Remove/replace unwanted characters from the full text
84 | string cleaned = text.Replace("...", "");
85 | cleaned = cleaned.Replace("\n", "");
86 | return cleaned;
87 | } // end CleanText()
88 |
89 | } // END Markov{}
90 | }
91 |
--------------------------------------------------------------------------------
/Markov Chain Sentence Generator/Trigram.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Markov_Chain_Sentence_Generator
8 | {
9 | class Trigram
10 | {
11 |
12 | public string[] prefixWords;
13 | public List suffixes;
14 |
15 | public Trigram(string prefix1, string prefix2)
16 | {
17 | prefixWords = new string[] { prefix1, prefix2 };
18 | this.suffixes = new List();
19 | }
20 |
21 | public void Add(string suffix)
22 | {
23 | suffixes.Add(suffix);
24 | } // end Add()
25 | } // END Trigram{}
26 | }
27 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Markov Text Generator
2 |
3 |
4 |
5 | Quickly generate text based on a sample of text provided. The produced text will make no logical sense except
6 | for a few occasions. This type of text generation is based of a Markov model/process whereby the program
7 | decides the next word using statistics of each preceding word found in the text.
8 |
9 | The Markov model used in this program uses a 2-word prefix (bi-gram) linked to a 1 word suffix
10 | e.g. "Hello my name is." -> {["Hello", "my"] : "name", ["my", "name"]: "is"...}.
11 |
12 | The image below shows text produced after genearting a model on the 4th Harry Potter book.
13 |
14 |
15 |
16 | ## How to Use
17 |
18 | The executable can be downloaded from the [Releases](https://github.com/akapila011/Markov-Text-Generator/releases/) page of this repository.
19 | Ensure your system has the .Net platform available to run this software. This especially affects Linux users.
20 |
21 |
22 | To use the software you first run the executable. Once the window has loaded you can select a text file to create a model.
23 | This text file must have .txt file extension. Please ensure that the text uses fullstops('.') to seperate sentences and spaces(" ") to seperate words for best results.
24 | **There are sample text file that can be [downloaded](https://github.com/akapila011/Markov-Text-Generator/tree/master/text%20files) from this repository.**
25 |
26 | Once you have selected the text file, you simply have to click the 'Train' button and you will be notified once the the model has been generated.
27 |
28 |
29 |
30 | Finally, select the number of words you want generated and click the 'Generate Text' button to get some computer generated sentences.
31 |
32 |
33 |
34 | ## Algorithm
35 |
36 | The text generation has a training phase and a execution phase.
37 |
38 | #### Training
39 | 1. Take text from the text file and break it into a list of words using a space character as the delimiter.
40 | 2. For every 3 words, use the first 2 words as a key to a list and put the the third word in the list linked to the key.
41 |
42 | This creates the model which is actually just a Dictionary where each key consists of 2 words to a value consisting of words that follow the first 2 words.
43 |
44 | #### Execution
45 | 1. Choose a random key from the model (dictionary) and add to the sentence being generated
46 | 2. Loop from index 1 to the text length specified. For every iteration:
47 | 2.1. Get the last 2 words from the generated sentence
48 | 2.2 Find the key with the last 2 words and then randomly select a word from the list associated with this key. If no key exists choose a new rnadom key and add to the sentence
49 |
50 |
51 | ### TODO:
52 | * Allow for selecting generated text.
53 | * Expand number of words produced.
54 | * Fix layout for resizing
55 |
56 |
--------------------------------------------------------------------------------
/Resources/markov-example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akapila011/Markov-Text-Generator/caa4625aa04fa68fee5cd8bb132f12bb511ebf08/Resources/markov-example.png
--------------------------------------------------------------------------------
/Resources/markov1.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akapila011/Markov-Text-Generator/caa4625aa04fa68fee5cd8bb132f12bb511ebf08/Resources/markov1.PNG
--------------------------------------------------------------------------------
/Resources/markov2.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akapila011/Markov-Text-Generator/caa4625aa04fa68fee5cd8bb132f12bb511ebf08/Resources/markov2.PNG
--------------------------------------------------------------------------------
/Resources/markov3.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akapila011/Markov-Text-Generator/caa4625aa04fa68fee5cd8bb132f12bb511ebf08/Resources/markov3.PNG
--------------------------------------------------------------------------------
/text files/A Descent Into The Maelstorm.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akapila011/Markov-Text-Generator/caa4625aa04fa68fee5cd8bb132f12bb511ebf08/text files/A Descent Into The Maelstorm.txt
--------------------------------------------------------------------------------
/text files/Mesmeric Revelation.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akapila011/Markov-Text-Generator/caa4625aa04fa68fee5cd8bb132f12bb511ebf08/text files/Mesmeric Revelation.txt
--------------------------------------------------------------------------------
/text files/The Facts in the Case of M Valdemar.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akapila011/Markov-Text-Generator/caa4625aa04fa68fee5cd8bb132f12bb511ebf08/text files/The Facts in the Case of M Valdemar.txt
--------------------------------------------------------------------------------
/text files/harrypotter4.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akapila011/Markov-Text-Generator/caa4625aa04fa68fee5cd8bb132f12bb511ebf08/text files/harrypotter4.txt
--------------------------------------------------------------------------------