Greedy Algorithm java in map - java

I'm working on emulator of ATM in java. The overall pattern in project is Command.
So I have 4 commands - getInfo, deposit,withdraw and exit.
I'm facing problems with an implementation of greedy algorithm in withdrawal method. It should return Map were first Integer is "denomination" and second Integer is "amount" left in ATM after we withdrew.
public Map<Integer, Integer> withdrawAmount(int expectedAmount)
So it takes expected amount as an argument and has to subtract it from ATM with the least possible amount of bills.
public class CurrencyManipulator
{
// denominations is a map where each denomination and it's quantity stored
private String currencyCode;
private Map<Integer, Integer> denominations = new HashMap<>();
public String getCurrencyCode()
{
return currencyCode;
}
public CurrencyManipulator(String currencyCode)
{
this.currencyCode = currencyCode;
}
public void addAmount(int denomination, int count)
{
if (denominations.containsKey(denomination))
{
denominations.put(denomination, denominations.get(count) + count);
} else
{
denominations.put(denomination, count);
}
}
public int getTotalAmount()
{
int sum = 0;
for (Map.Entry<Integer, Integer> pair : denominations.entrySet())
{
sum = pair.getKey() * pair.getValue();
}
return sum;
}
public boolean hasMoney()
{
return denominations.size() != 0;
}
public boolean isAmountAvailable(int expectedAmount)
{
return expectedAmount <= getTotalAmount();
}
public Map<Integer, Integer> withdrawAmount(int expectedAmount) throws NotEnoughMoneyException
{
}
}
So I need this method to return a map or throw exception if amount asked "expectedAmount" is higher then money available in ATM.
If we take $600 it could be - three bills: $500 + $50 + $50 OR $200 + $200 + $200, the preferred option is $500 + $50 + $50
Example, you have to give $600
The ATM has the following bill-count:
500 - 2
200 - 3
100 - 1
50 - 12
The result should be:
500 - 1
100 - 1
This what I came up with:
public Map<Integer, Integer> withdrawAmount(int expectedAmount) throws NotEnoughMoneyException
{
denominations.put(50,1);
denominations.put(500,1);
denominations.put(200,3);
HashMap<Integer, Integer> map = new HashMap<>();
TreeMap<Integer, Integer> sortedMap = new TreeMap<>(Collections.reverseOrder());
sortedMap.putAll(denominations);
ArrayList<Integer> bills = new ArrayList<>();
bills.addAll(sortedMap.keySet());
int num;
for (int i = 0; i < bills.size(); i++)
{
if (bills.get(i) <= expectedAmount)
{
num = expectedAmount / bills.get(i);
map.put(bills.get(i), num);
expectedAmount -= num * bills.get(i);
}
}
System.out.println(map);
return map;
}
It returns the map of needed bills and their quantity.
Now my question is..how do i compare it with the "denominations" map i have and subtract new map from it?

seems to be working code if someone ever needs it
public Map<Integer, Integer> withdrawAmount(int expectedAmount) throws NotEnoughMoneyException
{
denominations.put(50,2);
denominations.put(500,1);
denominations.put(100,1);
HashMap<Integer, Integer> map = new HashMap<>();
TreeMap<Integer, Integer> sortedDenominations = new TreeMap<>(Collections.reverseOrder());
sortedDenominations.putAll(denominations);
ArrayList<Integer> bills = new ArrayList<>();
bills.addAll(sortedDenominations.keySet());
int num;
for (int i = 0; i < bills.size(); i++)
{
if (bills.get(i) <= expectedAmount)
{
num = expectedAmount / bills.get(i);
map.put(bills.get(i), num);
expectedAmount -= num * bills.get(i);
}
}
System.out.println(map);
for (Map.Entry<Integer,Integer> denominPresent:sortedDenominations.entrySet()){
int value;
for (Map.Entry<Integer,Integer> deominNeeded:map.entrySet()){
if(denominPresent.getKey().equals(deominNeeded.getKey())){
value = denominPresent.getValue()-deominNeeded.getValue();
if (value>=0) sortedDenominations.put(denominPresent.getKey(),value);
else throw new NotEnoughMoneyException();
}
}
}
System.out.println(sortedDenominations);
return sortedDenominations;
}

