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;
|
package ch.nuth.zhaw.exbox;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.StringReader;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
public class FuzzySearchServer implements CommandExecutor {
|
public class FuzzySearchServer implements CommandExecutor {
|
||||||
public static List<String> names = new ArrayList<>(); // List of all names
|
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
|
// each name only once (i.e. no doublettes allowed
|
||||||
public static void loadNames(String nameString) {
|
public static void loadNames(String nameString) {
|
||||||
// TODO implement
|
// 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
|
// add a single trigram to 'trigrams' index
|
||||||
public static void addToTrigrams(int nameIdx, String trig) {
|
public static void addToTrigrams(int nameIdx, String trig) {
|
||||||
// TODO implement
|
// TODO implement
|
||||||
|
trigrams.computeIfAbsent(trig, (_name) -> new ArrayList<>()).add(nameIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// works better for flipped and short names if " " added and lowercase
|
// 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
|
// construct a list of trigrams for a name
|
||||||
public static List<String> trigramForName(String name) {
|
public static List<String> trigramForName(String name) {
|
||||||
|
List<String> result = new ArrayList<>();
|
||||||
name = nomalize(name);
|
name = nomalize(name);
|
||||||
// TODO implement
|
// 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) {
|
public static void constructTrigramIndex(List<String> names) {
|
||||||
for (int nameIdx = 0; nameIdx < names.size(); nameIdx++) {
|
for (int nameIdx = 0; nameIdx < names.size(); nameIdx++) {
|
||||||
List<String> trigs = trigramForName(names.get(nameIdx));
|
List<String> trigs = trigramForName(names.get(nameIdx));
|
||||||
|
|
||||||
for (String trig : trigs) {
|
for (String trig : trigs) {
|
||||||
addToTrigrams(nameIdx, trig);
|
addToTrigrams(nameIdx, trig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void incCount(int cntIdx) {
|
private static void incCount(int cntIdx, Map<Integer, Integer> counts) {
|
||||||
Integer c = counts.get(cntIdx);
|
int count = counts.computeIfAbsent(cntIdx, (_index) -> 0);
|
||||||
c = (c == null) ? 1 : c + 1;
|
counts.put(cntIdx, count + 1);
|
||||||
counts.put(cntIdx, c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// find name index with most corresponding trigrams
|
// find name index with most corresponding trigrams
|
||||||
// if no trigram/name matches at all then return -1
|
// if no trigram/name matches at all then return -1
|
||||||
public static int findIdx(String name) {
|
public static int findIdx(String name, Map<Integer, Integer> counts) {
|
||||||
counts.clear();
|
|
||||||
int maxIdx = -1;
|
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;
|
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) {
|
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 = "";
|
String foundName = "";
|
||||||
if (found >= 0 && score(found) >= scoreRequired) {
|
|
||||||
|
if (found >= 0 && score(found, counts) >= scoreRequired) {
|
||||||
foundName = names.get(found);
|
foundName = names.get(found);
|
||||||
}
|
}
|
||||||
return foundName;
|
return foundName;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int score(int found) {
|
private static int score(int found, Map<Integer, Integer> counts) {
|
||||||
String foundName = names.get(found);
|
String foundName = names.get(found);
|
||||||
return (int) (100.0 * Math.min(counts.get(found), foundName.length()) / foundName.length());
|
return (int) (100.0 * Math.min(counts.get(found), foundName.length()) / foundName.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String execute(String searchName) {
|
public String execute(String searchName) {
|
||||||
int found = findIdx(searchName);
|
Map<Integer, Integer> counts = new HashMap<>();
|
||||||
|
int found = findIdx(searchName, counts);
|
||||||
|
|
||||||
if (found >= 0) {
|
if (found >= 0) {
|
||||||
int score = score(found);
|
int score = score(found, counts);
|
||||||
String foundName = names.get(found);
|
String foundName = names.get(found);
|
||||||
return searchName + " -> " + foundName + " " + score + "%\n";
|
return searchName + " -> " + foundName + " " + score + "%\n";
|
||||||
} else {
|
} 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 {
|
static {
|
||||||
String rangliste = "Mueller Stefan;02:31:14\n" +
|
String rangliste = "Mueller Stefan;02:31:14\n" +
|
||||||
"Marti Adrian;02:30:09\n" +
|
"Marti Adrian;02:30:09\n" +
|
||||||
|
|
Loading…
Reference in a new issue