I've been working on a Project Euler problem about coin combinations. I got the answer using recursion, but I wanted to try some dynamic programming so I built myself a Pair class and tried to use it as a key for a TreeMap. I was able to get it going but I kept getting the completely wrong solution.
I'm not sure what is going on. My friend suggested that perhaps something was happening with the Map trying to match the Pair references rather than values, but I tried overriding the .equals and modifying the compareTo method and it still doesn't work. (According to the docs I think TreeMap keys use equals method to match...
Here is my code. Hope someone can give it a quick browse and let me know why it doesn't work... if you uncomment the last return statement and get rid of all the map stuff you'll see my recursive only solution and that WORKS.
import java.util.Map;
import java.util.TreeMap;
public class Coins3 {
public static class Pair implements Comparable<Pair> {
Integer i1;
Integer i2;
Pair(Integer i1, Integer i2) {
this.i1 = i1;
this.i2 = i2;
}
#Override
public int compareTo(Pair arg0) {
// TODO Auto-generated method stub
if(this.equals(arg0)) return 0;
return this.i1 - arg0.i1;
}
public boolean equals(Pair arg0) {
if(this.i1.equals(arg0.i1) && this.i2.equals(arg0.i2)) return true;
return false;
}
}
static int[] coins = {1, 2, 5, 10, 20, 50, 100, 200};
static Map<Pair,Integer> memo = new TreeMap<Pair,Integer>();
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(nWays(coins.length,200));
}
public static int nWays(int index, int target) {
if(target == 0) return 1;
if(target < 0) return 0;
if(index <= 0 && target > 0) return 0;
// use the coin or not
int n1, n2;
Pair p1 = new Pair(index, target-coins[index-1]);
Pair p2 = new Pair(index-1, target);
if(memo.containsKey(p1)) {
n1 = memo.get(p1);
} else {
n1 = nWays(index,target-coins[index-1]);
memo.put(p1, n1);
}
if(memo.containsKey(p2)) {
n2 = memo.get(p2);
} else {
n2 = nWays(index-1,target);
memo.put(p2, n2);
}
return n1 + n2;
//return nWays(index-1,target) + nWays(index,target-coins[index-1]);
}
}
youve overridden equals() without overriding hashcode(), and used the class (class Pair) as a key in a map/set (your memo field).
classical beginner mistake - read this for why you should always override equals() and hashcode() together.
the short version: map always uses hashcode to "narrow down" the search key you provide, and only then uses equals() to match your key against the keys it finds "in the area". since you didnt override hashcode() your calls memo.containsKey(p1) and memo.containsKey(p2) might fail to locate the keys even if equals keys to p1/p2 exist
Related
Run into abit of trouple with my code, want to check if sharedMemory is present in entire deck(it is) and have no duplicates of an object. I am getting false with this code and I don't really know why, any help would be appreciated. rank and suit together form a card object. rank and card are enumerators with values. Note: when i use 'return Arrays.asList(entireDeck).containsAll(sharedMemory)' on its own it does show true, but the messy if part is trying to check for duplicates
public static boolean isFull(){
Card[] entireDeck = Deck.fillDeck();
sharedMemory =Arrays.asList(Deck.fillDeck());
int i=0,duplicates=0, position =0, original;
for(Card c:entireDeck){
Card f = new Card(c.rank, c.suit);
original=i;
if (f.rank.equals(sharedMemory.get(i).rank)&&f.suit.equals(sharedMemory.get(i).suit)){
duplicates+=1;
position=i;
for(i=0; i<position;i++) {
if (f.rank.equals(sharedMemory.get(i).rank)&&f.suit.equals(sharedMemory.get(i).suit))
{
duplicates += 1;
return false;
}
}
for (i=position+1; i<52; i++){
if (f.rank.equals(sharedMemory.get(i).rank)&&f.suit.equals(sharedMemory.get(i).suit))
{
duplicates += 1;
return false;
}
}
if(duplicates>1){
return false;
}
else{
i=original;
}
}
i=original;
i++;
}
return Arrays.asList(entireDeck).containsAll(sharedMemory);
}
Thanks :)
The easiest way is to use a Set<Card>. If the return value of adding an object to a set is false, then it means the set already contains it, thus a duplicate. For this to work the Card class must override both hashCode and equals.
Set<Card> set = new HashSet<>();
for(Card card : cardArray) {
if (!set.add(card)) { // if false then !false is true so signal duplicate.
System.out.println("Duplicate of " + card + " found);
break;
}
}
You can always sort the Cards and then do a one to one comparison to see if they are equal. Comparing adjacent cards of a sorted deck can also detect duplicates.
Here is one example of how this could be achieved using an integer array. For your use case you would want to implement a Comparator for sorting and ordering.
I decided to show an approach which modify the input arrays during the check (by sorting them each run). This allows for moderate performance improvements, however I doubt that your use case will be using a large enough dataset for it to be a consideration.
// Checks if a is a subset of b and does not contain duplicates
public static boolean subsetOf(int[] a, int[] b) {
Arrays.sort(a);
Arrays.sort(b);
int aIdx = 0;
int bIdx = 0;
while (aIdx < a.length && bIdx < b.length) {
if (a[aIdx] == b[bIdx]) {
aIdx++;
bIdx++;
// Check for duplicate when incrementing index
if (aIdx + 1 < a.length && a[aIdx] == a[aIdx + 1]) {
return false;
}
} else if (b[bIdx] < a[aIdx]) {
// We need to keep moving through b to find next a
bIdx++;
} else {
// We missed an element in a
return false;
}
}
// Verify that we found all elements in a
return aIdx == a.length;
}
For your use case, I would recommend something like this for readability.
import java.util.Arrays;
import java.util.Set;
import java.util.HashSet;
public static boolean subsetOf(Card[] a, Card[] b) {
Set<Card> aSet = new Hashset<>();
Set<Card> bSet = new Hashset<>();
aSet.addAll(Arrays.asList(a));
bSet.addAll(Arrays.asList(b));
return aSet.size() == a.length && bSet.containsAll(aSet);
}
In order to use this method, make sure to implement hashCode and equals in Card. You don't need to do anything fancy or import any extra libraries. The important part is that it returns a different number for every rank/suit combination.
public class Card {
// Gives a unique number for each card
#Override
public int hashCode() {
return 4 * rank + suitNum;
}
// Check if this card is the same as another object
#Override
public boolean equals(Object other) {
if (other instanceof Card) {
Card otherCard = (Card) other;
return rank == otherCard.rank && suitNum == otherCard.suitNum;
}
return false;
}
}
Post Details
In a data structures course, I was given Java source code for a "quadratic probing hash table" class and asked to implement a generic map (with get and put methods) and store the key/definition pairs in a hash table. I understand the material when reading the book but find it difficult to implement in a programming language (Java). I think part of the problem is understanding exactly what the question requires and part is deficiency in Java programming experience. I'm hoping to receive some suggestions for how I can approach problems like this and fill in whatever Java knowledge I'm missing.
Some questions I've had
What is the function of the hash table class in relation to the generic map I'm supposed to create? The hash table has several methods including get, insert, remove, rehash, etc... Is the purpose of the hash table to generate a hash value to use as a key in the map class? Are keys and definitions stored in the hash table or will they be stored in the map? What's the point of making a map if the hash table already does all of this?
Can someone help me understand how to approach problems like this? What are some references that might help me, either specifically with this question or with understanding how to effectively and methodically complete this type of exercise?
I appreciate whatever help I can get. I'm including code from the book to help illustrate the problem.
Quadratic Probing Hash Table Code From Textbook
public class QuadraticProbingHashTable<AnyType> {
public QuadraticProbingHashTable() {
this(DEFAULT_TABLE_SIZE);
}
public QuadraticProbingHashTable(int size) {
allocateArray(size);
doClear();
}
public boolean insert(AnyType x) {
int currentPos = findPos(x);
if(isActive(currentPos)) return false;
array[currentPos] = new HashEntry<>(x, true);
theSize++;
if(++occupied > array.length / 2) rehash();
return true;
}
private void rehash() {
HashEntry<AnyType>[] oldArray = array;
allocateArray(2 * oldArray.length);
occupied = 0;
theSize = 0;
for(HashEntry<AnyType> entry : oldArray)
if(entry != null && entry.isActive) insert(entry.element);
}
private int findPos(AnyType x) {
int offset = 1;
int currentPos = myhash(x);
while(array[currentPos] != null && !array[currentPos].element.equals(x)) {
currentPos += offset;
offset += 2;
if(currentPos >= array.length) currentPos -= array.length;
}
return currentPos;
}
public boolean remove(AnyType x) {
int currentPos = findPos(x);
if(isActive(currentPos)) {
array[currentPos].isActive = false;
theSize--;
return true;
} else return false;
}
public int size() {
return theSize;
}
public int capacity() {
return array.length;
}
public boolean contains(AnyType x) {
int currentPos = findPos(x);
return isActive(currentPos);
}
public AnyType get(AnyType x) {
int currentPos = findPos(x);
if(isActive(currentPos)) return array[currentPos].element;
else return null;
}
private boolean isActive(int currentPos) {
return array[currentPos] != null && array[currentPos].isActive;
}
public void makeEmpty() {
doClear( );
}
private void doClear() {
occupied = 0;
for(int i = 0; i < array.length; i++) array[i] = null;
}
private int myhash(AnyType x) {
int hashVal = x.hashCode();
hashVal %= array.length;
if(hashVal < 0) hashVal += array.length;
return hashVal;
}
private static class HashEntry<AnyType> {
public AnyType element;
public boolean isActive;
public HashEntry(AnyType e) {
this(e, true);
}
public HashEntry(AnyType e, boolean i) {
element = e;
isActive = i;
}
}
private static final int DEFAULT_TABLE_SIZE = 101;
private HashEntry<AnyType>[] array;
private int occupied;
private int theSize;
private void allocateArray(int arraySize) {
array = new HashEntry[nextPrime(arraySize)];
}
private static int nextPrime(int n) {
if(n % 2 == 0) n++;
for(; !isPrime(n); n += 2) ;
return n;
}
private static boolean isPrime( int n ) {
if(n == 2 || n == 3) return true;
if(n == 1 || n % 2 == 0) return false;
for(int i = 3; i * i <= n; i += 2)
if(n % i == 0) return false;
return true;
}
}
Map Skeleton From Textbook
class Map<KeyType,ValueType> {
public Map()
public void put(KeyType key, ValueType val)
public ValueType get(KeyType key)
public boolean isEmpty()
public void makeEmpty()
private QuadraticProbingHashTable<Entry<KeyType,ValueType>> items;
private static class Entry<KeyType,ValueType> {
KeyType key;
ValueType value;
}
}
Generally, what you're facing is a problem of implementing a given interface. The Map is the interface - the HashTable is a means of implementing it, the underlying data structure.
However, I understand your confusion as the definition of the HashTable that you were provided seems ill-suited for the job as it does not seem to have an option to use a custom key (instead always relying on the object's hash code for calculating the hash) nor does it have an option to have a custom HashEntry. As the question is specified, I would say the answer is "you can't". Generally, implementing a Map on a HashTable comes down to handling collisions - one approach, which is not very effective but usually works, is that whenever you find a collision (a case where you have differing keys but the same hashes), you rehash the entire table until the collision is no longer there. The more commonly adopted answer is having a multi-level hashtable, which basically recursively stores a hashtable (calculating a different hash function) on each level. Another method is having a hashtable of arrays - where the arrays themselves store lists of elements with the same hash - and rehashing if the number of collisions is too large. Unfortunately, neither of those solutions is directly implementable with the sample class that you were provided. Without further context, I cannot really say more, but it just seems like a badly designed exercise (this is coming from someone who does occasionally torture students with similar things).
An way of hacking this within your framework is creating a Pair type whose hashCode function just calculates key.hashCode(). This way, as a value you could store an array (and then use the array approach I mentioned above) or you could store a single element (and then use the rehash approach). In either solution, solving the collision handling is the most difficult element (you have to handle cases where the HashTable contains() your Pair, but the value part of the pair doesn't equals() the element that you want to insert.
Suppose I have this array:
double[][] Q = new double[n1][n2];
I could index the values of Q by using int indexes, such as Q[2][1]. But in my case, n1 is a byte[], not an int. I still know the possible values of n1 (e.g, all possible combinations of the array values). What collection should I use instead of an array?
HashMap<byte[], Double>[] Q = new HashMap[n2];
This was my solution, but I'm not sure it is adequate. To index, I can do
byte[] n1 = {1,0,6,1,4,2,5,1};
Q[1].get(n1);
Is there a better way to do this? Something that is more performant? I think having an array of HashMaps is not ideal, but can I add that int to my key? How?
As stated in the comments,
The problem with using an array as a hashmap key (aside from the fact that it's mutable) is that arrays don't calculate their hashcode based on their contents; so you couldn't actually look up a value in the map unless you have the actual key instance.
So how do I use an array as an indexing key? A stupid solution would be to always convert it to String before using it, but I'm sure there are better and proper solutions.
I think the best way to go for your problem is to define a complex key class, which basically consists of your byte[] and int, write reliable hashCode and equals-Methods for this class, and use it as a key to the HashMap.
This way, you can use the runtime and memory efficiency of a hashmap and encapsulate the complexity of the key in a separate class.
Code to illustrate:
public static class MyKey {
private int i;
private byte[] b;
private MyKey(int i, byte[] b) {
this.i = i;
this.b = b;
}
public static MyKey of(int i, byte ... b) {
return new MyKey(i, b);
}
#Override
public int hashCode() { // Autogenerated from eclipse
final int prime = 31;
int result = 1;
result = prime * result + Arrays.hashCode(b);
result = prime * result + i;
return result;
}
#Override
public boolean equals(Object obj) { // Autogenerated from eclipse
if(this == obj)
return true;
if(obj == null)
return false;
if(getClass() != obj.getClass())
return false;
MyKey other = (MyKey) obj;
if(!Arrays.equals(b, other.b))
return false;
if(i != other.i)
return false;
return true;
}
}
public static void main(String[] args) {
HashMap<MyKey, Double> valueMap = new HashMap<>();
valueMap.put(MyKey.of(1, (byte)2, (byte)4, (byte)7), 0.1);
valueMap.put(MyKey.of(1, new byte[] { 3, 8, 14 }), 0.1);
}
I am building a data structure to learn more about java. I understand this program might be useless.
Here's what I want. I want to create a data structure that store smallest 3 values. if value is high, then ignore it. When storing values than I also want to put them in correct place so I don't have to sort them later. I can enter values by calling the add method.
so let's say I want to add 20, 10, 40, 30 than the result will be [10,20,30]. note I can only hold 3 smallest values and it store them as I place them.
I also understand that there are a lot of better ways for doing this but again this is just for learning purposes.
Question: I need help creating add method. I wrote some code but I am getting stuck with add method. Please help.
My Thinking: we might have to use a Iterator in add method?
public class MyJavaApp {
public static void main(String[] args){
MyClass<Integer> m = new MyClass<Integer>(3);
m.add(10);
m.add(20);
m.add(30);
m.add(40);
}
}
public class MyClass<V extends Comparable<V>> {
private V v[];
public MyClass(int s){
this.v = (V[])new Object[s];
}
public void add(V a){
}
}
Here is a rough sketch of the add method you have to implement.
You have to use the appropriate implementation of the compareTo method when comparing elements.
public void add(V a){
V temp = null;
if(a.compareTo( v[0]) == -1 ){
/*
keeping the v[0] in a temp variable since, v[0] could be the second
smallest value or the third smallest value.
Therefore call add method again to assign it to the correct
position.
*/
temp = v[0];
v[0] = a;
add(temp);
}else if(a.compareTo(v[0]) == 1 && a.compareTo(v[1]) == -1){
temp = v[1];
v[1] = a;
add(temp);
}else if(a.compareTo(v[1]) == 1 && a.compareTo(v[2]) == -1){
temp = v[2];
v[2] = a;
add(temp);
}
}
Therefore the v array will contain the lowerest elements.
Hope this helps.
A naive, inefficient approach would be (as you suggest) to iterate through the values and add / remove based on what you find:
public void add(Integer a)
{
// If fewer than 3 elements in the list, add and we're done.
if (m.size() < 3)
{
m.add(a);
return;
}
// If there's 3 elements, find the maximum.
int max = Integer.MIN_VALUE;
int index = -1;
for (int i=0; i<3; i++) {
int v = m.get(i);
if (v > max) {
max = v;
index = i;
}
}
// If a is less than the max, we need to add it and remove the existing max.
if (a < max) {
m.remove(index);
m.add(a);
}
}
Note: this has been written for Integer, not a generic type V. You'll need to generalise. It also doesn't keep the list sorted - another of your requirements.
Here's an implementation of that algorithm. It consists of looking for the right place to insert. Then it can be optimized for your requirements:
Don't bother looking past the size you want
Don't add more items than necessary
Here's the code. I added the toString() method for convenience. Only the add() method is interesting. Also this implementation is a bit more flexible as it respects the size you give to the constructor and doesn't assume 3.
I used a List rather than an array because it makes dealing with generics a lot easier. You'll find that using an array of generics makes using your class a bit more ugly (i.e. you have to deal with type erasure by providing a Class<V>).
import java.util.*;
public class MyClass<V extends Comparable<V>> {
private int s;
private List<V> v;
public MyClass(int s) {
this.s = s;
this.v = new ArrayList<V>(s);
}
public void add(V a) {
int i=0;
int l = v.size();
// Find the right index
while(i<l && v.get(i).compareTo(a) < 0) i++;
if(i<s) {
v.add(i, a);
// Truncate the list to make sure we don't store more values than needed
if(v.size() > s) v.remove(v.size()-1);
}
}
public String toString() {
StringBuilder result = new StringBuilder();
for(V item : v) {
result.append(item).append(',');
}
return result.toString();
}
}
I have an ArrayList in Java :
{"PatMic", "PatientDoc", "Phram", "Patnet", "PatientA"}
All the elements have a number assigned : PatMic = 20, PatientDoc = 30, Phram = 40, Patnet = 50, PatientA = 60.
And my current Comparator :
Comparator<String> comparator = new Comparator<String>() {
#Override
public int compare(final String o1, final String o2) {
final int numbr1 = getElementNumber(); //Returns element's number in a list
final int numbr2 = getElementNumber();
if (numbr1 > numbr2 ) {
return 1;
} else if (numbr1 < numbr2 ) {
return -1;
}
return 0;
}
};
Collections.sort(strings, comparator);
I do not want to change the assigned numbers to each element but would want to move the element PatientA in between PatMic and PatientDoc so the modified list should look like :
{"PatMic", "PatientA" "PatientDoc", "Phram", "Patnet"}
Could someone please suggest how to achieve this? I tried many ways to modify the existing Comparator logic but in vain. Thank you.
You are trying to sort based on some inherent value associated with a String. Therefore, sorting on a String itself is probably not correct. What you probably want to use is either a custom object (implement equals, hashCode and the interface Comparable), or an enum type. This will allow you to change the internal state of these objects explicitly, which will manifest itself naturally when using a Comparator. For example, using a class:
class MyClass implements Comparable
{
private String name;
private int value;
//Constructor
public MyClass(String s, int v)
{
name = s;
value = v;
}
//Getters and setters
//Implement comparing method
}
Then you can use these objects in place of your Strings:
//...
MyClass patMic = new MyClass("PatMic", 20);
// So on..
First, you should give you comparator sufficient knowledge about what it should do. I mean you should have some data available to comparator that says something like "okay, sort them all by associated number except this one - place it right here". "Right here" could be anything that points exact position, I gonna choose "before that element".
So here we go
public void sortWithException(List<String> data, final Map<String, Integer> numbers, final String element, final String next) {
Collections.sort(data, new Comparator<String>() {
#Override
public int compare(String first, String second) {
if (first.equals(element) || second.equals(element)) { //the exception
Integer nextNumber = numbers.get(next);
Integer firstNumber = numbers.get(first);
Integer secondNumber = numbers.get(second);
if (first.equals(element)) {
if (next == null) // placing the exception after ANY element
return 1;
return secondNumber >= nextNumber ? -1 : 1; //placing the element before next and after all next's predecessors
} else { // second.equals(element)
if (next == null)
return -1;
return firstNumber >= nextNumber ? 1 : -1;
}
} else { //normal sort
return numbers.get(first) - numbers.get(second);
}
}
});
}
and call it like sortWithException(data, numbers, "PatientA", "PatientDoc")
Note that i used Map for associated numbers, you should probably use your own method to get those numbers.