3 dimensional ConcurrentSkipListMap map - java

I have written 3 dimensional ConcurrentSkipListMap, but not able to figure out a way to iterate over it. How do i define a iterator for the same.
import java.util.concurrent.ConcurrentSkipListMap;
/**
* Helper implementation to handle 3 dimensional sorted maps
*/
public class MyCustomIndex {
private ConcurrentSkipListMap<byte[], ConcurrentSkipListMap<byte[], ConcurrentSkipListMap<byte[], byte[]>>> table;
public MyCustomIndex() {
this.table = new ConcurrentSkipListMap<byte[], ConcurrentSkipListMap<byte[], ConcurrentSkipListMap<byte[], byte[]>>>(new CustomComparator);
}
/**
*
* #param K
* #param F
* #param Q
*/
public void put(byte[] K, byte[] F, byte[] Q) {
ConcurrentSkipListMap<byte[], byte[]> QToDummyValueMap;
ConcurrentSkipListMap<byte[], ConcurrentSkipListMap<byte[], byte[]>> FToQMap;
if( table.containsK(K)) {
FToQMap = table.get(K);
if ( FToQMap.containsK(F)) {
QToDummyValueMap = FToQMap.get(F);
} else {
QToDummyValueMap = new ConcurrentSkipListMap<byte[], byte[]>(new CustomComparator);
}
} else {
QToDummyValueMap = new ConcurrentSkipListMap<byte[], byte[]>(new CustomComparator);
FToQMap = new ConcurrentSkipListMap<byte[], ConcurrentSkipListMap<byte[], byte[]>>(new CustomComparator);
}
QToDummyValueMap.put(Q, new byte[0]);
FToQMap.put(F, QToDummyValueMap);
table.put(K, FToQMap);
}
public ConcurrentSkipListMap<byte[], ConcurrentSkipListMap<byte[], ConcurrentSkipListMap<byte[], byte[]>>> gettable() {
return table;
}
public void settable(
ConcurrentSkipListMap<byte[], ConcurrentSkipListMap<byte[], ConcurrentSkipListMap<byte[], byte[]>>> table) {
this.table = table;
}
}

