I have a class TypesHolder that has four properties which are each int values. I want to identify how many unique combinations of values are in the four int variables, and then to give a count of how many instances of TypesHolder have each specific combination of the four integer variables. How can I accomplish this in code? My code attempt below is failing, with the failed results summarized at the end. There must be a simpler way to do this correctly.
Here is my TypesHolder class:
public class TypesHolder {
private int with;
private int type;
private int reason1;
private int reason2;
//getters and setters
}
To hold the unique combinations during analysis, I created the following TypesSummaryHolder class:
public class TypesSummaryHolder {
private int with;
private int type;
private int reason1;
private int reason2;
private int count;
//getters and setters
}
I then created an ArrayList to store the 15000+ instances of TypesHolder and another ArrayList to store the TypesSummaryHolder objects who represent each of the unique combinations of width, type, reason1, and reason2 from the TypesHolder objects, along with a count variable for each of the unique combinations. I wrote the following code to populate the ArrayList of TypesSummaryHolder objects along with their counts:
#SuppressWarnings("null")
static void countCommunicationTypes(){
int CommunicationWithNumber;int CommunicationTypeNumber;int CommunicationReasonNumber;
int SecondReasonNumber;int counter = 0;
ArrayList<EncounterTypesHolder> types = new ArrayList<EncounterTypesHolder>();
ArrayList<EncounterTypesSummaryHolder> summaries = new ArrayList<EncounterTypesSummaryHolder>();
////////
try {Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");}
catch (ClassNotFoundException e1) {e1.printStackTrace();}
Connection sourceConn = null;
try {sourceConn = DriverManager.getConnection("jdbc:odbc:PIC_NEW_32");}
catch (Exception e1) {e1.printStackTrace();}
Statement st = null;
try {st = sourceConn.createStatement();}
catch (Exception e1) { e1.printStackTrace();}
ResultSet rest = null;
try {
rest = st.executeQuery("SELECT * FROM someTable");
while (rest.next()) {
CommunicationWithNumber = rest.getInt(3);
CommunicationTypeNumber = rest.getInt(5);
CommunicationReasonNumber = rest.getInt(6);
SecondReasonNumber = rest.getInt(6);
EncounterTypesHolder etype = new EncounterTypesHolder();
etype.setWith(CommunicationWithNumber);
etype.setType(CommunicationTypeNumber);
etype.setReason1(CommunicationReasonNumber);
etype.setReason2(SecondReasonNumber);
if(!isDuplicateType(etype,types)){
EncounterTypesSummaryHolder summaryholder = new EncounterTypesSummaryHolder();
summaryholder.setWith(CommunicationWithNumber);
summaryholder.setType(CommunicationTypeNumber);
summaryholder.setReason1(CommunicationReasonNumber);
summaryholder.setReason2(SecondReasonNumber);
summaryholder.setCount(1);
summaries.add(summaryholder);
} else {
EncounterTypesSummaryHolder summaryholder = new EncounterTypesSummaryHolder();
summaryholder.setWith(etype.getWith());
summaryholder.setType(etype.getType());
summaryholder.setReason1(etype.getReason1());
summaryholder.setReason2(etype.getReason2());
if(isDuplicateSummaryType(summaryholder, summaries)){
for(int u = 0; u<summaries.size();u++){
if((CommunicationWithNumber==summaries.get(u).getWith()) && (CommunicationTypeNumber==summaries.get(u).getType()) && (CommunicationReasonNumber==summaries.get(u).getReason1()) && (SecondReasonNumber==summaries.get(u).getReason2()) ){
int oldcount = summaries.get(u).getCount();
int newcount = oldcount+1;
summaries.get(u).setCount(newcount);
}
}
}else {
summaryholder.setCount(1);
summaries.add(summaryholder);
}
}
types.add(etype);
counter += 1;
System.out.println("counter is: "+counter);
System.out.println("summaries.size() is: "+summaries.size());
}
} catch (Exception e) {e.printStackTrace();}
System.out.println("at end: counter is: "+counter);
System.out.println("at end: types.size() is: "+types.size());
System.out.println("at end: summaries.size() is: "+summaries.size());
int total = 0;
for(int r=0;r<summaries.size();r++){
total += summaries.get(r).getCount();
int with = summaries.get(r).getWith();int type = summaries.get(r).getType();int reason1 = summaries.get(r).getReason1();int reason2 = summaries.get(r).getReason2();int thiscount = summaries.get(r).getCount();
}
System.out.println("total is: "+total);
}
static boolean isDuplicateType(EncounterTypesHolder testType, ArrayList<EncounterTypesHolder> types){
for(int j = 0; j<types.size(); j++){
if( (testType.getWith() == types.get(j).getWith()) && (testType.getType() == types.get(j).getType()) && (testType.getReason1() == types.get(j).getReason1()) && (testType.getReason2() == types.get(j).getReason2())){
System.out.println("=====TRUE!!====");
return true;
}
}
return false;
}
static boolean isDuplicateSummaryType(EncounterTypesSummaryHolder testType, ArrayList<EncounterTypesSummaryHolder> types){
for(int j = 0; j<types.size(); j++){
if( (testType.getWith() == types.get(j).getWith()) && (testType.getType() == types.get(j).getType()) && (testType.getReason1() == types.get(j).getReason1()) && (testType.getReason2() == types.get(j).getReason2())){
System.out.println("=====TRUE!!====");
return true;
}
}
return false;
}
The code above is producing the following SYSO output at the end:
at end: counter is: 15415
at end: types.size() is: 15415
at end: summaries.size() is: 15084
total is: 2343089
The max possible value for summaries.size() should be around 600, but the 331 you get from types.size() minus summaries.size() above is within the range of believable values for summaries.size(). However, the value for total should be equal to the 15414 value of types.size(). What is wrong with my code above? How can I change my code above to get both a list of the unique combinations of with, type, reason1, and reason2, and also a count of the number of instances with each of those unique value combinations?
If I understand you right, you could add hashcode() and equals() methods to to TypesHolder, then add all your values to a Set<TypesHolder> of some sort. Then just count the total objects (call size()) in the set to get the number of unique combinations.
Here's a link to implementing hashcode() and equals() from SO, if you're not familiar with those methods. Google is your friend.
Related
enter image description hereI have a String named as Price. I take values of Price from the firebase database. I want to make sum of these String Values and make a total Price. The Value of Price increases automatically according to the child in the database. For example the values are 100, 70, 50, 20, 40 etc. And it will increase accordingly.
I think there should be a loop to make the sum of all these values to make it total price.
This is what i have done so far.
int pos = 0;
JSONObject jsonObject = new JSONObject();
if (jsonObject.has(Integer.toString(pos))) {
} else {
try {
jsonObject.put(Integer.toString(pos),Price);
} catch (JSONException e) {
e.printStackTrace();
}
}
for (int i = 0; i < jsonObj.length(); i++) {
try {
String itemInArray = jsonObj.getString(String.valueOf(i));
int Sum = 0;
int totalPrice = sum + itemInArray;
} catch (JSONException e) {
e.printStackTrace();
}
}
But The code is not working. Please any help would be appreciated.
Let's isolate the part of the code where is the problem of Summing numerous String Values Using Loop.
for (int i = 0; i < jsonObj.length(); i++) {
try {
String itemInArray = jsonObj.getString(String.valueOf(i));
int Sum = 0;
int totalPrice = sum + itemInArray;
} catch (JSONException e) {
e.printStackTrace();
}
}
Every time you loop through this code you reassign the value of 0 to Sum and as a result totalPrices value is always 0 plus the itemInArray (which, another problem, is a String and cannot be directly added to an integer).
Assuming everything else is right and itemInArray holds a numeric value here is the code to find the total price:
try{
int sum = 0; // you don't need the totalPrice variable, they will hold the same result
for (int i=0;i<jsonObj.length(); i++) {
String itemInArray = jsonObj.getString(String.valueOf(i));
int itemPrice = Integer.ParseInt(itemInArray);
sum = sum + itemPrice;
}
}catch (JSONException e) {
e.printStackTrace();
}
Now the sum is not redefined in every loop, it keeps its value from the previous loop and it adds itself and itemPrice in the next iteration.
This is school work.
I'm given the problem of finding the private keys of both parties in a DH exchange. The numbers involved in the tests aren't big enough and the task is basically brute-force.
In the task, I can get the prime p, generator g and Alice's public key A.
I'm also given the methods to encrypt a message and decrypt a message with a custom key.
Right now I've only gotten a by simply looping through integers i=1...p and checking if g^i mod p == g^A mod p and promptly returning the first value that meets the requirement.
However, my solution isn't always true according to automated tests.
Anyone know how or even if it's possible to fins a and b with the given info?
Thanks to a third party, I managed to crack the DH code:
public Integer crackAlice() {
// TODO
Integer alicePrivate = 0;
int p = session.getP();
int g = session.getG();
int A = session.getAlicesPublicKey();
// A = g^a mod p
System.out.println("Alice public A: "+A);
String message = String.valueOf(156215);
for (int i = 1; i < p; i++) {
if (BigInteger.valueOf(g).pow(i).mod(BigInteger.valueOf(p)).equals(BigInteger.valueOf(A))) {
//System.out.println("\t\t\t\t"+BigInteger.valueOf(g).pow(i));
alicePrivate = i;
System.out.println("Potential Alice private a: "+i);
//break;
}
}
return alicePrivate;
}
and
public Integer crackBob() {
// TODO
Integer bobPrivate = 0;
Integer a = crackAlice();
int p = session.getP();
int g = session.getG();
int A = session.getAlicesPublicKey();
String mainMessage = "teade";
String msg = null;
try {
msg = session.getEncrypted(mainMessage);
} catch (Exception e) {
e.printStackTrace();
}
for (int i = 1; i < p; i++) {
int ai = a*i;
int Ai = A*i;
//System.out.println("a*b = "+ai);
BigInteger bigintP = BigInteger.valueOf(p);
if (((BigInteger.valueOf(g).pow(a).mod(bigintP)).pow(i)).mod(bigintP)
.equals(((BigInteger.valueOf(g).pow(i).mod(bigintP)).pow(a)).mod(bigintP))) {
String decrypt = null;
try {
decrypt = session.getDecryptedWithCustomKey(msg, BigInteger.valueOf(g).pow(a*i).mod(bigintP).intValue());
} catch (Exception e) {
e.printStackTrace();
}
if (decrypt != null && decrypt.trim().equals(mainMessage)) {
bobPrivate = i;
break;
}
}
}
return bobPrivate;
}
I hope this will help out other with a similar problem.
Having a String representation of a number(no decimals), what's the best way to convert it to either one of java.lang.Integer or java.lang.Long or java.math.BigInteger? The only condition is that the converted type should be of minimal datatype required to hold the number.
I've this current implementation that works fine, but I would like to know if there's a better code without exception handling.
package com.stackoverflow.programmer;
import java.math.BigInteger;
public class Test {
public static void main(String[] args) {
String number = "-12121111111111111";
Number numberObject = null;
try {
numberObject = Integer.valueOf(number);
} catch (NumberFormatException nfe) {
System.out.println("Number will not fit into Integer type. Trying Long...");
try {
numberObject = Long.valueOf(number);
} catch (NumberFormatException nfeb) {
System.out.println("Number will not fit into Long type. Trying BigInteger...");
numberObject = new BigInteger(number);
}
}
System.out.println(numberObject.getClass() + " : "
+ numberObject.toString());
}
}
From what you said, here is what I would have done:
import java.math.BigInteger;
import java.util.Arrays;
import java.util.List;
public class TestSO09_39463168_StringToMinimalNumber {
public static void main(String[] args) {
List<String> strNumbers = Arrays.asList("0", //int
"123", //int
"-456", //int
"2147483700", // Long
"-2147483700", // Long
"9223372036854775900", //BigInt
"-9223372036854775900" //BigInt
);
for(String strNumber : strNumbers){
Number number = stringToMinimalNumber(strNumber);
System.out.println("The string '"+strNumber+"' is a "+number.getClass());
}
}
public static Number stringToMinimalNumber(String s){
BigInteger tempNumber = new BigInteger(s);
if(tempNumber.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0 || tempNumber.compareTo(BigInteger.valueOf(Long.MIN_VALUE)) < 0){
return tempNumber;
} else if(tempNumber.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0 || tempNumber.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) < 0){
return tempNumber.longValue(); //Autobox to Long
} else {
return tempNumber.intValue(); //Autobox to Integer
}
}
}
You must use a temporary BigInteger, or else you'll end up with lazarov's solution, which is correct, but you can't really do something like that for reason mentionned in the comments.
Anyway, every BigInteger (the ones that are not returned) will be garbage collected. As for autoboxing, I don't think it's that of a bad thing. You could also make "BigInteger.valueOf(Long.MAX_VALUE))" as a constant. Maybe the compiler or the JVM will do this on its own.
I'm not really sure of how efficient it is, and using only BigInteger might be a good idea (as Spotted did), because I serioulsy doubt it would really improve the rest of your code to use the right size, and it might even be error prone if you try to use these Numbers with each other ... But again, it all depend on what you need. (and yes, using Exception as flow control is a really bad idea, but you can add a try catch on the BigInteger tempNumber = new BigInteger(s); to throw your own exception if s is not a number at all)
For recreational purpose, I have made the solution without using a BigInteger, and only with String parsing (this is still not what I recommand to do, but it was fun :)
public static final String INT_MAX_VALUE = "2147483647";
public static final String LONG_MAX_VALUE = "9223372036854775807";
public static Number stringToMinimalNumberWithoutBigInteger(String numberStr){
//Removing the minus sign to test the value
String s = (numberStr.startsWith("-") ? numberStr.substring(1,numberStr.length()) : numberStr);
if(compareStringNumber(s, LONG_MAX_VALUE) > 0){
return new BigInteger(numberStr);
} else if(compareStringNumber(s, INT_MAX_VALUE) > 0){
return new Long(numberStr);
} else {
return new Integer(numberStr);
}
}
//return postive if a > b, negative if a < b, 0 if equals;
private static int compareStringNumber(String a, String b){
if(a.length() != b.length()){
return a.length() - b.length();
}
for(int i = 0; i < a.length(); i++){
if( a.codePointAt(i) != b.codePointAt(i) ){ //Or charAt()
return a.codePointAt(i) - b.codePointAt(i);
}
}
return 0;
}
Please don't use exceptions for handling flow control, this is a serious anti-pattern (also here).
As you mentionned in the comments, the real thing you've been asked is to convert a List<String> into a List<Number>.
Also, if I understand correctly, you know that:
You should encounter only numbers without decimals
The biggest value you can encounter is possibly unbound
Based on that, the following method will do the job in a more clever way:
private static List<Number> toNumbers(List<String> strings) {
return strings.stream()
.map(BigInteger::new)
.collect(Collectors.toList());
}
Eidt: if you're not very familiar with the stream concept, here's the equivalent code without streams:
private static List<Number> toNumbers(List<String> strings) {
List<Number> numbers = new ArrayList<>();
for (String s : strings) {
numbers.add(new BigInteger(s));
}
return numbers;
}
Well if you want to do it "by hand" try something like this:
We define the max values as strings :
String intMax = "2147483647";
String longMax = "9223372036854775807";
and our number:
String ourNumber = "1234567890"
Now our logic will be simple :
We will check lenghts of strings firstly
If our numbers length < int max length : IT IS INT
If our numbers length == int max length : Check is it INT or LONG
If our numbers length > int max length :
3.1 If our numbers length < long max length : IT IS LONG
3.2 If our numbers length == long max length : Check is it LONG or BIG INTEGER
3.3 If our numbers length > long max length : IT IS BIG INTEGER
The code should look something like this (I have not tried to compile it may have syntax or other errors) :
if(ourNumber.lenght() < intMax.length ){
System.out.println("It is an Integer");
} else if(ourNumber.lenght() == intMax.length){
// it can be int if the number is between 2000000000 and 2147483647
char[] ourNumberToCharArray = ourNumber.toCharArray();
char[] intMaxToCharArray = intMax.toCharArray();
int diff = 0;
for(int i = 0; i < ourNumberToCharArray.length; i++) {
diff = Character.getNumericValue(intMaxToCharArray[i]) - Character.getNumericValue(ourNumberToCharArray[i]);
if(diff > 0) {
System.out.println("It is a Long");
break;
} else if(diff < 0) {
System.out.println("It is an Integer");
break;
}
}
if(diff == 0){
System.out.println("It is an Integer");
}
} else {
if(ourNumber.lenght() < longMax.length()) {
System.out.println("It is a Long");
} else if(ourNumber.lenght() == longMax.length()){
char[] ourNumberToCharArray = ourNumber.toCharArray();
char[] longMaxToCharArray = longMax.toCharArray();
int diff = 0;
for(int i = 0; i < ourNumberToCharArray.length; i++) {
diff = Character.getNumericValue(longMaxToCharArray[i]) - Character.getNumericValue(ourNumberToCharArray[i]);
if(diff > 0) {
System.out.println("It is a BigInteger");
break;
} else if(diff < 0) {
System.out.println("It is a Long");
break;
}
}
if(diff == 0){
System.out.println("It is a Long");
}
} else {
System.out.println("It is a BigInteger");
}
}
Then logic that checks if the numbers match or not is the same in both cases you can but it in a function for example.
I'm trying to implement a dictionary with a hash table (not using Java's provided hash table classes, but rather made from scratch). Below is the find() method from my Dictionary class, used to detect whether or not a key is in the table when inserting/removing. If the key is already in the table, it returns a score associated with the key (elements in the table are inserted as pairs of key/score into LinkedLists in each table position). If not, it returns -1.
I am running a supplied test program to determine if my Dictionary class works, but I am encountering a NullPointerException when reaching a certain point. Included below is the particular test. Why would this exception be coming up? (I can provide more code if needed!)
Find:
public int find(String config) {
for (int i = 0; i < dictSize; i++) {
if (dict[i] != null) {
LinkedList<DictEntry> current = dict[i];
String currentConfig = current.peek().getConfig(); //Dictionary.java:66
if (currentConfig.equals(config)) {
int currentScore = current.peek().getScore();
return currentScore;
}
}
}
return -1;
}
Insert:
public int insert(DictEntry pair) throws DictionaryException {
String entryConfig = pair.getConfig();
int found = find(entryConfig); //Dictionary.java:27
if (found != -1) {
throw new DictionaryException("Pair already in dictionary.");
}
int entryPosition = hash(entryConfig);
if (dict[entryPosition] == null) { //Dictionary.java:35
LinkedList<DictEntry> list = new LinkedList<DictEntry>();
dict[entryPosition] = list;
list.add(pair);
return 0;
} else {
LinkedList<DictEntry> list = dict[entryPosition];
list.addLast(pair);
return 1;
}
}
The test:
// Test 7: insert 10000 different values into the Dictionary
// NOTE: Dictionary is of size 9901
try {
for (int i = 0; i < 10000; ++i) {
s = (new Integer(i)).toString();
for (int j = 0; j < 5; ++j) s += s;
collisions += dict.insert(new DictEntry(s,i)); //TestDict.java:69
}
System.out.println(" Test 7 succeeded");
} catch (DictionaryException e) {
System.out.println("***Test 7 failed");
}
Exception stack trace:
Exception in thread "main" java.lang.NullPointerException
at Dictionary.find(Dictionary.java:66)
at Dictionary.insert(Dictionary.java:27)
at TestDict.main(TestDict.java:69)
peek() returns null that's why. You can have a nullity check prior to getConfig() call.
I have an algorithm that recursively makes change in the following manner:
public static int makeChange(int amount, int currentCoin) {
//if amount = zero, we are at the bottom of a successful recursion
if (amount == 0){
//return 1 to add this successful solution
return 1;
//check to see if we went too far
}else if(amount < 0){
//don't count this try if we went too far
return 0;
//if we have exhausted our list of coin values
}else if(currentCoin < 0){
return 0;
}else{
int firstWay = makeChange(amount, currentCoin-1);
int secondWay = makeChange(amount - availableCoins[currentCoin], currentCoin);
return firstWay + secondWay;
}
}
However, I'd like to add the capability to store or print each combination as they successfully return. I'm having a bit of a hard time wrapping my head around how to do this. The original algorithm was pretty easy, but now I am frustrated. Any suggestions?
CB
Without getting into the specifics of your code, one pattern is to carry a mutable container for your results in the arguments
public static int makeChange(int amount, int currentCoin, List<Integer>results) {
// ....
if (valid_result) {
results.add(result);
makeChange(...);
}
// ....
}
And call the function like this
List<Integer> results = new LinkedList<Integer>();
makeChange(amount, currentCoin, results);
// after makeChange has executed your results are saved in the variable "results"
I don't understand logic or purpose of above code but this is how you can have each combination stored and then printed.
public class MakeChange {
private static int[] availableCoins = {
1, 2, 5, 10, 20, 25, 50, 100 };
public static void main(String[] args) {
Collection<CombinationResult> results = makeChange(5, 7);
for (CombinationResult r : results) {
System.out.println(
"firstWay=" + r.getFirstWay() + " : secondWay="
+ r.getSecondWay() + " --- Sum=" + r.getSum());
}
}
public static class CombinationResult {
int firstWay;
int secondWay;
CombinationResult(int firstWay, int secondWay) {
this.firstWay = firstWay;
this.secondWay = secondWay;
}
public int getFirstWay() {
return this.firstWay;
}
public int getSecondWay() {
return this.secondWay;
}
public int getSum() {
return this.firstWay + this.secondWay;
}
public boolean equals(Object o) {
boolean flag = false;
if (o instanceof CombinationResult) {
CombinationResult r = (CombinationResult) o;
flag = this.firstWay == r.firstWay
&& this.secondWay == r.secondWay;
}
return flag;
}
public int hashCode() {
return this.firstWay + this.secondWay;
}
}
public static Collection<CombinationResult> makeChange(
int amount, int currentCoin) {
Collection<CombinationResult> results =
new ArrayList<CombinationResult>();
makeChange(amount, currentCoin, results);
return results;
}
public static int makeChange(int amount, int currentCoin,
Collection<CombinationResult> results) {
// if amount = zero, we are at the bottom of a successful recursion
if (amount == 0) {
// return 1 to add this successful solution
return 1;
// check to see if we went too far
} else if (amount < 0) {
// don't count this try if we went too far
return 0;
// if we have exhausted our list of coin values
} else if (currentCoin < 0) {
return 0;
} else {
int firstWay = makeChange(
amount, currentCoin - 1, results);
int secondWay = makeChange(
amount - availableCoins[currentCoin],
currentCoin, results);
CombinationResult resultEntry = new CombinationResult(
firstWay, secondWay);
results.add(resultEntry);
return firstWay + secondWay;
}
}
}
I used the following:
/**
* This is a recursive method that calculates and displays the combinations of the coins included in
* coinAmounts that sum to amountToBeChanged.
*
* #param coinsUsed is a list of each coin used so far in the total. If this branch is successful, we will add another coin on it.
* #param largestCoinUsed is used in the recursion to indicate at which coin we should start trying to add additional ones.
* #param amountSoFar is used in the recursion to indicate what sum we are currently at.
* #param amountToChange is the original amount that we are making change for.
* #return the number of successful attempts that this branch has calculated.
*/private static int change(List<Integer> coinsUsed, Integer currentCoin, Integer amountSoFar, Integer amountToChange)
{
//if last added coin took us to the correct sum, we have a winner!
if (amountSoFar == amountToChange)
{
//output
System.out.print("Change for "+amountToChange+" = ");
//run through the list of coins that we have and display each.
for(Integer count: coinsUsed){
System.out.print(count + " ");
}
System.out.println();
//pass this back to be tallied
return 1;
}
/*
* Check to see if we overshot the amountToBeChanged
*/
if (amountSoFar > amountToChange)
{
//this branch was unsuccessful
return 0;
}
//this holds the sum of the branches that we send below it
int successes=0;
// Pass through each coin to be used
for (Integer coin:coinAmounts)
{
//we only want to work on currentCoin and the coins after it
if (coin >= currentCoin)
{
//copy the list so we can branch from it
List<Integer> copyOfCoinsUsed = new ArrayList<Integer>(coinsUsed);
//add on one of our current coins
copyOfCoinsUsed.add(coin);
//branch and then collect successful attempts
successes += change(copyOfCoinsUsed, coin, amountSoFar + coin, amountToChange);
}
}
//pass back the current
return successes;
}