Another solution. Will work if you initialize the denominations variable using TreeMap
...
private Map<Integer, Integer> denominations = new TreeMap<>(Comparator.reverseOrder());
...
public Map<Integer, Integer> withdrawAmount(int expectedAmount) throws NotEnoughMoneyException {
final Map<Integer, Integer> map = new TreeMap<>(Comparator.reverseOrder());
// calculate denomination map to cash
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
int denomination = entry.getKey();
if (denomination <= expectedAmount) {
int num = Math.min(expectedAmount / denomination, entry.getValue());
map.put(denomination, num);
expectedAmount -= num * denomination;
}
if (expectedAmount == 0) {
break;
}
}
if (expectedAmount != 0) {
throw new NotEnoughMoneyException();
}
map.forEach((key, value) -> {
denominations.compute(key, (denomination, count) -> {
return (count == value) ? null : count - value;
});
});
return map;
}

Related

Java Collections - Print interstates sorted by population, city and state

I am working on a problem I came across in an interview.
Input contains Population|City|State|Interstates list
Output needs to be sorted in descending order by population first, then alphabetically by city and state, and then the interstates need to be sorted in ascending order too.
Sample input:
27|Chicago|Illinois|I-94;I-90;I-88;I-57;I-55
83|New York|New York|I-78;I-95;I-87;I-80
15|Phoenix|Arizona|I-10;I-17;I-8
15|Philadelphia|Pennsylvania|I-95;I-76
Sample output:
83
New York, New York
Interstates: I-78, I-80, I-87, I-95
27
Chicago, Illinois
Interstates: I-55, I-57, I-88, I-90, I-94
15
Philadelphia, Pennsylvania
Interstates: I-76, I-95
Phoenix, Arizona
Interstates: I-8, I-10, I-17
Here's my approach so far. I am currently stuck in the if block where I've added a comment. I am not sure if I am going in the right direction. I am looking for a hint to take the right approach here.
Scanner sc = new Scanner(System.in);
String line;
List<String> al = new ArrayList<>();
//Outer map sorts reverse by population, inner map1 sorts by city, inner
map2 sorts by state
Map<Integer, Map<String, Map<String, String>>> outerMap = new TreeMap<>
(Collections.reverseOrder());
Map<String, Map<String, String>> innerMap1 = new TreeMap<>();
Map<String, String> innerMap2 = new TreeMap<>();
while(sc.hasNextLine() && (line = sc.nextLine()).length()!=0) {
//Ignore if input contains this character
if(line.contains("#")) {
line = sc.nextLine();
}
al.add(line);
}
for(int i = 0; i < al.size(); i++) {
int outerMapKey = Integer.parseInt(al.get(i).split("\\|")[0]);
String innerMap1Key = al.get(i).split("\\|")[1];
String innerMap2Key = al.get(i).split("\\|")[2];
String value = al.get(i);
outerMap.get(outerMapKey);
if(outerMap.containsKey(outerMapKey)) {
innerMap1 = outerMap.get(outerMapKey);
/* Logic to put values in inner maps
This is going to get very convoluted, not sure if I have the
right approach
*/
}
else {
innerMap1 = new TreeMap<>();
innerMap2 = new TreeMap<>();
innerMap2.put(innerMap2Key, value);
innerMap1.put(innerMap1Key, innerMap2);
outerMap.put(outerMapKey, innerMap1);
}
}
Thank you for all your help so far. I am posting my code (working now) based on feedback here. Please take a look and suggest how it can be improved.
public static void main(String[] args) {
Map<String, List<PopulationByCityState>> map = readAndProcessInput();
printSortedOutput(map);
}
private static Map<String, List<PopulationByCityState>> readAndProcessInput() {
Map<String, List<PopulationByCityState>> map = readInput();
sortByPopulationCityAndState(map);
return map;
}
private static Map<String, List<PopulationByCityState>> readInput() {
System.out.println("Enter input:");
Scanner sc = new Scanner(System.in);
String line;
Map<String, List<PopulationByCityState>> map = new TreeMap<>(Collections.reverseOrder());
while (sc.hasNextLine() && (line = sc.nextLine()).length() != 0) {
if (line.contains("#")) {
line = sc.nextLine();
}
populateMap(line, map);
}
return map;
}
private static void populateMap(String line, Map<String, List<PopulationByCityState>> map) {
String[] s = line.split("\\|");
String[] is = s[3].split(";");
String key = s[0];
PopulationByCityState p = new PopulationByCityState();
p.setPopulation(Long.parseLong(s[0]));
p.setCity(s[1]);
p.setState(s[2]);
List<String> interstates = new ArrayList<>();
for (String aString : is) {
interstates.add(aString);
}
sortInterstates(interstates);
p.setInterstates(interstates);
if (map.containsKey(key)) {
map.get(key).add(p);
} else {
List<PopulationByCityState> al = new ArrayList<>();
al.add(p);
map.put(key, al);
}
}
private static void sortInterstates(List<String> interstates) {
Collections.sort(interstates, new Comparator<String>() {
#Override
public int compare(String o1, String o2) {
int n1 = Integer.parseInt(o1.split("-")[1]);
int n2 = Integer.parseInt(o2.split("-")[1]);
return n1 - n2;
}
});
}
private static void sortByPopulationCityAndState(Map<String, List<PopulationByCityState>> map) {
for (Map.Entry entry : map.entrySet()) {
List<PopulationByCityState> list = (List<PopulationByCityState>) entry.getValue();
Collections.sort(list, new Comparator<PopulationByCityState>() {
#Override
public int compare(PopulationByCityState o1, PopulationByCityState o2) {
int c;
c = (int) (o2.getPopulation() - o1.getPopulation());
if (c == 0) {
c = o1.getCity().compareTo(o2.getCity());
}
if (c == 0) {
c = o1.getState().compareTo(o2.getState());
}
return c;
}
});
}
}
private static void printSortedOutput(Map<String, List<PopulationByCityState>> map) {
for (Map.Entry<String, List<PopulationByCityState>> entry : map.entrySet()) {
System.out.println(entry.getKey());
System.out.println();
List<PopulationByCityState> list = entry.getValue();
for (PopulationByCityState p : list) {
System.out.println(p.getCity() + ", " + p.getState());
List<String> interstates = p.getInterstates();
System.out.print("Interstates: ");
int s = 0;
for (String is : interstates) {
s++;
System.out.print(is);
if (s != interstates.size()) {
System.out.print(", ");
}
}
System.out.println();
System.out.println();
}
}
}
Your approach relies on over complicated and not meaningful structure and also uses a Comparator that will only sort the first level of the map :
Map<Integer, Map<String, Map<String, String>>> outerMap = new TreeMap<>
(Collections.reverseOrder());
A finer approach could rely on using a class that represents each individual information that you need to represent a population for a state : PopulationForState
Here is a very simple representation of it (that is of course improvable but that should help you to understand the logic) :
public class PopulationForState{
private long population;
private String city;
private String state;
private List<String> interstates;
...
// getters
}
Add instances of them in a List and use a comparator that sorted them in descending order by population first, then alphabetically by city and state.
The interstates field may be sorted independently or directly during the sort of outer elements.
You could provide a sort method in PopulationForState, for example sortInnerStates() that sorts them in ascending order.
Personally, I would make it independently to keep the processing less coupled between.
So you could write something like :
List<PopulationForState> populationForStates = new ArrayList<>();
populationForStates.add(new PopulationForState(...));
populationForStates.add(new PopulationForState(...));
Collection.sort(populationForStates, Comparator.comparing(PopulationForState::population).reversed()
.thenComparing(PopulationForState::getCity)
.thenComparing(PopulationForState::getState);
populationForStates.stream()
.forEach(PopulationForState::sortInnerStates);
If you have a structure such the one posted in above post:
public class PopulationForState{
public long population;
public String city;
public String state;
public List<String> interstates;
//Do encapsulate
}
You can sort it with one comparator:
Collections.sort(populatisForStates, new Comparator<PopulationForState>(){
public int compare(PopulationForState first, PopulationForState scnd) {
int compare = first.population - scnd.population;
if(compare != 0) return compare;
compare = first.city.compareTo(scnd.city);
if(compare != 0) return compare;
return first.state.compareTo(scnd.state);
}
});
Sorting Interstates is similar and you just need to use Collections.sort(interstates) on each instance.

Return the key of the smallest difference after substracting two values from hashmap?

How can I return the key of the smallest difference after substracting two values from a hashmap?
Example
first loop -> 10 - 8 = 2;
second loop -> 10 - 9 = 1;
third loop -> 10 - 7 = 3;
therefore second loop -> 10 - 9 = 1 is the smallest, so the key is "Three".
Code
import java.util.HashMap;
public class Difference {
HashMap<String,Double> hashMap = new HashMap<>();
double firstValue = 0;
double secondValue = 0;
double difference = 0;
public Difference() {
hashMap.put("One", 10.0);
hashMap.put("Two", 8.0);
hashMap.put("Three", 9.0);
hashMap.put("Four", 7.0);
firstValue = hashMap.get("One");
for (String key : hashMap.keySet()) {
if(!key.equals("One")) {
secondValue = hashMap.get(key);
difference = Math.abs(secondValue - firstValue);
}
}
}
public static void main(String[] args) {
new Difference();
}
}
Please Help. Thanks.
You can achieve that using something like the following:
public class MainTest {
public static void main(String[] args) {
HashMap<String,Double> hashMap = new HashMap<>();
hashMap.put("One", 10.0);
hashMap.put("Two", 8.0);
hashMap.put("Three", 9.0);
hashMap.put("Four", 7.0);
hashMap.put("Five", 10.1);
System.out.println(getSmallestDiffKeyJava8(hashMap, "One"));
}
/* This works only with java 8 */
private static String getSmallestDiffKeyJava8(Map<String, Double> map, String constantKey) {
double constant = map.get(constantKey);
return map.entrySet().stream()
.filter(entry -> !constantKey.equals(entry.getKey())) // Remove the constant from the values we process
.map(entry -> new SimpleEntry<>(entry.getKey(), Math.abs(entry.getValue() - constant))) // Map to a new entry with the key and the diff
.min((o1, o2) -> (int)(o1.getValue() - o2.getValue())) // Find the min
.map(Entry::getKey)
.get();
}
/* This works with older versions as well */
private static String getSmallestDiffKey(Map<String, Double> map, String constantKey) {
double constant = map.get(constantKey);
String key = null;
Double diff = null;
for (Entry<String, Double> entry : map.entrySet()) {
if (!constantKey.equals(entry.getKey())) {
double d = Math.abs(entry.getValue() - constant);
if (diff == null || diff > d) {
diff = d;
key = entry.getKey();
}
}
}
return key;
}
}
Try to use code something like that:
String smallestKey;
if(difference !=0 && difference < Math.abs(secondValue - firstValue);){
difference = Math.abs(secondValue - firstValue);
smallestKey = key;
}
I think your problem is simpler than you think. I know it's not the best one but here's a solution :
import java.util.HashMap;
public class Difference {
HashMap<String,Double> hashMap = new HashMap<>();
double firstValue = 0;
double secondValue = 0;
double difference = 0;
HashMap<Double, String> theMap = new HashMap<Double, String>();
public Difference() {
hashMap.put("One", 10.0);
hashMap.put("Two", 8.0);
hashMap.put("Three", 9.0);
hashMap.put("Four", 7.0);
firstValue = hashMap.get("One");
for (String key : hashMap.keySet()) {
if(!key.equals("One")) {
secondValue = hashMap.get(key);
difference = Math.abs(secondValue - firstValue);
theMap.put(difference, key);
}
}
Set<Double> dbl = theMap.keySet();
Double smallestDifference = findSmallest(dbl);
String smallestValue = hashMap.get(smallestDifference);
}
public Double findSmallest(Set<Double> setDbl){
Double smallest = 99999999.0;
for(Double d : setDbl){
if(d < smallest)
smallest = d;
}
return smallest;
}
public static void main(String[] args) {
new Difference();
}
}

Java edge case collection hashmap iteration

I got this problem I need to return the key in a hashmap with the largest value, the trick here is that the method must account for edge case scenarios. I can also only use the above imports, so Map.Entry is not allowed. Collections.sort isn't etc. Thanks.
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
public class Exercise {
public static String findLargest(HashMap<String, Integer> map) {
// Enter code here
if(that.isEmpty()) return "";
Integer maxInt = Integer.MIN_VALUE;
String maxCity = "";
for(String entry : that.keySet()) {
if (that.get(entry) != null && that.get(entry) < Integer.MAX_VALUE && that.get(entry) > Integer.MIN_VALUE && that.get(entry) > maxInt) {
maxInt = that.get(entry);
maxCity = entry;
}
}
return maxCity;
}
public static void check(String largest, List<String> apples, List<Integer> size) {
HashMap<String, Integer> map = new HashMap<>();
for (int i = 0; i < apples.size(); i++) {
map.put(apples.get(i), size.get(i));
}
assert largest.equals(findLargest(map)) : "expected " + largest + " but was " + findLargest(map);
}
public static void main(String[] arg) {
check("Granny", Arrays.asList("Granny", "Eve", "Rose"), Arrays.asList(5, 1, 2));
}
}
The solution is really inefficient, but if you cannot add any other imports... it works. The first step is to find the maximum value among the integers and then for each of the keys, check if the map.get(key).equals(max):
public static String findLargest(HashMap<String, Integer> map) {
//step 1
int max = Integer.MIN_VALUE;
for (int i : map.values()) {
max = Math.max(max, i);
}
//step 2
for (String str : map.keySet()) {
if (map.get(str).equals(max)) {
return str;
}
}
return null;
}

Cannot count number in ArrayList using java

I am using the List as shown below:-
List<Integer> integerlist = new ArrayList<Integer>();
integerlist=primeFactors(numberToBERadical);
The primeFactors method return me some number when i sysOut as:-
System.out.println("integer list=="+integerlist);
integer list==[2, 2, 2, 3, 5]
My Problem is i want to count how many time that each number appears so that i can show Like this:-
2^3 * 3 * 5
You need to associate each factor with the number of times it occurs (the exponent).
To do that, a better data structure than a List would be a Map<Integer,Integer>.
Let's assume you still get a List from your primeFactors(numberToBERadical); (assuming you can't change it or don't want to for some reason).
You can do something like:
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(2);
list.add(2);
list.add(2);
list.add(3);
list.add(3);
list.add(5);
Map<Integer, Integer> factors = new HashMap<>();
for(Integer fact: list){
if(!factors.containsKey(fact)) { factors.put(fact, 1);}
else {
Integer value = factors.get(fact);
factors.put(fact, ++value);
}
}
System.out.println(factors);
}
Prints: {2=3, 3=2, 5=1}
If the array is sorted, you can count them like:
int count = 0;
int last = 0; // zero is not possible for prime-factors
for(int i=0;i<list.size();i++) {
if(i == 0 || last == list.get(i)) count++;
else {
if(last > list.get(0)) {
System.out.print(" * ");
}
System.out.print(last + (count > 1 ? "^" + count: ""));
count = 1;
}
last = list.get(i);
}
//print last sequence.
if(last > 0) {
if(last > list.get(0)) {
System.out.print(" * ");
}
System.out.print(last + (count > 1 ? "^" + count: ""));
}
You need to use a Map<Integer, Integer> which you can override the put method in in order to count the instances of each Integer.
final Map<Integer, Integer> myStringMap = new HashMap<>(){
#override
public String put(final Integer key, final Integer value) {
if(contains(key)) {
return put(key, get(key) + 1);
} else {
return put(key, 1);
}
}
};
You could even use a TreeMap to have the prime factors sorted by size. I answered a very similar question here. Simply loop over your List and dump it into the map
for(final Integer integer : myList) {
myCountingMap.put(integer, 1);
}
Even better would be to change your factorising method to return a Map to begin with.
List<Integer> inputList = new ArrayList<Integer>();
inputList.add(2);
inputList.add(2);
inputList.add(2);
inputList.add(3);
inputList.add(3);
inputList.add(4);
Map<Integer, Integer> resultMap = new HashMap<Integer, Integer>();
boolean flag = false;
for(int val : inputList)
{
if(resultMap.get(val) == null)
{
resultMap.put(val, 1);
}
else
{
resultMap.put(val, (resultMap.get(val).intValue())+1);
}
}
for(int key : resultMap.keySet())
{
if(resultMap.get(key) == 1)
{
if(!flag)
{
System.out.print(key);
flag = true;
}
else
{
System.out.print("*"+key);
}
}
else
{
if(!flag)
{
System.out.print(key+"^"+resultMap.get(key));
flag = true;
}
else
{
System.out.print("*"+key+"^"+resultMap.get(key));
}
}
}
System.out.println();
One possible, but not the simplest solution:
public Map<Integer, AtomicInteger> primeFactors(List<Integer integerList) {
final Map<Integer, AtomicInteger> count = new HashMap<Integer, AtomicInteger>();
for (final Integer number : integerlist) {
if (count.containsKey(number)) {
count.get(number).incrementAndGet();
} else {
count.put(number, new AtomicInteger(1));
}
}
return count;
}

