Number Format Exception for Folding Method Hash Function [duplicate] - java

This question already has answers here:
What is a NumberFormatException and how can I fix it?
(9 answers)
Closed 6 years ago.
I wrote up a hash function using the folding method so that anagrams i.e. "ape" &"pea" would hash to the same value. So far most strings I put into it work. But on some occasions I get Number Format Exceptions.
For instance when I pass the string "abalone" with a table size of 109 the exception pops up while the string "abalon" does not.
private static int Hash(String theString,int theTableSize){
//ignore case and remove all non-alphanumeric characters
String temp = theString.toLowerCase();
temp = temp.replaceAll("[^a-zA-Z0-9]", "");
//sort to count # and type of characters when hashing, NOT alphabetical order
char[] arr = temp.toCharArray();
Arrays.sort(arr);
temp = new String(arr);
//Folding Method for Hash
String str_A = temp.substring(0, temp.length()/2);
String str_B = temp.substring(temp.length()/2, temp.length());
System.out.println(str_A + " " + str_B );
return (folding(str_A) + folding(str_B)) % theTableSize;
}
private static int folding(String substring){
int x = 0;
for(int i = 0; i < substring.length(); i++){
int tchar = substring.charAt(i);
String schar = Integer.toString(tchar);
System.out.println(schar);
x = Integer.parseInt(x + schar) ;
x = Math.abs(x);
}
return x;
}
Is there something that I am missing?

The problem seems to be the line
x = Integer.parseInt(x + schar);
You're concatenating strings here, so the argument x + schar could well be longer than the maximum size of an int.

A java int is 32 bits. the number you try to parse is 979897108111, which is over 32 bits.

Related

sorting a 24 bits array using bubble sort in Java [duplicate]

This question already has answers here:
What is a debugger and how can it help me diagnose problems?
(2 answers)
Closed 3 years ago.
I'm trying to find a good elegant way to bubble sort a 24 bits input.
it seems I have an issue with my code but I can't figure out the problem.
I'm new to Java, so please be compassionate.
thanks!
public static void sortTriBytes(RandomAccessFile file) throws IOException {
for (long i = 1; i < file.length()/3; i=i+3){
for (long j = 0; j < file.length()-(3*(i-1)); j=j+3){
String leftStr = "";
String rightStr = "";
file.seek(j);
int left1 = file.readUnsignedByte();
int left2 = file.readUnsignedByte();
int left3 = file.readUnsignedByte();
leftStr+= Integer.toBinaryString(left1);
leftStr+=Integer.toBinaryString(left2);
leftStr+=Integer.toBinaryString(left3);
int actualleft = Integer.parseInt(leftStr,2);
int right1 = file.readUnsignedByte();
int right2 = file.readUnsignedByte();
int right3 = file.readUnsignedByte();
rightStr+= Integer.toBinaryString(right1);
rightStr+= Integer.toBinaryString(right2);
rightStr+= Integer.toBinaryString(right3);
int actualright = Integer.parseInt(rightStr,2);
if (actualleft > actualright) {
file.seek(j);
file.write(right1);
file.write(right2);
file.write(right3);
file.write(left1);
file.write(left2);
file.write(left3);
}
}
}
}
thanks again!
There are no leading zeros in a binary string, so your concatenated version will be skewed by varying lengths. For example, "1" + "101" + "1" might look larger than "110" + "1" + "0".
You can neatly pack bytes into a larger word like an int or long using a bit-shift operator (<<) and avoid using strings altogether.
int word = (byte1 << 16) | (byte2 << 8) | byte3;
You can also use math to perform the same operation on unsigned bytes, but bit-shifting does a better job of communicating intent.
int word = byte1 * 256 * 256 + byte2 * 256 + byte3;

