Is there any way that I can use a hashcode of a string in java, and recreate that string?
e.g. something like this:
String myNewstring = StringUtils.createFromHashCode("Hello World".hashCode());
if (!myNewstring.equals("Hello World"))
System.out.println("Hmm, something went wrong: " + myNewstring);
I say this, because I must turn a string into an integer value, and reconstruct that string from that integer value.
This is impossible. The hash code for String is lossy; many String values will result in the same hash code. An integer has 32 bit positions and each position has two values. There's no way to map even just the 32-character strings (for instance) (each character having lots of possibilities) into 32 bits without collisions. They just won't fit.
If you want to use arbitrary precision arithmetic (say, BigInteger), then you can just take each character as an integer and concatenate them all together. VoilĂ .
No. Multiple Strings can have the same hash code. In theory you could create all the Strings that have have that hash code, but it would be near infinite.
Impossible I'm afraid. Think about it, a hashcode is a long value i.e. 8 bytes. A string maybe less than this but also could be much longer, you cannot squeeze a longer string into 8 bytes without losing something.
The Java hashcode algorithm sums every 8th byte if I remember correctly so you'd lose 7 out of 8 bytes. If your strings are all very short then you could encode them as an int or a long without losing anything.
For example, "1019744689" and "123926772" both have a hashcode of -1727003481. This proves that for any integer, you might get a different result (i.e. reversehashcode(hashcode(string)) != string).
Let's assume the string consists only of letters, digits and punctuation, so there are about 70 possible characters.
log_70{2^32} = 5.22...
This means for any given integer you will find a 5- or 6-character string with this as its hash code. So, retrieving "Hello World": impossible; but "Hello" might work if you're lucky.
You could do something like this:
char[] chars = "String here".toCharArray();
int[] ints = new int[chars.length];
for (int i = 0; i < chars.length; i++) {
ints[i] = (int)chars[i];
}
Then:
char[] chars = new char[ints.length]
for (int i = 0; i < chars.length; i++) {
chars[i] = (char)ints[i];
}
String final = new String(chars);
I have not actually tested this yet... It is just "concept" code.
Related
I am working on the problem to find the next greatest number with the same set of digits.
For this I take a integer value input from the user and I want to convert to char array or int array so that I can access individual digits.
But when I take
int value=09 as the input and convert to char array it gives only 9 as it considers it to be octal value. How can I overcome this ?
it is not possible in java to take the int values with leading zeros.
so for the value with leading zeros take it in string format.
but we can insert zeros
int n=7;
String str=String.format("%04d", n); //4 denotes the size of the string
System.out.println(str); // o/p->0007
It is not possible convert a 09 int value to a String of 9 since the value 09 can not be stored in an int.
int is not capable of storing trailing zeros.
Take this sample.
int foo = Integer.valueOf("09");
System.out.println(foo);
Output
9
So to solve your problem you should get a String from the user, validate it and parse it to an Integer[].
Solution
public Integer[] parseToInteger(String number) {
return Arrays.asList(number.toCharArray())
.stream()
.map(c -> Integer.valueOf(c.toString()))
.toArray(size -> new Integer[size]);
}
Now you have an Array of Integer.
Since leading 0's are dropped from integers there is no reason to support assigning such a value to an int.
If I want to convert 9 to '9' I usually just add '0' to it.
You can also do the following:
char c = Character.forDigit(9,10);
If you have a string of characters, you can do the following:
String str = "09";
List<Character> chrs =
str.chars().mapToObj(a -> Character.valueOf((char) a))
.collect(Collectors.toList());
System.out.println(chrs);
Prints
[0,9]
You are asking how to parse a number starting with a leading zero, but I get the feeling that you are actually on the worng track given the problem you are trying to resolve. So let's take one step backward, and lets make sure I understand your problem correctly.
You say that you have to find the "next greatest number with the same set of digits". So you are playing "Scrabble" with digits, trying to find the smalest number composed with the same digits that is strictly greater to the original number. For example, given the input "09", you would output "90", and for "123", you would output "132". Is that right? Let assume so.
Now, the real challenge here is how to determine the smalest number composed with thise digits that is stricly greater to the original number. Actually, there's a few possible strategies:
Enumerate all possible permutations of those digits, then filter out those that are not strictly greater to the original number, and then, among the remaining values, find the smallest value. That would be a very innefficient strategy, requiring both disproportionate memory and processing power. Please, don't consider this seriously (that is, unless you are actually coding for a Quantum Computer ;) ).
Set a variable to the initial number, then iteratively increment that variable by one until you eventually get a number that is composed of the same digits as the original values. That one might look simple to implement, but it actually hides some complexities (i.e. determining that two numbers are composed from the same digits is not trivial, special handling would be required to avoid endless loop if the initial number is actually the greatest value that can be formed with those digits). Anyway, this strategy would also be rather innefficient, requiring considerable processing power.
Iterate over the digits themselves, and determine exactly which digits have to be swapped/reordered to get the next number. This is actually very simple to implement (I just wrote it in less that 5 minutes), but require some thinking first. The algorithm is O(n log n), where n is the length of the number (in digits). Take a sheet of paper, write example numbers in columns, and try to understand the logic behind it. This is definitely the way to go.
All three strategies have one thing in common: they all require that you work (at some point at least) with digits rather than with the number itself. In the last strategy, you actually never need the actual value itself. You are simply playing Scrabble, with digits rather than letters.
So assuming you indeed want to implement strategy 3, here is what your main method might looks like (I wont expand more on this one, comments should be far enough):
public static void main(String[] args) {
// Read input number and parse it into an array of digit
String inputText = readLineFromUser();
int[] inputDigits = parseToDigits(inputText);
// Determine the next greater number
int[] outputDigits = findNextGreaterNumber(inputDigits);
// Output the resulting value
String outputText = joinDigits(outputDigits);
println(outputText);
}
So here's the point of all this discussion: the parseToDigits method takes a String and return an array of digits (I used int here to keep things simpler, but byte would actually have been enough). So basically, you want to take the characters of the input string, and convert that array to an array of integer, with each position in the output containing the value of the corresponding digit in the input. This can be written in various ways in Java, but I think the most simple would be with a simple for loop:
public static int[] parseToDigits(String input) {
char[] chars = input.toCharArray();
int[] digits = new int[chars.length];
for (int i = 0 ; i < chars.length ; i++)
digits[i] = Character.forDigit(chars[i], 10);
return digits;
}
Note that Character.forDigit(digit, radix) returns the value of character digit in base radix; if digit is not valid for the given base, forDigit returns 0. For simplicity, I'm skipping proper validation checking here. One could consider calling Character.isDigit(digit, radix) first to determine if a digit is acceptable, throwing an exception if it is not.
As to the opposite opperation, joinDigits, it would looks like:
public static String joinDigits(int[] digits) {
char[] chars = new char[digits.length];
for (int i = 0 ; i < digits.length ; i++)
chars[i] = Character.digit(digits[i], 10);
return new String(chars);
}
Hope that helps.
I have a logic requirement, where I need to ensure that a hexadecimal digit string is presented in 8-digit format, even if the leading digits are zero. For example, the string corresponding to 0x3132 should be formatted as "0x00003132".
I tried this:
String key_ip = txt_key.getText();
int addhex = 0;
char [] ch = key_ip.toCharArray ();
StringBuilder builder = new StringBuilder();
for (char c : ch) {
int z = (int) c;
builder.append(Integer.toHexString(z).toUpperCase());
}
System.out.println("\ n (key) is:" + key_ip);
System.out.println("\ nkey in Hex:" + addhex + builder.toString());
, but it gave me an error. Can anyone explain how to fix or rewrite my code for this?
and I want to ask one more thing, if use code
Long.toHexString(blabla);
is it true to change the value "0x00" to "\0030" so that the output of 0 is 30
Evidently, you are receiving a String, converting its chars to their Unicode code values, and forming a String containing the hexadecimal representations of those code values. The problem you want to solve is to left-pad the result with '0' characters so that the total length is not less than eight. In effect, the only parts of the example code that are directly related to the problem itself are
int addhex = 0;
and
System.out.println("\ nkey in Hex:" + addhex + builder.toString());
. Everything else is just setup.
It should be clear, however, that that particular attempt cannot work, because all other considerations aside, you need something that adapts to the un-padded length of the digit string. That computation has no dependency on the length of the digit string at all.
Since you're already accumulating the digit string in a StringBuilder, it seems sensible to apply the needed changes to it, before reading out the result. There are several ways you could approach that, but a pretty simple one would be to just insert() zeroes one at a time until you reach the wanted length:
while (builder.length() < 8) {
builder.insert(0, '0'); // Inserts char '0' at position 0
}
I do suspect, however, that you may have interpreted the problem wrongly. The result you obtain from doing what you ask is ambiguous: in most cases where such padding is necessary, there are several input strings that could produce the same output. I am therefore inclined to guess that what is actually wanted is to pad the digits corresponding to each input character on a per-character basis, so that an input of "12" would yield the result "00310032". This would be motivated by the fact that Java char values are 16 bits wide, and it would produce a transformation that is reliably reversible. If that's what you really want, then you should be able to adapt the approach I've presented to achieve it (though in that case there are easier ways).
if use code
Long.toHexString(blabla);
is it true to change the value "0x00" to "\0030" so that the output of
0 is 30
The Unicode code value for the character '0', expressed in hexadecimal, is 30. Your method of conversion would produce that for the input string "0". Your method does not lend any special significance to the character '\' in its input.
Hiii,I need to do the opposite of what my hash method does, I want a number to convert it to a string, unlike my other method.
I need you to do it in the same way coding as decoding
That would only be possible if there was a 1 to 1 mapping between Strings and longs. Since there are 264 possible long values, and many many more possible String values (even if you limit yourself to Strings of 64 characters, there are still K64 of them, where K is the number of possible unique characters), there cannot be a method that reverses your long hash(String c) method for all possible Strings.
I think that you are trying to implement the Vigenère cipher.
I have fixed your code for executing the two functions (hash and hash2) and I have noticed that hash("javaguay") returns the long number 2485697837967351 and then hash2(2485697837967351L) returns yaugavaj, the reverse string that you want.
A quick response could be the next, but I think you must fix your algorithm.
Add these lines to the end hash2 function:
String res2 = "";
for (int i = res.length() -1; i >=0; i--) {
res2 += res.charAt(i);
}
return res2;
I am making an application that involves a seed to generate a world and some games let you provide that seed with text. I'm wondering how would you 'convert' a string to an integer.
A simple way would be to use the ASCII values of all the characters and append them to a string which you would then parse to an integer, but that severely limits the size of the string. How would you be able to do this with a larger string?
EDIT: 64 bit not 32
I would just call String.hashcode(). The standard String.hashcode() function makes use of all characters in the target string and gives good dispersal.
The only thing I would question is whether 32 bits of seed is going to be enough. It might mean that your world generator could generate at most 232 different worlds.
Random seeds for Random can be at least 48-bit, ideally 64-bit. You can write your own hash code like this.
public static long hashFor(String s) {
long h = 0;
for(int i = 0; i < s.length(); i++)
h = h * 10191 + s.charAt(i);
return h;
}
The Standard way for converting a String to Integer is using Integer.parseInt(String);
You pass the string into this and it would convert the String to int. Try it and let me know!
I can't think of a better way to left pad an integer with zeroes without first converting it to a String. Is there a way to do this? I've found numerous questions regarding this but they all require a String conversion. I understand we can find the length with this approach:
int length = (num==0) ? 1 : (int)Math.log10(num) + 1;
However, this will still require me to convert it to a String and back afterwards. Surely, there's a better way?
No. An int represents a mathematical integer value, represented as 32 bits. The number 0001 is 1, and has a unique binary representation. Left-padded integers are not integers. they are Strings.
No. Numeric types cannot contain leading zeros. This a feature of the formatted textual representation i.e. Strings
Since you already have the length I'm guessing the leading zero's are simply for output, but ultimately your question was answered by the other two posters.
int length = (num==0) ? 1 : (int)Math.log10(num) + 1;
String zeros;
for(int i=0; i<length; i++) {
zeros = zeros.concat("0");
}
System.out.println(zeros + num);