Choosing the Correct Collections

I have a situation where I have set of Players in a Room and every Player will have set of cards in their hand.
HashMap<Integer,ArrayList<Integer>> useridToCardsinTheirHand = new HashMap<Integer, ArrayList<Integer>>();
Any Player can "Make a Call".
I need to check if the Player who has made a 'call' has the least value
(least value of the aggregate cards).
To Proceed with the above logic I use again an LinkedhashMap
private static LinkedhashMap<Integer,Integer> useridTotalRank = new LinkedhashMap<Integer,Integer>();
If there is a tie in the values then there will a priority algorithm carried on.
I use hashMap in all the logics.
I am facing problems since I am using HashMaps. The Logic flow is clumsy.
I am planning to make a redesign.I am going through MultiMap , But still anticipate the similar problem.
Can I have suggestions on the kind of Collections to be used.
The psuedo code I have tried is ::
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
public class NewCalling {
static HashMap<Integer,ArrayList<Integer>> useridToPointsmap = new HashMap<Integer, ArrayList<Integer>>();
lamposHAshMap hashmapsort = new lamposHAshMap();
private static HashMap<Integer,Integer> useridTotalRank = new HashMap<Integer,Integer>();
private static int jokercard = 0x27;
private static int closedjokercard =0x25 ;
private static List<Integer> faceCards = new ArrayList<Integer>();
#SuppressWarnings("unchecked")
public static void main(String args[]) {
/**
* Assuming the calling is made and the Player id is hard Coded
*/
boolean callingflag = true;
int callinguserid = 2;
/*************** Preparing the information which will be given by the ********/
ArrayList<Integer> cardsArray1 = new ArrayList<Integer>();
ArrayList<Integer> cardsArray2 = new ArrayList<Integer>();
ArrayList<Integer> cardsArray3 = new ArrayList<Integer>();
ArrayList<Integer> cardsArray4 = new ArrayList<Integer>();
cardsArray1.add(0x01);
cardsArray1.add(0x1A);
//cardsArray1.add(0x33);
cardsArray2.add(0x21);
cardsArray2.add(0x03);
cardsArray2.add(0x32);
cardsArray3.add(0x21);
cardsArray3.add(0x03);
cardsArray3.add(0x32);
cardsArray4.add(0x01);
cardsArray4.add(0x02);
cardsArray4.add(0x32);
cardsArray4.add(0x31);
useridToPointsmap.put(1,cardsArray1);
useridToPointsmap.put(2,cardsArray2);
useridToPointsmap.put(3,cardsArray3);
useridToPointsmap.put(4,cardsArray4);
faceCards.add(0,10);
faceCards.add(1,11);
faceCards.add(2,12);
faceCards.add(3,13);
/*************** Preparing the information which will be given by the ********/
if(callingflag)
{
int calledUserTp = totalPointsByUserid(callinguserid,jokercard);
System.out.println("Total Points of the User Who has made a Call is ::"+calledUserTp);
HashMap<Integer,Integer> useridTotalRankMap = totalPointsforEveryUser(jokercard);
LinkedHashMap<Integer,Integer> useridTotalRankMapSorted = new LinkedHashMap<Integer, Integer>();
useridTotalRankMapSorted = (LinkedHashMap<Integer, Integer>) sortByComparator(useridTotalRankMap);
for(Map.Entry<Integer, Integer> entry :useridTotalRankMapSorted.entrySet())
{
System.out.println( entry.getKey() +"----"+entry.getValue());
if(entry.getKey() == callinguserid )
{
System.out.println( "GOOD CALL");
break;
}
}
}
}
/** Gives the Cards Rank **/
static int getCardRank(int Cardhexvalue)
{
int rank = Cardhexvalue & 15;
return rank;
}
/** Gives the Cards Suit **/
static int getCardSuit(int Cardhexvalue)
{
int suit = (Cardhexvalue>>4);
return suit;
}
// METHODS REQUIRED
private static HashMap<Integer,Integer> totalPointsforEveryUser(int jokerCardVal)
{
for(Map.Entry<Integer, ArrayList<Integer>> entry :useridToPointsmap.entrySet())
{
int sum = 0;
int playerId = entry.getKey();
ArrayList<Integer> cardsList = entry.getValue();
for (Integer s : cardsList)
{
if (getCardRank(s) != getCardRank(jokerCardVal)) {
if (faceCards.contains(s))
{
sum += 10;
}
else
{
sum += getCardRank(s);
}
}
}
useridTotalRank.put(playerId, sum);
}
return useridTotalRank;
}
private static int totalPointsByUserid(int userId,int jokerCardVal)
{
ArrayList<Integer> cardsList = useridToPointsmap.get(userId);
int sum = 0;
for (Integer s : cardsList)
{
if (getCardRank(s) != getCardRank(jokerCardVal)) {
if (faceCards.contains(s))
{
sum += 10;
}
else
{
sum += getCardRank(s);
}
}
}
return sum;
}
#SuppressWarnings("unchecked")
private static Map sortByComparator(Map unsortMap) {
List list = new LinkedList(unsortMap.entrySet());
//sort list based on comparator
Collections.sort(list, new Comparator() {
public int compare(Object o1, Object o2) {
return ((Comparable) ((Map.Entry) (o1)).getValue())
.compareTo(((Map.Entry) (o2)).getValue());
}
});
//put sorted list into map again
Map sortedMap = new LinkedHashMap();
for (Iterator it = list.iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry)it.next();
sortedMap.put(entry.getKey(), entry.getValue());
}
return sortedMap;
}
private static boolean checkForNoDuplicates(HashMap<Integer, Integer > useridTotalRankMapSorted)
{
Collection<Integer> valuesList = useridTotalRankMapSorted.values();
Set<Integer> valuesSet = new HashSet<Integer>(useridTotalRankMapSorted.values());
System.out.println("-----"+ valuesList.size() +"----"+valuesSet.size());
if(valuesList.size() == valuesSet.size())
{
return true;
}
else
return false;
}
// Stack
public static HashMap getDuplicateValues(HashMap in)
{
// Clone input HashMap because we're removing stuff from it
in = (HashMap)in.clone();
HashMap rval = new HashMap();
Object[] keys = in.keySet().toArray();
// iterate through all keys
for(int x=0;x<keys.length;x++) {
Object value = in.get(keys[x]);
in.remove(keys[x]);
// if value is in input HashMap, store it in duplicate HashMap because it has another value
if(in.containsValue(value)) {
rval.put(keys[x],value);
}
// if value is in duplicate HashMap, store it also because it HAD another value earlier
if(rval.containsValue(value)) {
rval.put(keys[x],value);
}
}
return(rval);
}
public static HashMap<Object, ArrayList<Object>> gettingTheDuplicates(HashMap map) {
HashMap<Object, ArrayList<Object>> newMap = new HashMap<Object, ArrayList<Object>>();
Set<Entry> set = map.entrySet();
for(Entry entry : set) {
ArrayList list = new ArrayList();
if(newMap.containsKey(entry.getValue())) {
list=newMap.get(entry.getValue());
}
list.add(entry.getKey());
newMap.put(entry.getValue(), list);
}
return newMap;
}
private static void priorityCheck(int playerId1,int playerId2,int jokerCardVal)
{
int jokerCountPlayerOne = 0;
int jokerCountPlayerTwo = 0;
int openJokerCountPlayerOne = 0;
int openJokerCountPlayerTwo = 0;
List<Integer> playerOneCards = useridToPointsmap.get(playerId1);
List<Integer> playerTwoCards = useridToPointsmap.get(playerId2);
System.out.println("Current game player cards-----"+playerOneCards);
System.out.println("Tied game player cards--------"+playerTwoCards);
int playerOneCardCount = playerOneCards.size();
int playerTwoCardCount = playerTwoCards.size();
// Hard coded
// playerOneCardCount = 4;
//playerTwoCardCount = 4;
// jokerCountPlayerOne = 1;
// jokerCountPlayerTwo = 1;
//openJokerCountPlayerOne =1;
//openJokerCountPlayerTwo =2;
System.out.println("---jokerCardVal---"+jokerCardVal);
System.out.println("---playerOneCardCount---playerTwoCardCount"+playerOneCardCount+" "+playerTwoCardCount);
if (playerOneCards.contains(jokerCardVal))
{
openJokerCountPlayerOne++;
}
if (playerTwoCards.contains(jokerCardVal))
{
openJokerCountPlayerTwo++;
}
if (playerOneCards.contains(0))
{
jokerCountPlayerOne++;
}
if (playerTwoCards.contains(0))
{
jokerCountPlayerTwo++;
}
if (playerOneCardCount == playerTwoCardCount)
{
if (jokerCountPlayerOne == jokerCountPlayerTwo)
{
if (openJokerCountPlayerOne == openJokerCountPlayerTwo)
{
System.out.println("Still Tie Occurring---------------");
} else
{
if (openJokerCountPlayerOne > openJokerCountPlayerTwo)
{
System.out.println("First player has high rank based on open joker");
} else
{
System.out.println("Second player has high rank based on open joker");
}
}
} else
{
if (jokerCountPlayerOne > jokerCountPlayerTwo)
{
System.out.println("First player has high rank based on joker");
} else
{
System.out.println("Second player has high rank based on joker");
}
}
} else
{
if (playerOneCardCount < playerTwoCardCount)
{
System.out.println("First player has high rank based on Count");
} else
{
System.out.println("Second player has high rank based on count");
}
}
}
// New Priority Check
private static List<Integer> priorityNew(ArrayList<Integer> tocompare)
{
// ArrayList to array
Integer[] sortedArray = (Integer[]) tocompare.toArray();
bubble_srt(sortedArray,sortedArray.length);
List<Integer> mapValuesNew = Arrays.asList(sortedArray);
return mapValuesNew;
}
public static void bubble_srt( Integer a[], int n ){
int i, j,t=0;
for(i = 0; i < n; i++){
for(j = 1; j < (n-i); j++){
// System.out.print(" I am in first "+a[j-1]+" "+a[j] +"*********"+whichCardHigher(a[j-1],a[j]));
if(WhichuserHigher(a[j-1],a[j])){
t = a[j-1];
a[j-1]=a[j];
a[j]=t;
}
}
}
}
public static boolean WhichuserHigher(int user1,int user2)
{
if(getNumberofCards(user1) == getNumberofCards(user1) )
{
if(getNumberofJoker(user1) == getNumberofJoker(user2))
{
if(getNumberofClosedJoker(user1) == getNumberofClosedJoker(user2))
{
System.out.println("Its a Mega Tie");
}
else
{
if(getNumberofClosedJoker(user1) > getNumberofClosedJoker(user2))
{
return true;
}
else
{
return false;
}
}
}
else
{
if(getNumberofJoker(user1) > getNumberofJoker(user2))
{
return true;
}
else
{
return false;
}
}
}
else
{
if(getNumberofCards(user1) >getNumberofCards(user2))
{
return true;
}
else
{
return false;
}
}
return false;
}
public static int getNumberofCards(int user)
{
int noOfCards = 0;
for(Map.Entry<Integer, ArrayList<Integer>> entry :useridToPointsmap.entrySet())
{
if(entry.getKey() == user)
{
noOfCards = entry.getValue().size();
}
}
return noOfCards;
}
public static int getNumberofJoker(int user)
{
int noOfJokers = 0;
int count = 0;
for(Map.Entry<Integer, ArrayList<Integer>> entry :useridToPointsmap.entrySet())
{
if(entry.getKey() == user)
{
for(int i= 0 ;i< entry.getValue().size();i++)
{
if(Integer.parseInt(entry.getValue().toString()) == jokercard)
{
count ++;
}
}
}
}
noOfJokers = count;
return noOfJokers;
}
public static int getNumberofClosedJoker(int user)
{
int noOfClosedJokers = 0;
int count = 0;
for(Map.Entry<Integer, ArrayList<Integer>> entry :useridToPointsmap.entrySet())
{
if(entry.getKey() == user)
{
for(int i= 0 ;i< entry.getValue().size();i++)
{
if(Integer.parseInt(entry.getValue().toString()) == closedjokercard)
{
count ++;
}
}
}
}
noOfClosedJokers = count;
return noOfClosedJokers;
}
}
Please have simple Java beans for Room, Player and Card (probably for Card may not be necessary) etc. This way you can change the properties of the classes when new requirement comes in the future. Ultimately you need to manage only List Room, so that if you get an Room object you can easily retrieve the Players from it and so on.
Class Room{
String roomName;
String location;
String List<Player>;
// have getters setters for each of them
}
This way it is more manageable as well, so that processing code if any present you can put them in the related classes only. for e.g. In the room class you can have a method called getLeastValueCard which returns for that Room which user and you can have loop for entire Rooms.
Hope this make sense.

Categories

Resources