Java edge case collection hashmap iteration - java

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;
}

Related

implementing comparator to sort list of strings

I have a list of strings which I would like to sort instead of by their lexicographic order- by their weight (number of times the word appears in the specifies URL / number of words in this URL).
the problem is with the methode "searchPrefix" that when I creat a new Comparator, it obviously doesn't recognize the fields of that class in which I use to calculate the weight.
things iv'e tried:
1. using SortedMap and then there is no need to implement the Comparator, only that the instructions specifically note to implement the Comparator.
2. using getters (also didn't work because i'm working within the class and the methode);
3. implement the list as List> urlList = new ArrayList... also didn't work.
(The implementation of Comparator is what I would like to do)
how do I change it to work?
package il.ac.tau.cs.sw1.searchengine;
import java.util.*
public class MyWordIndex implements WordIndex {
public SortedMap<String, HashMap<String, Integer>> words;
public HashMap<String, Integer> urls;
public MyWordIndex() {
this.words = new TreeMap<String, HashMap<String, Integer>>();;
this.urls = new HashMap<String, Integer>();
}
#Override
public void index(Collection<String> words, String strURL) {
this.urls.put(strURL, words.size()); // to every page- how many words in it.
String subPrefix = "";
HashMap<String, Integer> help1; // how many times a word appears on that page
for (String word : words) {
if (word == null || word == "") // not a valid word
continue;
word.toLowerCase();
help1 = new HashMap<String, Integer>();
for (int i = 0; i < word.length(); i++) {
subPrefix = word.substring(0, i);
if (this.words.get(subPrefix) == null) { // new prefix
help1.put(strURL, 1);
this.words.put(subPrefix, help1);
}
else { // prefix exists
if (this.words.get(subPrefix).get(strURL) == null)//new URL with old prefix
this.words.get(subPrefix).put(strURL, 1);
else // both url and prefix exists
this.words.get(subPrefix).put(strURL, help1.get(strURL) + 1);
}
}
}
}
#Override
public List<String> searchPrefix(String prefix) {
prefix.toLowerCase();
List<String> urlList = new ArrayList<String>();
for (String word : this.words.keySet()) {
if (word.startsWith(prefix)) {
for (String strUrl : this.words.get(word).keySet()) {
urlList.add(strUrl);
}
}
}
Collections.sort(urlList, new Comparator<String>() {
#Override
public int compare(String strUrl1, String strUrl2) {
Double d1 = this.words.get(word).get(strUrl1) / this.urls.get(strUrl1);
Double d2 = this.words.get(word).get(strUrl2) / this.urls.get(strUrl2);
return Double.compare(d1, d2);
}
});
........
}
These changes take you closer to a solution.
Double d1 = MyWordIndex.this.words.get(word).get(strUrl1) / (double) MyWordIndex.this.urls.get(strUrl1);
Double d2 = MyWordIndex.this.words.get(word).get(strUrl2) / (double) MyWordIndex.this.urls.get(strUrl2);
I don't know what word is supposed to be though as there is no variable with that name in scope.
Suggestion for the for-loop in your index method:
for (int i = 1; i < word.length(); i++) { // no point starting at 0 - empty string
subPrefix = word.substring(0, i);
if (this.words.get(subPrefix) == null) { // new prefix
help1.put(strURL, 1);
this.words.put(subPrefix, help1);
}
else { // prefix exists
Integer count = this.words.get(subPrefix).get(strURL);
if (count == null)//new URL with old prefix
count = 0;
this.words.get(subPrefix).put(strURL, count + 1);
}
}
While we are on this, may I suggest Guava multiset which does this sort of counting for you automatically:
import com.google.common.collect.Multiset;
import com.google.common.collect.HashMultiset;
public class MultiTest{
public final Multiset<String> words;
public MultiTest() {
words = HashMultiset.create();
}
public static void main(String []args) {
MultiTest test = new MultiTest();
test.words.add("Mandible");
test.words.add("Incredible");
test.words.add("Commendable");
test.words.add("Mandible");
System.out.println(test.words.count("Mandible")); // 2
}
}
Finally to solve your problem, this should work, haven't tested:
#Override
public List<String> searchPrefix(String prefix) {
prefix = prefix.toLowerCase(); // Strings are immutable so this returns a new String
Map<String, Double> urlList = new HashMap<String, Double>();
for (String word : this.words.keySet()) {
if (word.startsWith(prefix)) {
for (String strUrl : this.words.get(word).keySet()) {
Double v = urlList.get(strUrl);
if (v == null) v = 0;
urlList.put(strUrl, v + this.words.get(word).get(strUrl));
}
}
}
List<String> myUrls = new ArrayList<String>(urlList.keySet());
Collections.sort(myUrls, new Comparator<String>() {
#Override
public int compare(String strUrl1, String strUrl2) {
return Double.compare(urlList.get(strUrl1) / MyWordIndex.this.urls.get(strUrl1),
urlList.get(strUrl2) / MyWordIndex.this.urls.get(strUrl2));
}
});
return myUrls;
}

Partition a Set into smaller Subsets and process as batch

I have a continuous running thread in my application, which consists of a HashSet to store all the symbols inside the application. As per the design at the time it was written, inside the thread's while true condition it will iterate the HashSet continuously, and update the database for all the symbols contained inside HashSet.
The maximum number of symbols that might be present inside the HashSet will be around 6000. I don't want to update the DB with all the 6000 symbols at once, but divide this HashSet into different subsets of 500 each (12 sets) and execute each subset individually and have a thread sleep after each subset for 15 minutes, so that I can reduce the pressure on the database.
This is my code (sample code snippet)
How can I partition a set into smaller subsets and process (I have seen the examples for partitioning ArrayList, TreeSet, but didn't find any example related to HashSet)
package com.ubsc.rewji.threads;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.PriorityBlockingQueue;
public class TaskerThread extends Thread {
private PriorityBlockingQueue<String> priorityBlocking = new PriorityBlockingQueue<String>();
String symbols[] = new String[] { "One", "Two", "Three", "Four" };
Set<String> allSymbolsSet = Collections
.synchronizedSet(new HashSet<String>(Arrays.asList(symbols)));
public void addsymbols(String commaDelimSymbolsList) {
if (commaDelimSymbolsList != null) {
String[] symAr = commaDelimSymbolsList.split(",");
for (int i = 0; i < symAr.length; i++) {
priorityBlocking.add(symAr[i]);
}
}
}
public void run() {
while (true) {
try {
while (priorityBlocking.peek() != null) {
String symbol = priorityBlocking.poll();
allSymbolsSet.add(symbol);
}
Iterator<String> ite = allSymbolsSet.iterator();
System.out.println("=======================");
while (ite.hasNext()) {
String symbol = ite.next();
if (symbol != null && symbol.trim().length() > 0) {
try {
updateDB(symbol);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void updateDB(String symbol) {
System.out.println("THE SYMBOL BEING UPDATED IS" + " " + symbol);
}
public static void main(String args[]) {
TaskerThread taskThread = new TaskerThread();
taskThread.start();
String commaDelimSymbolsList = "ONVO,HJI,HYU,SD,F,SDF,ASA,TRET,TRE,JHG,RWE,XCX,WQE,KLJK,XCZ";
taskThread.addsymbols(commaDelimSymbolsList);
}
}
With Guava:
for (List<String> partition : Iterables.partition(yourSet, 500)) {
// ... handle partition ...
}
Or Apache Commons:
for (List<String> partition : ListUtils.partition(yourList, 500)) {
// ... handle partition ...
}
Do something like
private static final int PARTITIONS_COUNT = 12;
List<Set<Type>> theSets = new ArrayList<Set<Type>>(PARTITIONS_COUNT);
for (int i = 0; i < PARTITIONS_COUNT; i++) {
theSets.add(new HashSet<Type>());
}
int index = 0;
for (Type object : originalSet) {
theSets.get(index++ % PARTITIONS_COUNT).add(object);
}
Now you have partitioned the originalSet into 12 other HashSets.
We can use the following approach to divide a Set.
We will get the output as
[a, b]
[c, d]
[e]`
private static List<Set<String>> partitionSet(Set<String> set, int partitionSize)
{
List<Set<String>> list = new ArrayList<>();
int setSize = set.size();
Iterator iterator = set.iterator();
while(iterator.hasNext())
{
Set newSet = new HashSet();
for(int j = 0; j < partitionSize && iterator.hasNext(); j++)
{
String s = (String)iterator.next();
newSet.add(s);
}
list.add(newSet);
}
return list;
}
public static void main(String[] args)
{
Set<String> set = new HashSet<>();
set.add("a");
set.add("b");
set.add("c");
set.add("d");
set.add("e");
int size = 2;
List<Set<String>> list = partitionSet(set, 2);
for(int i = 0; i < list.size(); i++)
{
Set<String> s = list.get(i);
System.out.println(s);
}
}
If you are not worried much about space complexity, you can do like this in a clean way :
List<List<T>> partitionList = Lists.partition(new ArrayList<>(inputSet), PARTITION_SIZE);
List<Set<T>> partitionSet = partitionList.stream().map((Function<List<T>, HashSet>) HashSet::new).collect(Collectors.toList());
The Guava solution from #Andrey_chaschev seems the best, but in case it is not possible to use it, I believe the following would help
public static List<Set<String>> partition(Set<String> set, int chunk) {
if(set == null || set.isEmpty() || chunk < 1)
return new ArrayList<>();
List<Set<String>> partitionedList = new ArrayList<>();
double loopsize = Math.ceil((double) set.size() / (double) chunk);
for(int i =0; i < loopsize; i++) {
partitionedList.add(set.stream().skip((long)i * chunk).limit(chunk).collect(Collectors.toSet()));
}
return partitionedList;
}
A very simple way for your actual problem would be to change your code as follows:
Iterator<String> ite = allSymbolsSet.iterator();
System.out.println("=======================");
int i = 500;
while ((--i > 0) && ite.hasNext()) {
A general method would be to use the iterator to take the elements out one by one in a simple loop:
int i = 500;
while ((--i > 0) && ite.hasNext()) {
sublist.add(ite.next());
ite.remove();
}

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.

Given a target sum, find if there is a pair of element in the given array which sums up to it

import java.util.HashMap;
public class target
{
public static void hash(int []a,int sum)
{
HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
int i;
for (i = 0; i < a.length; ++i)
map.put(a[i], sum-a[i]);
for (i = 0; i < a.length; ++i)
if(map.containsValue(a[i]) && map.get(a[i])!=null)
{
System.out.println("("+a[i]+","+map.get(a[i])+")");
map.remove(a[i]);
}
}
public static void main(String[] args)
{
int []a={1, 2, 13, 34, 9, 3, 23, 45, 8, 7, 8, 3, 2};
hash(a,11);
}
}
I want to know if there is a better and more efficient solution that the above one. Complexity of this is n. Can I do better?
Your implementation misses duplicated pairs.
You could
sort the array
iterate from the start and for each element
calculate the required complement (sum - element)
do a reverse binary search (from the end of the sorted array) looking for that precise value
if found, remove both
It boils down to the observation that, with elements sorted:
n1 < n2 < n3 < n4 < n5 < n6
the most likely pairs are coming symmetrically from both ends to the middle. Now, the worst case is still bad, but at least you don't have the hashtable overhead
As I commented, your sollution is not O(N), because the containsValue make a search of all values stored at the HashMap. To solve it, I made a different approach using your solution:
public static void newVersion(int[] a, int sum){
HashMap<Integer, Boolean> map = new HashMap<Integer, Boolean>();
for (int i= 0; i< a.length; i++) {
map.put(sum - a[i], true);
}
for (int i = 0; i < a.length; i++) {
if (map.containsKey(a[i]) && map.get(a[i])) {
System.out.println("("+(sum-a[i])+","+a[i]+")");
map.put(a[i], false);
map.put(sum-a[i], false);
}
}
}
At the first step, it stores the "complement value" of each integer and at the second step it checks if the complement exists. If it exists, mark both pair as used.
This complexity is:
* O(N) for the first looping
* O(N) * (O(1) + O(1)) for the second loop and the containsValue and get.
* Finally: O(N) + O(N) .:. O(N) solution,
I have the following solution for this problem. The time complexity should be O(N) because the HashMap operations put, get and keySet are O(1).
import java.util.HashMap;
import java.util.Map;
/**
* Find a pair of numbers in an array given a target sum
*
*
*/
public class FindNums {
public static void findSumsForTarget(int[] input, int target)
{
// just print it instead of returning
Map<Integer, String> myMap = populateMap(input);
// iterate over key set
for (Integer currKey : myMap.keySet()) {
// find the diff
Integer diff = target - currKey;
// check if diff exists in the map
String diffMapValue = myMap.get(diff);
if(diffMapValue!=null)
{
// sum exists
String output = "Sum of parts for target " + target + " are " + currKey + " and " + diff;
System.out.println(output);
return; // exit; we're done - unless we wanted all the possible pairs and permutations
}
// else
// keep looking
}
System.out.println("No matches found!");
}
private static Map<Integer, String> populateMap(int[] input)
{
Map<Integer,String> myMap = new HashMap<Integer,String>();
for (int i = 0; i < input.length; i++) {
String currInputVal = myMap.get(input[i]);
if(currInputVal!=null) // value already exists
{
// append current index location to value
currInputVal = currInputVal + ", " + i;
// do a put with the updated value
myMap.put(input[i], currInputVal);
}
else
{
myMap.put(input[i], Integer.toString(i)); // first argument is autoboxed to Integer class
}
}
return myMap;
}
// test it out!
public static void main(String[] args)
{
int[] input1 = {2,3,8,12,1,4,7,3,8,22};
int[] input2 = {1,2,3,4,5,6,7,8,9,10};
int[] input3 = {2,-3,8,12,1,4,7,3,8,22};
int target1 = 19;
int target2 = 16;
// test
FindNums.findSumsForTarget(input1, target1);
FindNums.findSumsForTarget(input1, -1);
FindNums.findSumsForTarget(input2, target2);
FindNums.findSumsForTarget(input3, target1);
}
}
import java.util.*;
import java.io.*;
class hashsum
{
public static void main(String arg[])throws IOException
{
HashMap h1=new HashMap();
h1.put("1st",new Integer(10));
h1.put("2nd",new Integer(24));
h1.put("3rd",new Integer(12));
h1.put("4th",new Integer(9));
h1.put("5th",new Integer(43));
h1.put("6th",new Integer(13));
h1.put("7th",new Integer(5));
h1.put("8th",new Integer(32));
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter no.");
int no=Integer.parseInt(br.readLine());
Iterator i=h1.entrySet().iterator();
boolean flag=false;
while(i.hasNext())
{
Map.Entry e1=(Map.Entry)i.next();
Integer n1=(Integer)e1.getValue();
Iterator j=h1.entrySet().iterator();
while(j.hasNext())
{
Map.Entry e2=(Map.Entry)j.next();
Integer n2=(Integer)e2.getValue();
if(no==(n1+n2))
{
System.out.println("Pair of elements:"+n1 +" "+n2);
flag=true;
}
}
}
if(flag==false)
System.out.println("No pairs");
}
}
public static void hash1(int[] a, int num) {
Arrays.sort(a);
// printArray(a);
int top = 0;
int bott = a.length - 1;
while (top < bott) {
while (a[bott] > num)
bott--;
int sum = a[top] + a[bott];
if (sum == num) {
System.out.println("Pair " + a[top] + " " + a[bott]);
top++;
bott--;
}
if (sum < num)
top++;
if (sum > num)
bott--;
}
}
Solution: O(n) time and O(log(n)) space.
public static boolean array_find(Integer[] a, int X)
{
boolean[] b = new boolean[X];
int i;
for (i=0;i<a.length;i++){
int temp = X-a[i];
if(temp >= 0 && temp < X) //make sure you are in the bound or b
b[temp]=true;
}
for (i=0;i<a.length;i++)
if(a[i]<X && b[a[i]]) return true;
return false;
}
Recursively to find the subset whose sum is the targeted sum from given array.
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Main {
public static Set<List<Integer>> set = new HashSet<>();
public static void main(String[] args) {
int[] biggerArray = {1, 2, 1, 1};
int targetedSum = 3;
findSubset(biggerArray, targetedSum);
}
public static void findSubset(int[] biggerArray, int targetedSum) {
for (int i = 0; i < biggerArray.length; i++) {
List<Integer> subset = new ArrayList<>();
if (biggerArray[i] > targetedSum)
continue;
else
subset.add(biggerArray[i]);
if (i + 1 < biggerArray.length)
find(subset, i, biggerArray, targetedSum, i);
}
System.out.println(set);
}
public static List<Integer> find(List<Integer> subset, int startIndex, final int[] biggerArray, final int targetedSum, final int skipIndex) {
if (skipIndex == startIndex) {
find(subset, startIndex + 1, biggerArray, targetedSum, skipIndex);
return null;
}
int subsetSum = findSumOfList(subset);
int remainedSum = targetedSum - subsetSum;
int i = startIndex;
if (remainedSum == 0) {
set.add(subset);
return null;
}
if ((startIndex < biggerArray.length) && (biggerArray[startIndex] == remainedSum)) {
List<Integer> temp = new ArrayList<Integer>(subset);
temp.add(biggerArray[i]);
set.add(temp);
}
else if ((startIndex < biggerArray.length) && (biggerArray[startIndex] < remainedSum)) {
while (i + 1 <= biggerArray.length) {
List<Integer> temp = new ArrayList<Integer>(subset);
if (i != skipIndex) {
temp.add(biggerArray[i]);
find(temp, ++i, biggerArray, targetedSum, skipIndex);
}
else {
i = i + 1;
}
}
}
else if ((startIndex < biggerArray.length) && (biggerArray[startIndex] > remainedSum)) {
find(subset, ++i, biggerArray, targetedSum, skipIndex);
}
return null;
}
public static int findSumOfList(List<Integer> list) {
int i = 0;
for (int j : list) {
i = i + j;
}
return i;
}
}
We need not have two for loops. The match can be detected in the same loop while populating the map it self.
public static void matchingTargetSumPair(int[] input, int target){
Map<Integer, Integer> targetMap = new HashMap<Integer, Integer>();
for(int i=0; i<input.length; i++){
targetMap.put(input[i],target - input[i]);
if(targetMap.containsKey(target - input[i])){
System.out.println("Mathcing Pair: "+(target - input[i])+" , "+input[i]);
}
}
}
public static void main(String[] args) {
int[] targetInput = {1,2,4,5,8,12};
int target = 9;
matchingTargetSumPair(targetInput, target);
}
We can easily find if any pair exists while populating the array itself. Use a hashmap and for every input element, check if sum-input difference element exists in the hashmap or not.
import java.util.*;
class findElementPairSum{
public static void main(String[] args){
Map<Integer, Integer> hm = new HashMap<Integer, Integer>();
Scanner sc = new Scanner(System.in);
System.out.println("Enter the sum key: ");
int sum=sc.nextInt();
for(int i=0; i<10; i++){
int x = sc.nextInt();
if(!hm.containsKey(sum-x)){
hm.put(x, 1);
} else {
System.out.println("Array contains two elements with sum equals to: "+sum);
break;
}
}
}
}

Categories

Resources