## Tuesday, September 28, 2010

### Puzzle: Java identity hashcode

Just for fun, I came up with this original (hopefully) puzzle: can you find a Java string whose `hashCode()` is equal to the numeric value that the string "represents"?

Here are some random guesses that fail to solve the puzzle but perhaps convey the idea:
```System.out.println("42".hashCode()); // 1662

System.out.println(
Integer.toBinaryString(
"10101010101010101010101010101010"
.hashCode()
)
);  // 11001111110011111101111111110000

System.out.println(
"Long.MAX_VALUE + Integer.valueOf(666)".hashCode()
==
Long.MAX_VALUE + Integer.valueOf(666)
); // false
```
This is just for fun, so the rules are pretty relaxed. You can use base conversion, expressions, constants, widening conversion, autoboxing, etc. Anything creative is acceptable.

Here's a rather dumb solution that isn't mathematically/algorithmically interesting, using comment to break the circular dependency and unicode escapes to pretty much concoct any number you want.
```System.out.println(
"1337 // \u3902 \u016d \u06b0".hashCode()
==
1337 // \u3902 \u016d \u06b0
); // true
```
Allowing comments really makes this puzzle rather trivial to solve:
```System.out.println(
"Integer.MAX_VALUE // nc7!''\$".hashCode()
==
Integer.MAX_VALUE // nc7!''\$
); // true
```

Here's a more interesting solution that takes advantage of the atrocity that is `Integer.getInteger` (see discussion on stackoverflow).
```System.out.println(
"Integer.getInteger(new String(new char[] { '\u7a11', '\u0000', '\u5238' }), 42)".hashCode()
==
Integer.getInteger(new String(new char[] { '\u7a11', '\u0000', '\u5238' }), 42)
); // true unless system properties is messed with
```
So it's definitely possible to solve this without using comments. This still breaks the circular dependency, though, this time by using a default value for `Integer.getInteger`.

The next step is obvious: try to solve this puzzle without any kind of "cheating".

Well, I don't know what is and isn't cheating anymore, but this breaks the circular dependency by multiplication with 0.
```System.out.println(
"0 * '\u31b1' * '\0' * '\u1167'".hashCode()
==
0 * '\u31b1' * '\0' * '\u1167'
); // true
```
Okay, so perhaps the next step is not to use Unicode escapes, because that really does make things somewhat easier.

#### 4 comments:

1. System.out.println("-2097072302".hashCode() + "-2097072301".hashCode());
System.out.println(-2097072302L + -2097072301L);

2. System.out.println(("43624670".hashCode() - "43624678".hashCode()) == (43624670 - 43624678));

3. Nice attempts, but you have two strings, requiring two hashCode calls for each "solution". A "proper" solution should just be one string with one hashCode call.

4. "2552+2451410".hashCode() == 2552+2451410