Here's a nested iterator that will take an Iterator<Iterator<T>> and turn it into an Iterator<T>. Also there are static methods that allow you to grow Iterator<V> objects out of Map<K,V>s along with some higher-order stuff (Iterator<Iterator<V>> and Map<K,Map<K,V> etc.).
The idea for iterating over higher levels of iterator such as Iterator<Iterator<Iterator<T>>> would be to wrap one of these inside the other as you can see in the three-way test and the MapMapMap test.
public class NestedIterator<T> implements Iterator<T> {
// Outer iterator. Goes null when exhausted.
Iterator<Iterator<T>> i2 = null;
// Inner iterator. Goes null when exhausted.
Iterator<T> i1 = null;
// Next value.
T next = null;
// Takes a depth-2 iterator.
public NestedIterator(Iterator<Iterator<T>> i2) {
this.i2 = i2;
// Prime the pump.
if (i2 != null && i2.hasNext()) {
i1 = i2.next();
}
}
#Override
public boolean hasNext() {
// Is there one waiting?
if (next == null) {
// No!
// i1 will go null if it is exhausted.
if (i1 == null) {
// i1 is exhausted! Get a new one from i2.
if (i2 != null && i2.hasNext()) {
/// Get next.
i1 = i2.next();
// Set i2 null if exhausted.
if (!i2.hasNext()) {
// Exhausted.
i2 = null;
}
} else {
// Exhausted.
i2 = null;
}
}
// A null i1 now will mean all is over!
if (i1 != null) {
if (i1.hasNext()) {
// get next.
next = i1.next();
// Set i1 null if exhausted.
if (!i1.hasNext()) {
// Exhausted.
i1 = null;
}
} else {
// Exhausted.
i1 = null;
}
}
}
return next != null;
}
#Override
public T next() {
T n = next;
next = null;
return n;
}
#Override
public void remove() {
throw new UnsupportedOperationException("Not supported.");
}
// Iterating across Maps of Maps of Maps.
static <K1, K2, K3, V> Iterator<Iterator<Iterator<V>>> iiiV(Map<K1, Map<K2, Map<K3, V>>> i) {
final Iterator<Map<K2, Map<K3, V>>> iV = iV(i);
return new Iterator<Iterator<Iterator<V>>>() {
#Override
public boolean hasNext() {
return iV.hasNext();
}
#Override
public Iterator<Iterator<V>> next() {
return iiV(iV.next());
}
#Override
public void remove() {
iV.remove();
}
};
}
// Iterating across Maps of Maps.
static <K1, K2, V> Iterator<Iterator<V>> iiV(Map<K1, Map<K2, V>> i) {
final Iterator<Map<K2, V>> iV = iV(i);
return new Iterator<Iterator<V>>() {
#Override
public boolean hasNext() {
return iV.hasNext();
}
#Override
public Iterator<V> next() {
return iV(iV.next());
}
#Override
public void remove() {
iV.remove();
}
};
}
// Iterating across Map values.
static <K, V> Iterator<V> iV(final Map<K, V> map) {
return iV(map.entrySet().iterator());
}
// Iterating across Map.Entry Iterators.
static <K, V> Iterator<V> iV(final Iterator<Map.Entry<K, V>> i) {
return new Iterator<V>() {
#Override
public boolean hasNext() {
return i.hasNext();
}
#Override
public V next() {
return i.next().getValue();
}
#Override
public void remove() {
i.remove();
}
};
}
// **** TESTING ****
enum I {
I1, I2, I3;
};
public static void main(String[] args) {
// Two way test.
testTwoWay();
System.out.flush();
System.err.flush();
// Three way test.
testThreeWay();
System.out.flush();
System.err.flush();
// MapMap test
testMapMap();
System.out.flush();
System.err.flush();
// MapMapMap test
testMapMapMap();
System.out.flush();
System.err.flush();
}
private static void testMapMap() {
Map<String,String> m = new TreeMap<> ();
m.put("M-1", "V-1");
m.put("M-2", "V-2");
Map<String,Map<String,String>> mm = new TreeMap<> ();
mm.put("MM-1", m);
mm.put("MM-2", m);
System.out.println("MapMap");
Iterator<Iterator<String>> iiV = iiV(mm);
for (Iterator<String> i = new NestedIterator<>(iiV); i.hasNext();) {
System.out.print(i.next() + ",");
}
System.out.println();
}
private static void testMapMapMap() {
Map<String,String> m = new TreeMap<> ();
m.put("M-1", "V-1");
m.put("M-2", "V-2");
m.put("M-3", "V-3");
Map<String,Map<String,String>> mm = new TreeMap<> ();
mm.put("MM-1", m);
mm.put("MM-2", m);
Map<String,Map<String,Map<String,String>>> mmm = new TreeMap<> ();
mmm.put("MMM-1", mm);
mmm.put("MMM-2", mm);
System.out.println("MapMapMap");
Iterator<Iterator<Iterator<String>>> iiiV = iiiV(mmm);
for (Iterator<String> i = new NestedIterator<>(new NestedIterator<>(iiiV)); i.hasNext();) {
System.out.print(i.next() + ",");
}
System.out.println();
}
private static void testThreeWay() {
// Three way test.
System.out.println("Three way");
List<Iterator<I>> lii1 = Arrays.asList(
EnumSet.allOf(I.class).iterator(),
EnumSet.allOf(I.class).iterator(),
EnumSet.allOf(I.class).iterator(),
EnumSet.allOf(I.class).iterator());
List<Iterator<I>> lii2 = Arrays.asList(
EnumSet.allOf(I.class).iterator(),
EnumSet.allOf(I.class).iterator(),
EnumSet.allOf(I.class).iterator(),
EnumSet.allOf(I.class).iterator());
List<Iterator<I>> lii3 = Arrays.asList(
EnumSet.allOf(I.class).iterator(),
EnumSet.allOf(I.class).iterator(),
EnumSet.allOf(I.class).iterator(),
EnumSet.allOf(I.class).iterator());
Iterator<Iterator<Iterator<I>>> liii = Arrays.asList(
lii1.iterator(),
lii2.iterator(),
lii3.iterator()).iterator();
// Grow a 3-nest.
// Unroll it.
for (Iterator<I> ii = new NestedIterator<>(new NestedIterator<>(liii)); ii.hasNext();) {
I it = ii.next();
System.out.print(it + ",");
}
System.out.println();
}
private static void testTwoWay() {
System.out.println("Two way");
List<Iterator<I>> lii = Arrays.asList(
EnumSet.allOf(I.class).iterator(),
EnumSet.allOf(I.class).iterator(),
EnumSet.allOf(I.class).iterator());
for (Iterator<I> ii = new NestedIterator<>(lii.iterator()); ii.hasNext();) {
I it = ii.next();
System.out.print(it + ",");
}
System.out.println();
}
}
Your code can now look something like this. Note that I have not tested this at all and I have made use of Map instead of ConcurrentSkipListMap whenever possible and I am using the <> stuff from Java 7 to help out a LOT.
public class MyCustomIndex implements Iterable<byte[]> {
private Map<byte[], Map<byte[], Map<byte[], byte[]>>> table;
public MyCustomIndex() {
this.table = new ConcurrentSkipListMap<>();
}
/**
* #param K
* #param F
* #param Q
*/
public void put(byte[] K, byte[] F, byte[] Q) {
Map<byte[], byte[]> QToDummyValueMap;
Map<byte[], Map<byte[], byte[]>> FToQMap;
if (table.containsKey(K)) {
FToQMap = table.get(K);
if (FToQMap.containsKey(F)) {
QToDummyValueMap = FToQMap.get(F);
} else {
QToDummyValueMap = new ConcurrentSkipListMap<>();
}
} else {
QToDummyValueMap = new ConcurrentSkipListMap<>();
FToQMap = new ConcurrentSkipListMap<>();
}
QToDummyValueMap.put(Q, new byte[0]);
FToQMap.put(F, QToDummyValueMap);
table.put(K, FToQMap);
}
public Map<byte[], Map<byte[], Map<byte[], byte[]>>> gettable() {
return table;
}
public Iterator<byte[]> iterator () {
// **** This is what I have been aiming at all along ****
return new NestedIterator(new NestedIterator<>(NestedIterator.iiiV(table)));
}
}

Related

split strings with backtracking