Adding zeroes to front and end of an integer - binary output [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I had posted a question yesterday about this program I have been working on but essentially I've programmed an encoder of sorts that takes a string and an integer and then adds to every character within the string the value of the integer and then finally prints the binary of the string assuming 8 bits for every symbol or character. For example ABC with integer(code) 4 should output 01000101 01000110 01000111 (EFG). Now, I've managed to get super close to completing this project but I've run into an issue when converting each character to binary which I assume is due to how I'm actually calculating the binary.
Example: If a binary integer starts with a 0, then obviously I will need to pad the integer with a 0 on the far left. I've managed to do that but there are cases where the integer ends in 0 and I need to do the same thing except on the far right... I'm not sure if I'm making 100% sense but I have posted my code and test result with expected outcome below. As you can see, it converts almost perfectly except the value in the middle (B) adds an extra 2 zeroes instead of just one on the far left and I haven't figured out how to check to add an ending zero. Can someone please help me? How I should go ahead and handle converting to binary(8 bits) from characters?
I also need to figure out how to decode binary into the original message. Example: InputMessage: 01000101 01000110 01000111, InputCode: 4
OriginalMessage: ABC
public class Encoder{
public static void main (String[] args) {
String msg;
int code;
int i;
msg = getMsg();
code = getCode();
getBinaryMsg(getCodedMsg(msg, code));
}
public static String getMsg(){
String msg;
System.out.print("Input message: ");
Scanner input = new Scanner(System.in);
msg = input.nextLine();
return msg;
}
public static int getCode(){
int code=0;
System.out.print("Input Code from 1 - 10: ");
Scanner input = new Scanner(System.in);
return input.nextInt();
}
public static String getCodedMsg(String msg, int code){
int letterOrDigit;
String codedMessage = "";
for(int i = 0; i<= msg.length()-1; i++){
letterOrDigit = msg.charAt(i);
if(Character.isLetter(letterOrDigit)){
letterOrDigit = (char)(msg.charAt(i)+code);
}
if((Character.isLowerCase(msg.charAt(i)) && letterOrDigit > 'z') || (Character.isUpperCase(msg.charAt(i)) && letterOrDigit > 'Z')){
letterOrDigit = (char)(msg.charAt(i) - (26 - code));
}
if(Character.isDigit(letterOrDigit)){
letterOrDigit = (char)(msg.charAt(i)+code);
}
if(Character.isDigit(msg.charAt(i)) && letterOrDigit > '9'){
letterOrDigit = (char)(msg.charAt(i) - (10 - code));
}
codedMessage +=(char)letterOrDigit;
}
return codedMessage;
}
public static void getBinaryMsg(String codedMessage){
char[] strChar = codedMessage.toCharArray();
int character;
int remainder;
int binaryInt;
int revBinInt;
int firstDigit;
String paddedWithZero = "";
String binaryMsg = "";
for(int i = 0; i < strChar.length; i++){
binaryInt = 0;
revBinInt = 0;
firstDigit = 0;
character = strChar[i];
//Calculating 8 binary bits
for(int j = 0; j <= 7; j++){
remainder = character % 2;
binaryInt = binaryInt * 10 + remainder;
character = character / 2;
}
//Reversing the above for loop so that binary is correct
while(binaryInt != 0){
remainder = binaryInt % 10;
revBinInt = revBinInt * 10 + remainder;
binaryInt = binaryInt / 10;
}
firstDigit += revBinInt/(int)(Math.pow(10,(int)Math.log(revBinInt)));
if(firstDigit == 0 && numOfDigits(revBinInt) <= 7){
binaryMsg += String.format("%8s", Integer.toString(revBinInt)).replace(' ', '0') + " ";
}
}
System.out.print(binaryMsg);
}
//Counts the number of digits in case binary number starts or ends in 0
public static int numOfDigits(int number){
int count = 0;
while(number !=0){
number = number/10;
count++;
}
return count;
}
}
Test Result:
Input: ABC, 4
Output: 01000101 00100011 01000111
Expected: 01000101 01000110 01000111
As you say, you were almost done. But the binary encoding wasn't working as expected. Here is my suggestion:
public static void getBinaryMsg(String codedMessage) {
String binary = toBinary(codedMessage);
System.out.println(binary);
}
private static String toBinary(String codedMessage) {
String binary = codedMessage.chars().boxed().map(c -> pad(Integer.toBinaryString(c), 8, '0') + " ").collect(Collectors.joining());
return binary;
}
private static String pad(String s, int n, char c) {
return String.format("%"+n+"s", Integer.parseInt(s)).replace(' ', c);
}
Using Integer.toBinaryString(int i) you don't have to reinvent the wheel. The only thing you have to add is the padding, to get every binary formatted to eight bits. You did it well according to: How to get 0-padded binary representation of an integer in java?
Here's a piece of code that trims zeros on both ends of a binary string:
String s = "00010111110100";
Pattern p = Pattern.compile("(1+[01]*1+)|(1)");
Matcher m = p.matcher(s);
if (m.find()) {
System.out.println(m.group());
}
It uses a regular expression (1+[01]*1+)|(1).
| in the epression means or, so it says (1+[01]*1+) or (1).
In (1+[01]*1+) 1+ means one or more repetitions of 1 and [01]* means 0 or more repetitions or 1 or 0.
(1) means just 1, to handle the case where your string looks like this: 00010000.
Edit: note that you can actually use (1[01]*1)|(1), since [01]* will handle the case of multiple 1's.

compiler error: Array required, but java.lang.String found

So I've looked at "questions that may already have my answer" but, despite getting the same error message as those questions, I think I may have a different issue:
//find greatest product generated by 5 consecutive integers below
class project_euler8 {
public static String numbers =
"73167176531330624919225119674426574742355349194934" +
"96983520312774506326239578318016984801869478851843" +
"85861560789112949495459501737958331952853208805511" +
"12540698747158523863050715693290963295227443043557" +
"66896648950445244523161731856403098711121722383113" +
"62229893423380308135336276614282806444486645238749" +
"30358907296290491560440772390713810515859307960866" +
"70172427121883998797908792274921901699720888093776" +
"65727333001053367881220235421809751254540594752243" +
"52584907711670556013604839586446706324415722155397" +
"53697817977846174064955149290862569321978468622482" +
"83972241375657056057490261407972968652414535100474" +
"82166370484403199890008895243450658541227588666881" +
"16427171479924442928230863465674813919123162824586" +
"17866458359124566529476545682848912883142607690042" +
"24219022671055626321111109370544217506941658960408" +
"07198403850962455444362981230987879927244284909188" +
"84580156166097919133875499200524063689912560717606" +
"05886116467109405077541002256983155200055935729725" +
"71636269561882670428252483600823257530420752963450";
public static int calculateProduct(int[] myArray) {
int product = 1;
for (int i = 0; i < myArray.length; i++) {
product *= myArray[i];
}
return product;
}
public static void main(String[] args) {
//declare biggest_product, temporary array
int biggest_product = 0;
int[] temp = new int[5];
//loop through each sequence of 5 integers
for (int i = 0; i < numbers.length() - 5; i++) {
int remainder = i % 5;
**temp[remainder] = Integer.parseInt(numbers[i]);**
int candidate_product = calculateProduct(temp);
if (candidate_product > biggest_product) {
biggest_product = candidate_product;
}
}
System.out.println("Biggest product is " + biggest_product);
}
The line the compiler doesn't like is bolded above. If I declare my array (temp) within the for loop, will this fix the issue? I'm a bit confused why I can't assign integer values element-wise based on array index...
I know arrays in Java are immutable but, if this were the case, how could I assign values at any point after array declaration?
numbers isn't declared as an array; it is instead a String.
If you wanted to iterate over each character in the String, then that can be accomplished by numbers.charAt(i).
However, since what you're getting back is a char and not a String, you have to convert it appropriately (that is, subtract '0' from your numerical character to normalize it).
Since a char really is an int (with a shorter range), there's no convenience method in Integer to convert from a char to an int, so one has to subtract the char '0' to get a number back.
That solution would look something like this:
temp[remainder] = numbers.charAt(i) - '0';
This means that you have more work to do in changing the signature of your method that accepts an int[], but I leave that as an exercise for the reader.
It looks like you want to extract five digits from i to i+5. You can achieve this with substring method.
Instead of:
temp[remainder] = Integer.parseInt(numbers[i]);
do:
temp[remainder] = Integer.parseInt(numbers.substring(i,i+5));

From random integers to an actual String

This is a code that takes in an array of all the printing characters of the ASCII table. I am trying to make it so that any String message in the form of integers (e.g. String "aba" that is converted 97098097 can be put back into its original String form. 100101101 can be taken and made back into "dee". I've really tried hard with this method but it does not seem to be working, especially when it comes to numbers and such please help me. It is in Java by the way and I am using Eclipse.
public static String IntToString (){
int n = 0;
String message = "";
String message2 = null;
String [] ASCII = {" ","!","\"","#","$","%","&","\'","(",")","*","+",",","-",".","/","0","1","2","3","4","5","6","7","8","9",":",";","<","=",">","?","#","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","[","\\","]","^","_","`","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","{","|","}","~"};
String IntMessage = result.toString();
String firstChar = IntMessage.substring(0,2);
if (IntMessage.substring(0,1)=="1" && IntMessage.length()%3==0)
{
for (int x = (IntMessage.length() % 3 - 3) % 3; x < IntMessage.length()-2; x += 3)
n = Integer.parseInt(IntMessage.substring(Math.max(x, 0), x + 3));
message=message.concat(ASCII[n-31]);
return message;
}
else if (IntMessage.length()%3==2)
message2=ASCII[(Integer.parseInt(firstChar))-31];
for (int x = 2; x < IntMessage.length()-2; x += 3)
n = Integer.parseInt(IntMessage.substring(x, x + 3));
message=message2+=ASCII [n - 31];
return message;
It would seem that your encoding scheme is, er, crazy.
First, you take the ASCII value of a string, then take the character representation of that ASCII value, then store it as a string.
So "abc" => {97, 98, 99} => "979899".
But since you are using ASCII, which can have values of 100 or more, you are padding your ints with 0 if they are under 100:
"abc" => {97, 98, 99} => {"097", "098", "099"} => "097098099"
But you decide to do this only sometimes, because somehow
"aba" => "97098097"
That is, the first "a" is turned into "97", but the last "a" is turned into "097".
I'd say you should fix your encoding scheme first.
Also, these are hopefully not "random integers" because you are trying to turn them into sensible strings. Otherwise a simple mapping such as base64 would easily map any integers to strings, they just might not make much sense.
In fact, they aren't even really integers. You're storing your encoded strings as strings.
public static void main(String[] srgs){
String aaa = "100101101";
String[] a = split(aaa, 3);
String s = "";
for(int i=0;i<a.length;i++){
char c = (char)Integer.parseInt(a[i]);
s += Character.toString(c);
}
System.out.println(s);
}
public static String[] split(String str, int groupIndex){
int strLength = str.length();
int arrayLength = strLength/groupIndex;
String[] splitedArray = new String[strLength/groupIndex];
for(int i=0;i<arrayLength;i++){
String splitedStr = str.substring(0, groupIndex);
str = str.substring(groupIndex, str.length());
arrayLength = str.length();
splitedArray[i] = splitedStr;
}
return splitedArray;
}
The most important is that ASCII string covert to Char value, than turn it to real Character value in the string. The ASCII code length need be fix by 3 can be helpful in this case.

How to concatenate int values in java?

I have the following values:
int a=1;
int b=0;
int c=2;
int d=2;
int e=1;
How do i concatenate these values so that i end up with a String that is 10221;
please note that multiplying a by 10000, b by 1000.....and e by 1 will not working since b=0 and therefore i will lose it when i add the values up.
The easiest (but somewhat dirty) way:
String result = "" + a + b + c + d + e
Edit: I don't recommend this and agree with Jon's comment. Adding those extra empty strings is probably the best compromise between shortness and clarity.
Michael Borgwardt's solution is the best for 5 digits, but if you have variable number of digits, you can use something like this:
public static String concatenateDigits(int... digits) {
StringBuilder sb = new StringBuilder(digits.length);
for (int digit : digits) {
sb.append(digit);
}
return sb.toString();
}
This worked for me.
int i = 14;
int j = 26;
int k = Integer.valueOf(String.valueOf(i) + String.valueOf(j));
System.out.println(k);
It turned out as 1426
just to not forget the format method
String s = String.format("%s%s%s%s%s", a, b, c, d, e);
(%1.1s%1.1s%1.1s%1.1s%1.1s if you only want the first digit of each number...)
Actually,
int result = a * 10000 + b * 1000 + c * 100 + d * 10 + e;
String s = Integer.toString(result);
will work.
Note: this will only work when a is greater than 0 and all of b, c, d and e are in [0, 9]. For example, if b is 15, Michael's method will get you the result you probably want.
How about not using strings at all...
This should work for any number of digits...
int[] nums = {1, 0, 2, 2, 1};
int retval = 0;
for (int digit : nums)
{
retval *= 10;
retval += digit;
}
System.out.println("Return value is: " + retval);
StringBuffer sb = new StringBuffer();
sb.append(a).append(b).append(c)...
Keeping the values as an int is preferred thou, as the other answers show you.
If you multiply b by 1000, you will not lose any of the values. See below for the math.
10000
0
200
20
1
=====
10221
Others have pointed out that multiplying b by 1000 shouldn't cause a problem - but if a were zero, you'd end up losing it. (You'd get a 4 digit string instead of 5.)
Here's an alternative (general purpose) approach - which assumes that all the values are in the range 0-9. (You should quite possibly put in some code to throw an exception if that turns out not to be true, but I've left it out here for simplicity.)
public static String concatenateDigits(int... digits)
{
char[] chars = new char[digits.length];
for (int i = 0; i < digits.length; i++)
{
chars[i] = (char)(digits[i] + '0');
}
return new String(chars);
}
In this case you'd call it with:
String result = concatenateDigits(a, b, c, d, e);
For fun... how NOT to do it ;-)
String s = Arrays.asList(a,b,c,d,e).toString().replaceAll("[\\[\\], ]", "");
Not that anyone would really think of doing it this way in this case - but this illustrates why it's important to give access to certain object members, otherwise API users end up parsing the string representation of your object, and then you're stuck not being able to modify it, or risk breaking their code if you do.
Using Java 8 and higher, you can use the StringJoiner, a very clean and more flexible way (especially if you have a list as input instead of known set of variables a-e):
int a = 1;
int b = 0;
int c = 2;
int d = 2;
int e = 1;
List<Integer> values = Arrays.asList(a, b, c, d, e);
String result = values.stream().map(i -> i.toString()).collect(Collectors.joining());
System.out.println(result);
If you need a separator use:
String result = values.stream().map(i -> i.toString()).collect(Collectors.joining(","));
To get the following result:
1,0,2,2,1
Edit: as LuCio commented, the following code is shorter:
Stream.of(a, b, c, d, e).map(Object::toString).collect(Collectors.joining());
int number =0;
int[] tab = {your numbers}.
for(int i=0; i<tab.length; i++){
number*=10;
number+=tab[i];
}
And you have your concatenated number.
I would suggest converting them to Strings.
StringBuilder concatenated = new StringBuilder();
concatenated.append(a);
concatenated.append(b);
/// etc...
concatenated.append(e);
Then converting back to an Integer:
Integer.valueOf(concatenated.toString());
Use StringBuilder
StringBuilder sb = new StringBuilder(String.valueOf(a));
sb.append(String.valueOf(b));
sb.append(String.valueOf(c));
sb.append(String.valueOf(d));
sb.append(String.valueOf(e));
System.out.print(sb.toString());
People were fretting over what happens when a == 0. Easy fix for that...have a digit before it. :)
int sum = 100000 + a*10000 + b*1000 + c*100 + d*10 + e;
System.out.println(String.valueOf(sum).substring(1));
Biggest drawback: it creates two strings. If that's a big deal, String.format could help.
int sum = a*10000 + b*1000 + c*100 + d*10 + e;
System.out.println(String.format("%05d", sum));
You can Use
String x = a+"" +b +""+ c+""+d+""+ e;
int result = Integer.parseInt(x);
Assuming you start with variables:
int i=12;
int j=12;
This will give output 1212:
System.out.print(i+""+j);
And this will give output 24:
System.out.print(i+j);
Best solutions are already discussed.
For the heck of it, you could do this as well:
Given that you are always dealing with 5 digits,
(new java.util.Formatter().format("%d%d%d%d%d", a,b,c,d,e)).toString()
I am not claiming this is the best way; just adding an alternate way to look at similar situations. :)
NOTE: when you try to use + operator on (string + int) it converts int into strings and
concatnates them !
so you need to convert only one int to string
public class scratch {
public static void main(String[] args){
int a=1;
int b=0;
int c=2;
int d=2;
int e=1;
System.out.println( String.valueOf(a)+b+c+d+e) ;
}
//Here is the simplest way
public class ConcatInteger{
public static void main(String[] args) {
int [] list1={1,2,3};
int [] list2={1,9,6};
String stNum1="";
String stNum2="";
for(int i=0 ; i<3 ;i++){
stNum1=stNum1+Integer.toString(list2[i]); //Concat done with string
}
for(int i=0 ; i<3 ;i++){
stNum2=stNum2+Integer.toString(list1[i]);
}
int sum= Integer.parseInt(stNum1)+Integer.parseInt(stNum2); // Converting string to int
System.out.println(sum);
}
}
Couldn't you just make the numbers strings, concatenate them, and convert the strings to an integer value?
public class joining {
public static void main(String[] args) {
int a=1;
int b=0;
int c=2;
int d=2;
int e=1;
String j = Long.toString(a);
String k = Long.toString(b);
String l = Long.toString(c);
String m = Long.toString(d);
String n = Long.toString(e);
/* String s1=Long.toString(a); // converting long to String
String s2=Long.toString(b);
String s3=s2+s1;
long c=Long.valueOf(s3).longValue(); // converting String to long
*/
System.out.println(j+k+l+m+n);
}
}

Categories

Resources