Wednesday, June 23, 2010

Regex insanity

Now the most insane regex I've written:
String[] tests = {
   "APPLE juice; APPLE cream; APPLE pie; ORANGE sherbet; ORANGE punch; ",
   "APPLE juice; ORANGE punch; ",
   "APPLE juice; ORANGE punch; ORANGE sherbet; ",
   "APPLE juice; ORANGE punch; LEMON pie; ",
   "APPLE juice; APPLE pie; APPLE cream; ",
   "Tommy eats; Tommy sleeps; Tommy drinks; Jamie tosses; Jamie turns; Amy blinks; "
};
for (String test : tests) {         
   System.out.println(test.replaceAll(
      "(?<=^(?=.*\\b(\\w+) \\w+; \\G).*)?(?:\\1 |(\\w+ ))(\\w+; )",
      "$2$3"
   ));
}
This prints, believe it or not:
APPLE juice; cream; pie; ORANGE sherbet; punch; 
APPLE juice; ORANGE punch; 
APPLE juice; ORANGE punch; sherbet; 
APPLE juice; ORANGE punch; LEMON pie; 
APPLE juice; pie; cream; 
Tommy eats; sleeps; drinks; Jamie tosses; turns; Amy blinks; 
It'll be fun to go back to this, say oh, five years from now, and try to figure out what's going on here...

Sunday, June 20, 2010

Using regex to replace a digit with that many number of zeroes

This was an illustrative example I concocted to answer a stackoverflow question.

The problem: using one String.replaceAll, replace each digit with that many number of zeroes.
See also: [stackoverflow] -- Regex: how can I replace $n with n instances of a string?

It's not pretty, but this can in fact be done (see on ideone.com):
// meta-regexing to generate the regex and replacement string
String seq = "123456789";
String regex = "(?x)\n" + seq.replaceAll(".", "(?=[$0-9].*(0)\\$)?\n") + "[0-9]";
String repl = seq.replaceAll(".", "\\$$0");

// let's see what they look like!  
System.out.println(repl);
// $1$2$3$4$5$6$7$8$9
System.out.println(regex);
// (?x)
// (?=[1-9].*(0)$)?
// (?=[2-9].*(0)$)?
// (?=[3-9].*(0)$)?
// (?=[4-9].*(0)$)?
// (?=[5-9].*(0)$)?
// (?=[6-9].*(0)$)?
// (?=[7-9].*(0)$)?
// (?=[8-9].*(0)$)?
// (?=[9-9].*(0)$)?
// [0-9]

String input = "3 2 0 4 x 11 9";
System.out.println(
 (input + "0").replaceAll(regex, repl)
);
// 000 00  0000 x 00 000000000
// it works!  

Here's a bonus snippet that shows the same technique, applied differently (see also on ideone.com):
String seq = "123456789";
String regex = seq.replaceAll(".", "(?=[$0-9]([a-z]))?") + "[0-9][a-z]";
String repl = seq.replaceAll(".", "\\$$0");

String input = "3a 2b 0c 4d 5x";
System.out.println(input.replaceAll(regex, repl));
// aaa bb  dddd xxxxx

Sunday, June 13, 2010

[TF005] Widening primitive conversion doesn't lose any information (true/false?)

(true/false?) The reason why Java doesn't let you assign a double value to a long variable without an explicit narrowing conversion is because some information may be lost during the conversion. Conversely, the reason why Java lets you assign a long value to a double variable without an explicit widening conversion is because no information is ever lost during the conversion.

Friday, June 4, 2010

My first Eclipse bug

I filed my first Eclipse bug recently:

Bug 314830 - [JDT/core/compiler]
Switching on a null expression doesn't always throw NullPointerException
.

The person to which this bug is assigned made no mentions about it being specific to any version, so presumably this affects all current versions of Eclipse.

The essence of the bug is that due to overly aggressive optimizations on the part of Eclipse compiler, the following code does not throw NullPointerException.
java.math.RoundingMode x = null;
switch(x) {};

switch((Integer) null) {};

switch((Character) null) {
   default: System.out.println("I've got sunshine!");
}
This is a violation of JLS 14.11 The Switch Statement.
SwitchStatement:
        switch ( Expression ) SwitchBlock

When the switch statement is executed, first the Expression is evaluated. If it evaluates to null, a NullPointerException is thrown and the entire switch statement completes abruptly for that reason.

See also: stackoverflow.com - Eclipse bug? Switching on a null with only default case