I'm trying to write a code that split a spaceless string into meaningful words but when I give sentence like "arealways" it returns ['a', 'real', 'ways'] and what I want is ['are', 'always'] and my dictionary contains all this words. How can I can write a code that keep backtracking till find the best matching?
the code that returns 'a', 'real', 'ways':
splitter.java:
public class splitter {
HashMap<String, String> map = new HashMap<>();
Trie dict;
public splitter(Trie t) {
dict = t;
}
public String split(String test) {
if (dict.contains(test)) {
return (test);
} else if (map.containsKey(test)) {
return (map.get(test));
} else {
for (int i = 0; i < test.length(); i++) {
String pre = test.substring(0, i);
if (dict.contains(pre)) {
String end = test.substring(i);
String fixedEnd = split(end);
if(fixedEnd != null){
map.put(test, pre + " " + fixedEnd);
return pre + " " + fixedEnd;
}else {
}
}
}
}
map.put(test,null);
return null;
}
}
Trie.java:
public class Trie {
public static class TrieNode {
private HashMap<Character, TrieNode> charMap = new HashMap<>();
public char c;
public boolean endOWord;
public void insert(String s){
}
public boolean contains(String s){
return true;
}
}
public TrieNode root;
public Trie() {
root = new TrieNode();
}
public void insert(String s){
TrieNode p = root;
for(char c : s.toCharArray()) {
if(! p.charMap.containsKey(c)) {
TrieNode node = new TrieNode();
node.c = c;
p.charMap.put(c, node);
}
p = p.charMap.get(c);
}
p.endOWord = true;
}
public boolean contains(String s){
TrieNode p = root;
for(char c : s.toCharArray()) {
if(!p.charMap.containsKey(c)) {
return false;
}
p = p.charMap.get(c);
}
return p.endOWord;
}
public void insertDictionary(String filename) throws FileNotFoundException{
File file = new File(filename);
Scanner sc = new Scanner(file);
while(sc.hasNextLine())
insert(sc.nextLine());
}
public void insertDictionary(File file) throws FileNotFoundException{
Scanner sc = new Scanner(file);
while(sc.hasNextLine())
insert(sc.nextLine());
}
}
WordSplitter class:
public class WordSplitter {
public static void main(String[] args) throws FileNotFoundException {
String test = "arealways";
String myFile = "/Users/abc/Desktop/dictionary.txt";
Trie dict = new Trie();
dict.insertDictionary(myFile);
splitter sp = new splitter(dict);
test = sp.split(test);
if(test != null)
System.out.println(test);
else
System.out.println("No Splitting Found.");
}
}
Using the OP's split method and the implementation of Trie found in The Trie Data Structure in Java Baeldung's article, I was able to get the following results:
realways=real ways
arealways=a real ways
However, if I remove the word "real" or "a" from the dictionary, I get the following results:
realways=null
arealways=are always
Here's the entire code I used to get these results:
public class Splitter {
private static Map<String, String> map = new HashMap<>();
private Trie dict;
public Splitter(Trie t) {
dict = t;
}
/**
* #param args
*/
public static void main(String[] args) {
List<String> words = List.of("a", "always", "are", "area", "r", "way", "ways"); // The order of these words does not seem to impact the final result
String test = "arealways";
Trie t = new Trie();
for (String word : words) {
t.insert(word);
}
System.out.println(t);
Splitter splitter = new Splitter(t);
splitter.split(test);
map.entrySet().forEach(System.out::println);
}
public String split(String test) {
if (dict.find(test)) {
return (test);
} else if (map.containsKey(test)) {
return (map.get(test));
} else {
for (int i = 0; i < test.length(); i++) {
String pre = test.substring(0, i);
if (dict.find(pre)) {
String end = test.substring(i);
String fixedEnd = split(end);
if (fixedEnd != null) {
map.put(test, pre + " " + fixedEnd);
return pre + " " + fixedEnd;
} else {
}
}
}
}
map.put(test, null);
return null;
}
public static class Trie {
private TrieNode root = new TrieNode();
public boolean find(String word) {
TrieNode current = root;
for (int i = 0; i < word.length(); i++) {
char ch = word.charAt(i);
TrieNode node = current.getChildren().get(ch);
if (node == null) {
return false;
}
current = node;
}
return current.isEndOfWord();
}
public void insert(String word) {
TrieNode current = root;
for (char l : word.toCharArray()) {
current = current.getChildren().computeIfAbsent(l, c -> new TrieNode());
}
current.setEndOfWord(true);
}
#Override
public String toString() {
return toString(root);
}
/**
* #param root2
* #return
*/
private String toString(TrieNode node) {
return node.toString();
}
public static class TrieNode {
private Map<Character, TrieNode> children = new HashMap<>() ;
private String contents;
private boolean endOfWord;
public Map<Character, TrieNode> getChildren() {
return children;
}
public void setEndOfWord(boolean endOfWord) {
this.endOfWord = endOfWord;
}
public boolean isEndOfWord() {
return endOfWord;
}
#Override
public String toString() {
StringBuilder sbuff = new StringBuilder();
if (isLeaf()) {
return sbuff.toString();
}
children.entrySet().forEach(entry -> {
sbuff.append(entry.getKey() + "\n");
});
sbuff.append(" ");
return children.toString();
}
private boolean isLeaf() {
return children.isEmpty();
}
}
public void delete(String word) {
delete(root, word, 0);
}
private boolean delete(TrieNode current, String word, int index) {
if (index == word.length()) {
if (!current.isEndOfWord()) {
return false;
}
current.setEndOfWord(false);
return current.getChildren().isEmpty();
}
char ch = word.charAt(index);
TrieNode node = current.getChildren().get(ch);
if (node == null) {
return false;
}
boolean shouldDeleteCurrentNode = delete(node, word, index + 1) && !node.isEndOfWord();
if (shouldDeleteCurrentNode) {
current.getChildren().remove(ch);
return current.getChildren().isEmpty();
}
return false;
}
}
}
I improved the original code by adding a toString() method to the Trie and TrieNode. Now, when I print out the Trie object "t", I get the following result:
{a={r={e={a=}}, l={w={a={y={s=}}}}}, w={a={y={s=}}}}
My conclusion is that the OP's TrieNode implementation is incorrect. The way the Trie is built, given the inputted string value, the behavior described by the OP seems to be correct.

Get the top 3 elements from the memory cache

