Solve exercise 10

This commit is contained in:
Manuel Thalmann 2022-11-22 22:27:05 +01:00
parent 025bfa7a7f
commit c120592296

View file

@ -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" +