Solve exercise 10
This commit is contained in:
parent
025bfa7a7f
commit
c120592296
1 changed files with 57 additions and 22 deletions
|
@ -1,10 +1,12 @@
|
|||
package ch.nuth.zhaw.exbox;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class FuzzySearchServer implements CommandExecutor {
|
||||
public static List<String> names = new ArrayList<>(); // List of all names
|
||||
|
@ -15,11 +17,24 @@ public class FuzzySearchServer implements CommandExecutor {
|
|||
// each name only once (i.e. no doublettes allowed
|
||||
public static void loadNames(String nameString) {
|
||||
// TODO implement
|
||||
BufferedReader reader = new BufferedReader(new StringReader(nameString));
|
||||
String line;
|
||||
|
||||
try {
|
||||
while ((line = reader.readLine()) != null) {
|
||||
String name = line.split(";")[0];
|
||||
names.add(name);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("An error occurred:");
|
||||
System.err.println(e);
|
||||
}
|
||||
}
|
||||
|
||||
// add a single trigram to 'trigrams' index
|
||||
public static void addToTrigrams(int nameIdx, String trig) {
|
||||
// TODO implement
|
||||
trigrams.computeIfAbsent(trig, (_name) -> new ArrayList<>()).add(nameIdx);
|
||||
}
|
||||
|
||||
// works better for flipped and short names if " " added and lowercase
|
||||
|
@ -29,52 +44,80 @@ public class FuzzySearchServer implements CommandExecutor {
|
|||
|
||||
// construct a list of trigrams for a name
|
||||
public static List<String> trigramForName(String name) {
|
||||
List<String> result = new ArrayList<>();
|
||||
name = nomalize(name);
|
||||
// TODO implement
|
||||
|
||||
for (int i = 0; i < name.length() - 3; i++) {
|
||||
result.add(name.substring(i, i + 3));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void constructTrigramIndex(List<String> names) {
|
||||
for (int nameIdx = 0; nameIdx < names.size(); nameIdx++) {
|
||||
List<String> trigs = trigramForName(names.get(nameIdx));
|
||||
|
||||
for (String trig : trigs) {
|
||||
addToTrigrams(nameIdx, trig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void incCount(int cntIdx) {
|
||||
Integer c = counts.get(cntIdx);
|
||||
c = (c == null) ? 1 : c + 1;
|
||||
counts.put(cntIdx, c);
|
||||
private static void incCount(int cntIdx, Map<Integer, Integer> counts) {
|
||||
int count = counts.computeIfAbsent(cntIdx, (_index) -> 0);
|
||||
counts.put(cntIdx, count + 1);
|
||||
}
|
||||
|
||||
// find name index with most corresponding trigrams
|
||||
// if no trigram/name matches at all then return -1
|
||||
public static int findIdx(String name) {
|
||||
counts.clear();
|
||||
public static int findIdx(String name, Map<Integer, Integer> counts) {
|
||||
int maxIdx = -1;
|
||||
// TODO implement
|
||||
int maxCount = -1;
|
||||
|
||||
for (String trigram : trigramForName(name)) {
|
||||
if (trigrams.containsKey(trigram)) {
|
||||
for (int index : trigrams.get(trigram)) {
|
||||
incCount(index, counts);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Entry<Integer, Integer> entry : counts.entrySet()) {
|
||||
if (entry.getValue() > maxCount) {
|
||||
maxCount = entry.getValue();
|
||||
maxIdx = entry.getKey();
|
||||
}
|
||||
}
|
||||
|
||||
return maxIdx;
|
||||
}
|
||||
// finde Namen gebe "" zurück wenn gefundener Name nicht grösser als verlangter score ist.
|
||||
|
||||
// finde Namen gebe "" zurück wenn gefundener Name nicht grösser als verlangter
|
||||
// score ist.
|
||||
public static String find(String searchName, int scoreRequired) {
|
||||
int found = findIdx(searchName);
|
||||
Map<Integer, Integer> counts = new HashMap<>();
|
||||
int found = findIdx(searchName, counts);
|
||||
String foundName = "";
|
||||
if (found >= 0 && score(found) >= scoreRequired) {
|
||||
|
||||
if (found >= 0 && score(found, counts) >= scoreRequired) {
|
||||
foundName = names.get(found);
|
||||
}
|
||||
return foundName;
|
||||
}
|
||||
|
||||
private static int score(int found) {
|
||||
private static int score(int found, Map<Integer, Integer> counts) {
|
||||
String foundName = names.get(found);
|
||||
return (int) (100.0 * Math.min(counts.get(found), foundName.length()) / foundName.length());
|
||||
}
|
||||
|
||||
public String execute(String searchName) {
|
||||
int found = findIdx(searchName);
|
||||
Map<Integer, Integer> counts = new HashMap<>();
|
||||
int found = findIdx(searchName, counts);
|
||||
|
||||
if (found >= 0) {
|
||||
int score = score(found);
|
||||
int score = score(found, counts);
|
||||
String foundName = names.get(found);
|
||||
return searchName + " -> " + foundName + " " + score + "%\n";
|
||||
} else {
|
||||
|
@ -82,14 +125,6 @@ public class FuzzySearchServer implements CommandExecutor {
|
|||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
FuzzySearchServer fs = new FuzzySearchServer();
|
||||
System.out.println(fs.execute("Kiptum Daniel"));
|
||||
System.out.println(fs.execute("Daniel Kiptum"));
|
||||
System.out.println(fs.execute("Kip Dan"));
|
||||
System.out.println(fs.execute("Dan Kip"));
|
||||
}
|
||||
|
||||
static {
|
||||
String rangliste = "Mueller Stefan;02:31:14\n" +
|
||||
"Marti Adrian;02:30:09\n" +
|
||||
|
|
Loading…
Reference in a new issue