When I need to get the top 3 items from a Map, I can write the code,
private static Map<String, Integer> SortMapBasedOnValues(Map<String, Integer> map, int n) {
Map<String, Integer> sortedDecreasingly = map.entrySet().stream()
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue())).limit(n)
.collect(toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e2, LinkedHashMap::new));
return sortedDecreasingly;
}
I have a memory cache that I use to keep track of some app data,
public class MemoryCache<K, T> {
private long timeToLive;
private LRUMap map;
protected class CacheObject {
public long lastAccessed = System.currentTimeMillis();
public T value;
protected CacheObject(T value) {
this.value = value;
}
}
public MemoryCache(long timeToLive, final long timerInterval, int maxItems) {
this.timeToLive = timeToLive * 1000;
map = new LRUMap(maxItems);
if (this.timeToLive > 0 && timerInterval > 0) {
Thread t = new Thread(new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(timerInterval * 1000);
} catch (InterruptedException ex) {
}
cleanup();
}
}
});
t.setDaemon(true);
t.start();
}
}
public void put(K key, T value) {
synchronized (map) {
map.put(key, new CacheObject(value));
}
}
#SuppressWarnings("unchecked")
public T get(K key) {
synchronized (map) {
CacheObject c = (CacheObject) map.get(key);
if (c == null)
return null;
else {
c.lastAccessed = System.currentTimeMillis();
return c.value;
}
}
}
public void remove(K key) {
synchronized (map) {
map.remove(key);
}
}
public int size() {
synchronized (map) {
return map.size();
}
}
#SuppressWarnings("unchecked")
public void cleanup() {
long now = System.currentTimeMillis();
ArrayList<K> deleteKey = null;
synchronized (map) {
MapIterator itr = map.mapIterator();
deleteKey = new ArrayList<K>((map.size() / 2) + 1);
K key = null;
CacheObject c = null;
while (itr.hasNext()) {
key = (K) itr.next();
c = (CacheObject) itr.getValue();
if (c != null && (now > (timeToLive + c.lastAccessed))) {
deleteKey.add(key);
}
}
}
for (K key : deleteKey) {
synchronized (map) {
map.remove(key);
}
Thread.yield();
}
}
}
Inside the app, I initialize it,
MemoryCache<String, Integer> cache = new MemoryCache<String, Integer>(200, 500, 100);
Then I can add the data,
cache.put("productId", 500);
I would like to add functionality in the MemoryCache class so if called will return a HashMap of the top 3 items based on the value.
Do you have any advise how to implement that?
While I don't have a good answer, I convert the MemoryCache to the HashMap with an additional functionality implemented inside the class of MemoryCache and later, use it with the function provided earlier to retrieve the top 3 items based on the value,
Here is my updated code,
/**
* convert the cache full of items to regular HashMap with the same
* key and value pair
*
* #return
*/
public Map<Product, Integer> convertToMap() {
synchronized (lruMap) {
Map<Product, Integer> convertedMap = new HashMap<>();
MapIterator iterator = lruMap.mapIterator();
K k = null;
V v = null;
CacheObject o = null;
while (iterator.hasNext()) {
k = (K) iterator.next();
v = (V) iterator.getValue();
Product product = (Product) k;
o = (CacheObject) v;
int itemsSold = Integer.valueOf((o.value).toString());
convertedMap.put(product, itemsSold);
}
return convertedMap;
}
}

How can I restrict the generation of permutations? (In Java)

