-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAutocomplete.java
134 lines (109 loc) · 4.83 KB
/
Autocomplete.java
1
2
3
4
5
6
7
8
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
public class Autocomplete {
public final static Path filePath = Path.of("data.txt");
public static String data = "";
public static String prompt = "";
public static int contextWords = 4; // The number of words to look for (as context for the next word)
public static int numberOfSuggestions = 3; // The number of top suggestions to pick a random suggestion from
public static int wordsToComplete = 100; // The number of words to autocomplete
private static Random randomGenerator;
public static void main(String[] args) {
data = getData(filePath).toLowerCase();
randomGenerator = new Random();
while(true) {
prompt = Str.input("Enter text to autocomplete: ");
for (int i = 0; i < wordsToComplete; i++) {
prompt = completePrompt(prompt, data, contextWords, numberOfSuggestions);
}
Str.print(prompt);
}
}
/**
* Extracts a string from the input file
* @param filePath The path of the input file
* @return A string that contains the contents of the file
* @exception IOException Signals that an I/O exception of some sort has occurred (e.g. file path does not exist)
*/
public static String getData(Path filePath) {
String inputString = "";
try {
inputString = Files.readString(filePath);
}
catch (IOException e) {
e.printStackTrace();
}
return inputString;
}
/**
* Completes an additional word for the given prompt
* @param prompt The prompt to complete
* @param data The dataset to extract suggestions from
* @param contextWords The number of words to look for (as context for the next word)
* @param numberOfSuggestions The number of top suggestions to pick a random suggestion from
* @return A new string with the prompt and autocompleted word
*/
public static String completePrompt(String prompt, String data, int contextWords, int numberOfSuggestions) {
String promptWords[] = prompt.split(" ");
String context = "";
if (promptWords.length < contextWords) {
context = prompt.toLowerCase();
}
else {
context = promptWords[promptWords.length - contextWords];
for (int i = contextWords - 1; i > 0; i--) {
context = String.join(" ", context, promptWords[promptWords.length - i]);
}
context = (context + " ").toLowerCase();
}
int index = data.indexOf(context);
int dataLength = data.length();
String complete = "";
String completeWord = "";
int wordIndex = 0;
List<Integer> contextIndex = new ArrayList<>();
List<String> contextComplete = new ArrayList<>();
while (index >= 0) {
contextIndex.add(index);
index = data.indexOf(context, index + 1);
int beginIndex = index + context.length();
int endIndex = index + context.length() + 20;
if (index >= 0 && endIndex <= dataLength) {
complete = data.substring(beginIndex, endIndex);
wordIndex = 0;
completeWord = complete.split(" ")[wordIndex];
while (Pattern.matches("\\p{Punct}", completeWord)) {
wordIndex++;
completeWord = complete.split(" ")[wordIndex];
}
contextComplete.add(completeWord.strip());
}
}
Map<String, Integer> frequencyMap = new HashMap<String, Integer>();
for (int i = 0; i < contextComplete.size(); i++) {
frequencyMap.put(contextComplete.get(i), Collections.frequency(contextComplete, contextComplete.get(i)));
}
List<String> topSuggestions = frequencyMap
.entrySet().stream().sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
.limit(numberOfSuggestions).map(Map.Entry::getKey).collect(Collectors.toList());
String nextEntry = topSuggestions.size() > 0 ? topSuggestions.get(randomGenerator.nextInt(topSuggestions.size())) : "";
if (nextEntry.isBlank() && contextWords > 2) {
return completePrompt(prompt, data, contextWords - 1, numberOfSuggestions);
}
else if (nextEntry.isBlank() && contextWords <= 2) {
return String.join(" ", prompt, "and");
}
else {
return String.join(" ", prompt, nextEntry);
}
}
}