Dataset:
P1: Lion, Snow, Chair
P2: Min: 0, Max: 28
P3: Min: 34, Max is 39.
My Program is fed the above dataset (P1, P2, P3) as a series of arraylists. From this it continuously outputs different variations of a sequence including one element from each part (P1, P2, P3), until all possible permutations have been generated. (When generated P2 and P3 can be any number between their respective Min and Max.)
Examples of these sequences:
[Lion, 2, 37]
[Lion, 3, 34]
[Lion, 3, 35]
[Chair, 15, 35]
[Chair, 15, 36]
[Chair, 15, 37]
[Snow, 25, 36]
[Snow, 25, 37]
[Snow, 26, 34]
How?
To achieve this, I make use of the getCombinations function with P1,
P2 and P3 as parameters. To prepare the P2 and P3 arraylists for
use, I make use of the fillArrayList function which iterates from a
min to a max filling and then returning the relevant arraylist.
The problem I am facing is, I'm confused (lost) as to how I restrict the output of permutations which can lead to a 'Bad outcome' as below:
e.g.
P1 = Lion && P2 > 23 && P3 <= 35 Then Bad Outcome.
P1 = Lion && P2 < 13 && P3 >= 37 Then Bad Outcome.
P1 = Chair && P2 < 7 && P3 = 34 Then Bad Outcome.
Although I would be content to statically encoding a series of conditional statements for each, as these steps are read from a file which can change, this approach isn't applicable.
Code:
static ArrayList<ArrayList<String>> dataset = new ArrayList<ArrayList<String>>();
static ArrayList<ArrayList<String>> rows = new ArrayList<ArrayList<String>>();
static ArrayList<String> NegativePredictions = new ArrayList<String>();
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
init();
for (ArrayList<String> curArrayList : dataset) {
ArrayList<String> currentRule = new ArrayList<String>();
if (curArrayList.size() > 2) {
currentRule = curArrayList;
} else {
currentRule = new ArrayList<String>(
fillArrayList(Integer.parseInt(curArrayList.get(0)), Integer.parseInt(curArrayList.get(1))));
}
rows.add(currentRule);
}
getCombinations(rows).forEach(System.out::println);
}
public static void init() throws IOException {
ArrayList<String> P1 = new ArrayList<String>(Arrays.asList("Lion", "Snow", "Chair"));
ArrayList<String> P2 = new ArrayList<String>(Arrays.asList("0", "28"));
ArrayList<String> P3 = new ArrayList<String>(Arrays.asList("34", "37"));
dataset = new ArrayList<ArrayList<String>>(Arrays.asList(P1, P2, P3));
NegativePredictions = new ArrayList<String>(Files.readAllLines(Paths.get("Predict.txt")));
}
public static ArrayList<String> fillArrayList(Integer start, Integer end) {
ArrayList<String> returnedList = new ArrayList<String>();
for (int i = start; i <= end; i++) {
returnedList.add(String.valueOf(i));
}
return returnedList;
}
#SuppressWarnings("unchecked")
public static <T> List<List<T>> getCombinations(Collection<? extends Iterable<T>> valueSetCollection) {
Iterable<T>[] valueSets = new Iterable[valueSetCollection.size()];
Iterator<T>[] valueIters = new Iterator[valueSetCollection.size()];
T[] values = (T[]) new Object[valueSetCollection.size()];
int i = 0;
for (Iterable<T> valueSet : valueSetCollection) {
valueSets[i] = valueSet; // Copy to array for fast index lookup
valueIters[i] = valueSet.iterator();
values[i] = valueIters[i].next(); // Fail if a wordSet is empty
i++;
}
List<List<T>> combinations = new ArrayList<>();
NEXT_COMBO: for (;;) {
combinations.add(Arrays.asList(values.clone()));
for (i = values.length - 1; i >= 0; i--) {
if (valueIters[i].hasNext()) {
values[i] = valueIters[i].next();
continue NEXT_COMBO;
}
valueIters[i] = valueSets[i].iterator();
values[i] = valueIters[i].next();
}
return combinations;
}
}
}
What would you recommend?
Consider encoding a rule, where a set of rules determines if that particular candidate permutation is included or excluded. For example, an interface to define a rule:
public interface ExclusionRule<X> {
public boolean isExcluded(X x);
}
along with several implementations which know how to make comparisons with a String or an Integer:
public class ExcludeIfEqualStringRule implements ExclusionRule<String> {
private final String exclusion;
public ExcludeIfEqualStringRule(String exclusion) {
this.exclusion = exclusion;
}
#Override
public boolean isExcluded(String x) {
return x.equals(exclusion);
}
}
public abstract class AbstractExcludeIntegerRule implements ExclusionRule<Integer> {
private final int threshold;
private final ExclusionRule<Integer> or;
public AbstractExcludeIntegerRule(int threshold, ExclusionRule<Integer> or) {
this.threshold = threshold;
this.or = or;
}
#Override
public final boolean isExcluded(Integer x) {
if (or != null) {
return or.isExcluded(x) || doComparison(x, threshold);
}
return doComparison(x, threshold);
}
protected abstract boolean doComparison(int x, int threshold);
}
public class ExcludeIfGreaterThanIntegerRule extends AbstractExcludeIntegerRule {
public ExcludeIfGreaterThanIntegerRule(int threshold, ExclusionRule<Integer> or) {
super(threshold, or);
}
public ExcludeIfGreaterThanIntegerRule(int threshold) {
this(threshold, null);
}
#Override
protected boolean doComparison(int x, int threshold) {
return x > threshold;
}
}
public class ExcludeIfLessThanIntegerRule extends AbstractExcludeIntegerRule {
public ExcludeIfLessThanIntegerRule(int threshold, ExclusionRule<Integer> or) {
super(threshold, or);
}
public ExcludeIfLessThanIntegerRule(int threshold) {
this(threshold, null);
}
#Override
protected boolean doComparison(int x, int threshold) {
return x < threshold;
}
}
public class ExcludeIfEqualIntegerRule extends AbstractExcludeIntegerRule {
public ExcludeIfEqualIntegerRule(int threshold, ExclusionRule<Integer> or) {
super(threshold, or);
}
public ExcludeIfEqualIntegerRule(int threshold) {
this(threshold, null);
}
#Override
protected boolean doComparison(int x, int threshold) {
return x == threshold;
}
}
Along with another class which defines the set of rules to evaluate any candidate permutation:
public class ExclusionEvaluator<T, U, V> {
private final ExclusionRule<T> tRule;
private final ExclusionRule<U> uRule;
private final ExclusionRule<V> vRule;
public ExclusionEvaluator(ExclusionRule<T> tRule, ExclusionRule<U> uRule, ExclusionRule<V> vRule) {
this.tRule = tRule;
this.uRule = uRule;
this.vRule = vRule;
}
public boolean isExcluded(T t, U u, V v) {
return tRule.isExcluded(t) && uRule.isExcluded(u) && vRule.isExcluded(v);
}
}
With the three lists as separate objects, this can be encapsulated within another class which provides the getCombinations() method:
public class PermutationProvider<T, U, V> {
private final List<T> tItems;
private final List<U> uItems;
private final List<V> vItems;
private final List<ExclusionEvaluator<T, U, V>> exclusionEvaluators;
public PermutationProvider(List<T> tItems, List<U> uItems, List<V> vItems, List<ExclusionEvaluator<T, U, V>> exclusionEvaluators) {
this.tItems = tItems;
this.uItems = uItems;
this.vItems = vItems;
this.exclusionEvaluators = exclusionEvaluators;
}
public List<Permutation<T, U, V>> getCombinations() {
List<Permutation<T, U, V>> combinations = new ArrayList<>();
for (T tElement : tItems) {
for (U uElement : uItems) {
for (V vElement : vItems) {
Permutation<T, U, V> p = new Permutation<>(tElement, uElement, vElement);
if (isExcluded(tElement, uElement, vElement)) {
System.out.println(p + " IS EXCLUDED");
} else {
combinations.add(p);
}
}
}
}
return combinations;
}
private boolean isExcluded(T tElement, U uElement, V vElement) {
for (ExclusionEvaluator<T, U, V> exclusionEvaluator : exclusionEvaluators) {
if (exclusionEvaluator.isExcluded(tElement, uElement, vElement)) {
return true;
}
}
return false;
}
}
and result class to hold a permutation:
public class Permutation<T, U, V> {
private final T t;
private final U u;
private final V v;
public Permutation(T t, U u, V v) {
this.t = t;
this.u = u;
this.v = v;
}
public String toString() {
return t.toString() + " " + u.toString() + " " + v.toString();
}
}
along with a driver class to build the lists, exclusion rules, and get the accepted permutations:
public class PermuteWithExclusionsApp {
public static void main(String[] args) {
new PermuteWithExclusionsApp().permute();
}
private void permute() {
List<String> p1 = Arrays.asList("Lion", "Chair", "Snow");
List<Integer> p2 = new ArrayList<>();
for (int i = 0; i <= 28; i++) {
p2.add(i);
}
List<Integer> p3 = new ArrayList<>();
for (int i = 34; i <= 39; i++) {
p3.add(i);
}
// read from a file or some other source
List<String> compoundExclusionRules = Arrays.asList("P1 = Lion && P2 > 23 && P3 <= 35", "P1 = Lion && P2 < 13 && P3 >= 37", "P1 = Chair && P2 < 7 && P3 = 34");
ExclusionRuleFactory<String> stringRuleFactory = new StringExclusionRuleFactory();
ExclusionRuleFactory<Integer> integerRuleFactory = new IntegerExclusionRuleFactory();
ExclusionEvaluatorFactory<String, Integer, Integer> evaluatorFactory = new ExclusionEvaluatorFactory<>(stringRuleFactory, integerRuleFactory, integerRuleFactory);
List<ExclusionEvaluator<String, Integer, Integer>> evaluators = new ArrayList<>();
for (String compoundExclusionRule : compoundExclusionRules) {
evaluators.add(evaluatorFactory.create(compoundExclusionRule));
}
// List<ExclusionEvaluator<String, Integer, Integer>> evaluators = new ArrayList<>();
// evaluators.add(getExclusionRul1());
// evaluators.add(getExclusionRul2());
// evaluators.add(getExclusionRul3());
PermutationProvider<String, Integer, Integer> provider = new PermutationProvider<>(p1, p2, p3, evaluators);
List<Permutation<String, Integer, Integer>> permuations = provider.getCombinations();
for (Permutation<String, Integer, Integer> p : permuations) {
System.out.println(p);
}
}
// private ExclusionEvaluator<String, Integer, Integer> getExclusionRul3() {
// ExclusionRule<String> p1Rule = new ExcludeIfEqualStringRule("Chair");
// ExclusionRule<Integer> p2Rule = new ExcludeIfLessThanIntegerRule(7);
// ExclusionRule<Integer> p3Rule = new ExcludeIfEqualIntegerRule(34);
// return new ExclusionEvaluator<String, Integer, Integer>(p1Rule, p2Rule, p3Rule);
// }
//
// private ExclusionEvaluator<String, Integer, Integer> getExclusionRul2() {
// ExclusionRule<String> p1Rule = new ExcludeIfEqualStringRule("Lion");
// ExclusionRule<Integer> p2Rule = new ExcludeIfLessThanIntegerRule(13);
// ExclusionRule<Integer> p3Rule = new ExcludeIfGreaterThanIntegerRule(37, new ExcludeIfEqualIntegerRule(37));
// return new ExclusionEvaluator<String, Integer, Integer>(p1Rule, p2Rule, p3Rule);
// }
//
// private ExclusionEvaluator<String, Integer, Integer> getExclusionRul1() {
// ExclusionRule<String> p1Rule = new ExcludeIfEqualStringRule("Lion");
// ExclusionRule<Integer> p2Rule = new ExcludeIfGreaterThanIntegerRule(23);
// ExclusionRule<Integer> p3Rule = new ExcludeIfLessThanIntegerRule(35, new ExcludeIfEqualIntegerRule(35));
// return new ExclusionEvaluator<String, Integer, Integer>(p1Rule, p2Rule, p3Rule);
// }
Here's an example of a factory to parse the exclusion rules if for example the rules were defined as text.
public interface ExclusionRuleFactory<Z> {
public ExclusionRule<Z> create(String operator, String operand);
}
public class StringExclusionRuleFactory implements ExclusionRuleFactory<String> {
#Override
public ExclusionRule<String> create(String operator, String operand) {
return new ExcludeIfEqualStringRule(operand);
}
}
public class IntegerExclusionRuleFactory implements ExclusionRuleFactory<Integer> {
#Override
public ExclusionRule<Integer> create(String operator, String operand) {
int threshold = Integer.parseInt(operand);
switch (operator) {
case "=":
return new ExcludeIfEqualIntegerRule(threshold);
case ">":
return new ExcludeIfGreaterThanIntegerRule(threshold);
case "<":
return new ExcludeIfLessThanIntegerRule(threshold);
case ">=":
return new ExcludeIfGreaterThanIntegerRule(threshold, new ExcludeIfEqualIntegerRule(threshold));
case "<=":
return new ExcludeIfLessThanIntegerRule(threshold, new ExcludeIfEqualIntegerRule(threshold));
}
throw new IllegalArgumentException("Unsupported operator " + operator);
}
}
public class ExclusionEvaluatorFactory<T, U, V> {
private final ExclusionRuleFactory<T> p1RuleFactory;
private final ExclusionRuleFactory<U> p2RuleFactory;
private final ExclusionRuleFactory<V> p3RuleFactory;
public ExclusionEvaluatorFactory(ExclusionRuleFactory<T> p1RuleFactory, ExclusionRuleFactory<U> p2RuleFactory, ExclusionRuleFactory<V> p3RuleFactory) {
this.p1RuleFactory = p1RuleFactory;
this.p2RuleFactory = p2RuleFactory;
this.p3RuleFactory = p3RuleFactory;
}
public ExclusionEvaluator<T, U, V> create(String compoundExclusionRule) {
ExclusionRule<T> p1Rule = null;
ExclusionRule<U> p2Rule = null;
ExclusionRule<V> p3Rule = null;
String[] exclusionSubRules = compoundExclusionRule.split("&&");
for (int sr = 0; sr < exclusionSubRules.length; sr++) {
String[] ruleParts = exclusionSubRules[sr].trim().split(" ");
String whichRule = ruleParts[0].trim();
String operator = ruleParts[1].trim();
String operand = ruleParts[2].trim();
switch (whichRule) {
case "P1":
p1Rule = p1RuleFactory.create(operator, operand);
break;
case "P2":
p2Rule = p2RuleFactory.create(operator, operand);
break;
case "P3":
p3Rule = p3RuleFactory.create(operator, operand);
break;
}
}
return new ExclusionEvaluator<T, U, V>(p1Rule, p2Rule, p3Rule);
}
}
You could pass a Predicate function to your getCombinations method to filter or accept certain combinations:
/** Returns true if this combination is accepted, false if it should be filtered. */
public static boolean myFilter(Object[] combo) {
// Object arrays and casting is gross
if (combo.length != 3) {
return false;
}
try {
String p1 = (String) combo[0];
// Why are they strings?
Integer p2 = Integer.valueOf((String) combo[1]);
Integer p3 = Integer.valueOf((String) combo[2]);
return !("Lion".equals(p1) && (13 > p2) && (35 >= p3))
&& !("Lion".equals(p1) && (13 > p2) && (37 <= p3))
&& !("Chair".equals(p1) && (7 > p2) && (34 == p3));
} catch (Exception e) {
// invalid combination, filter it
return false;
}
}
#SuppressWarnings("unchecked")
public static <T> List<List<T>> getCombinations(
Collection<? extends Iterable<T>> valueSetCollection,
Predicate<Object[]> filter) {
Iterable<T>[] valueSets = new Iterable[valueSetCollection.size()];
Iterator<T>[] valueIters = new Iterator[valueSetCollection.size()];
T[] values = (T[]) new Object[valueSetCollection.size()];
int i = 0;
for (Iterable<T> valueSet : valueSetCollection) {
valueSets[i] = valueSet; // Copy to array for fast index lookup
valueIters[i] = valueSet.iterator();
values[i] = valueIters[i].next(); // Fail if a wordSet is empty
i++;
}
List<List<T>> combinations = new ArrayList<>();
NEXT_COMBO: for (;;) {
T[] v = values.clone();
if (filter.test(v)) {
combinations.add(Arrays.asList(v));
} else {
System.out.println("rejected " + Arrays.asList(v));
}
for (i = values.length - 1; i >= 0; i--) {
if (valueIters[i].hasNext()) {
values[i] = valueIters[i].next();
continue NEXT_COMBO;
}
valueIters[i] = valueSets[i].iterator();
values[i] = valueIters[i].next();
}
return combinations;
}
}
public static void main(String[] args){
// ...
getCombinations(rows, MyClass::myFilter).forEach(System.out::println);
System.out.println("##############################");
// accept all
getCombinations(rows, o -> true).forEach(System.out::println);
}
Also, rather than passing lists of lists it may be better to make a data container class like this:
public class MyCombination {
private final String s;
private final int i1;
private final int i2;
public MyCombination(String s, int i1, int i2){
this.s = s;
this.i1 = i1;
this.i2 = i2;
}
}

Modifying Dijkstra to save paths with equal values - StackOverflow error

I'm trying to modify Dijkstra's algorithm to show all the paths that have the minimum value. So I decided to use a list of previous vertices. And I added an if clause that checks if the path is igual to the previous with minimum value I add the previous vertex as the parent of the current one.
The problem is that I am getting a StackOverflow error and I don't know what is causing it.
This is my code:
The purpose of the code below is to calculate Dijkstra for all of the vertices in the graph, calculate the number of times a vertex appears in the minimum paths found and display in decrescent order the all of them.
public class Dijkstra {
public static final Map<String, Integer> ordem = new HashMap<>();
public static void main(String[] args) throws FileNotFoundException, IOException {
List<Graph.Edge> edges = new ArrayList<>();
try {
FileReader arq = new FileReader("input.txt");
BufferedReader fw = new BufferedReader(arq);
String linha = "";
while (fw.ready()) {
linha = fw.readLine();
if (!linha.equals("0,0,0")) {
String parts[] = linha.split(",");
ordem.put(parts[0], 0);
ordem.put(parts[1], 0);
Graph.Edge a = new Graph.Edge(parts[0], parts[1], 100 - Integer.parseInt(parts[2]));
edges.add(a);
} else {
break;
}
}
fw.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Graph g = new Graph(edges);
for (int i = 0; i < 5; i++) {
g.dijkstra(String.valueOf(i));
g.printAllPaths();
}
Object[] a = ordem.entrySet().toArray();
Arrays.sort(a, new Comparator() {
public int compare(Object o1, Object o2) {
return ((Map.Entry<String, Integer>) o2).getValue()
.compareTo(((Map.Entry<String, Integer>) o1).getValue());
}
});
for (Object e : a) {
System.out.print(((Map.Entry<String, Integer>) e).getKey() + " ");
}
System.out.println("\n");
}
}
class Graph {
private final Map<String, Vertex> graph;
public static class Edge {
public final String v1, v2;
public final int dist;
public Edge(String v1, String v2, int dist) {
this.v1 = v1;
this.v2 = v2;
this.dist = dist;
}
}
public static class Vertex implements Comparable<Vertex> {
public final String name;
public int dist = Integer.MAX_VALUE;
public List<Vertex> previous = new ArrayList<>();
public final Map<Vertex, Integer> neighbours = new HashMap<>();
public Vertex(String name) {
this.name = name;
}
private void printPath() {
if (this == this.previous) {
} else if (this.previous == null) {
} else {
//This is where I am getting the error
for (int i = 0; i<this.previous.size(); i++){
this.previous.get(i).printPath();
Dijkstra.ordem.replace(this.name, Dijkstra.ordem.get(this.name) + 1);
}
}
}
public int compareTo(Vertex other) {
if (dist == other.dist) {
return name.compareTo(other.name);
}
return Integer.compare(dist, other.dist);
}
#Override
public String toString() {
return "(" + name + ", " + dist + ")";
}
}
public Graph(List<Graph.Edge> edges) {
graph = new HashMap<>(edges.size());
for (Edge e : edges) {
if (!graph.containsKey(e.v1)) {
graph.put(e.v1, new Vertex(e.v1));
}
if (!graph.containsKey(e.v2)) {
graph.put(e.v2, new Vertex(e.v2));
}
}
for (Edge e : edges) {
graph.get(e.v1).neighbours.put(graph.get(e.v2), e.dist);
graph.get(e.v2).neighbours.put(graph.get(e.v1), e.dist);
}
}
public void dijkstra(String startName) {
if (!graph.containsKey(startName)) {
System.err.printf("Graph doesn't contain start vertex \"%s\"\n", startName);
return;
}
final Vertex source = graph.get(startName);
NavigableSet<Vertex> q = new TreeSet<>();
// Inicializacao dos vertices
for (Vertex v : graph.values()) {
//v.previous = v == source ? list : null;
if (v == source) {
v.previous.add(source);
} else {
v.previous = new ArrayList<>();
}
v.dist = v == source ? 0 : Integer.MAX_VALUE;
q.add(v);
}
dijkstra(q);
}
private void dijkstra(final NavigableSet<Vertex> q) {
Vertex u, v;
while (!q.isEmpty()) {
u = q.pollFirst();
if (u.dist == Integer.MAX_VALUE) {
}
for (Map.Entry<Vertex, Integer> a : u.neighbours.entrySet()) {
v = a.getKey();
final int alternateDist = u.dist + a.getValue();
if (alternateDist < v.dist) {
q.remove(v);
v.dist = alternateDist;
v.previous.add(u);
q.add(v);
} else if(alternateDist == v.dist) {
v.previous.add(u);
}
}
}
}
public void printPath(String endName) {
if (!graph.containsKey(endName)) {
System.err.printf("Graph doesn't contain end vertex \"%s\"\n", endName);
return;
}
graph.get(endName).printPath();
//System.out.println();
}
public void printAllPaths() {
for (Vertex v : graph.values()) {
v.printPath();
}
}
}
This is the error:
Exception in thread "main" java.lang.StackOverflowError
at Graph$Vertex.printPath(Dijkstra.java:117)
at Graph$Vertex.printPath(Dijkstra.java:118)
As the Error message already suggests: Your dijkstra isn't the problem.
The problem is printPath() calling itself.
Likely the culprit is
if (this == this.previous) {} ...
You compare Vertex this to List<Vertex> previous. Maybe you want to check
if (this == this.previous.get(this.previous.size() - 1)) {} ...
instead.
I didn't test this, because your code is (1.) too long and (2.) not self-contained (missing at least "input.txt").

MultiKey HashMap Implementation

I'm looking for an implementation of MultiKey (actually DoubleDouble) to single Value. * BUT * you can access the value via ONE OF THE KEYS!
meaning, It's not mandatory to have both keys in order to access the map.
I know I can write something to fulfill my request - but the question is if there is something out there that is already written so I can use it out-of-the-box.
Thanks :-)
EDIT:
At this point the best implementation I can think of is this:
class DoubleKeyHashMap<K1, K2, V> {
BiMap<K1, K2> keys; // Bidirectional map
Map<K2, V> values;
..
..
}
This seems like a good start to a multi key map implementation.
Edited to add a removeElement method, and to save and return a List of values.
package com.ggl.testing;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class MultiMap<K, V> {
private static long sequence = 0;
private Map<K, Long> key1Map;
private Map<K, Long> key2Map;
private Map<Long, List<V>> valueMap;
public MultiMap() {
this.key1Map = new HashMap<>();
this.key2Map = new HashMap<>();
this.valueMap = new HashMap<>();
}
public void addElement(K key1, K key2, V value) {
boolean key1boolean = key1Map.containsKey(key1);
boolean key2boolean = key2Map.containsKey(key2);
boolean key3boolean = key1Map.containsKey(key2);
boolean key4boolean = key2Map.containsKey(key1);
if (key1boolean && key2boolean) {
Long key1Value = key1Map.get(key1);
Long key2Value = key2Map.get(key2);
updateValue(key1, key2, key1Value, key2Value, value);
} else if (key3boolean && key4boolean) {
Long key1Value = key1Map.get(key2);
Long key2Value = key2Map.get(key1);
updateValue(key1, key2, key1Value, key2Value, value);
} else if (key1boolean || key4boolean) {
String s = displayDuplicateError(key1);
throw new IllegalStateException(s);
} else if (key2boolean || key3boolean) {
String s = displayDuplicateError(key2);
throw new IllegalStateException(s);
} else {
createValue(key1, key2, value);
}
}
private void createValue(K key1, K key2, V value) {
Long newKeyValue = sequence++;
key1Map.put(key1, newKeyValue);
key2Map.put(key2, newKeyValue);
List<V> values = new ArrayList<>();
values.add(value);
valueMap.put(newKeyValue, values);
}
private void updateValue(K key1, K key2, Long key1Value, Long key2Value,
V value) {
if (key1Value.equals(key2Value)) {
List<V> values = valueMap.get(key1Value);
values.add(value);
valueMap.put(key1Value, values);
} else {
String s = displayMismatchError(key1, key2);
throw new IllegalStateException(s);
}
}
private String displayMismatchError(K key1, K key2) {
return "Keys " + key1.toString() + " & " + key2.toString()
+ " have a different internal key.";
}
private String displayDuplicateError(K key) {
return "Key " + key.toString() + " is part of another key pair";
}
public List<V> getElement(K key) {
if (key1Map.containsKey(key)) {
return valueMap.get(key1Map.get(key));
}
if (key2Map.containsKey(key)) {
return valueMap.get(key2Map.get(key));
}
return null;
}
public boolean removeElement(K key) {
if (key1Map.containsKey(key)) {
Long key1Value = key1Map.get(key);
Set<Entry<K, Long>> entrySet = key2Map.entrySet();
K key2 = getOtherKey(key1Value, entrySet);
valueMap.remove(key1Value);
key1Map.remove(key);
key2Map.remove(key2);
return true;
} else if (key2Map.containsKey(key)) {
Long key2Value = key2Map.get(key);
Set<Entry<K, Long>> entrySet = key1Map.entrySet();
K key1 = getOtherKey(key2Value, entrySet);
valueMap.remove(key2Value);
key1Map.remove(key1);
key2Map.remove(key);
return true;
}
return false;
}
private K getOtherKey(Long key1Value, Set<Entry<K, Long>> entrySet) {
Iterator<Entry<K, Long>> iter = entrySet.iterator();
K key = null;
while (iter.hasNext() && key == null) {
Entry<K, Long> entry = iter.next();
if (entry.getValue().equals(key1Value)) {
key = entry.getKey();
}
}
return key;
}
public static void main(String[] args) {
MultiMap<String, String> multiMap = new MultiMap<>();
try {
multiMap.addElement("one", "two", "numbers");
multiMap.addElement("alpha", "beta", "greek alphabet");
multiMap.addElement("beta", "alpha", "alphabet");
multiMap.addElement("iron", "oxygen", "elements");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Arrays.toString(multiMap.getElement("iron")
.toArray()));
System.out.println(Arrays.toString(multiMap.getElement("beta")
.toArray()));
System.out.println(multiMap.removeElement("two"));
}
}

Categories