Monday, April 12, 2010

CodingBat string manipulation problems - Appendix

This appendix just has more examples, including one where my first attempt ended in an unreadable disaster.

Octoslash disaster

last2: Given a string, return the count of the number of times that the string consisting of the last 2 characters also appear elsewhere.
public int last2(String str) {
  return str.isEmpty() ? 0
    : str.split(
        "(.)(?=(.).)(?=.*\\1\\2$)",
        -1
      ).length - 1;
}
The above was not my first solution. That would be this one:
public int last2(String str) {
  return str.isEmpty() ? 0
    : str.split(
        str.replaceAll(
          ".*(.)(.)",
          "$1(?=$2)".replaceAll("(\\$.)", "\\\\\\\\Q$1\\\\\\\\E")
        ),
        -1
      ).length - 1 - 1;
}
Note the use of octo-slashes. The inner replaceAll is actually not necessary to pass the available tests, but is required for something like last2("..+++..++").

Basically I wanted to split on "x(?=y)", except that x and y need to be replaced by the last two characters of str. Of course, you also need to quote each character, so I really needed "\Qx\E(?=\Qy\E)". Java language specification for string literals requires that I double the slash; using it in a regex replacement string also requires that you double it; using it twice means doubling it twice. Hence the octo-slashes.

Simply more examples

xyzThere: Return true if the given string contains an appearance of "xyz" not directly preceeded by a period.
public boolean xyzThere(String str) {
  return str.matches(".*(?<!\\.)xyz.*");
}

mixStart: Return true if the given string begins with "mix", except the 'm' can be anything.
public boolean mixStart(String str) {
  return str.matches(".ix.*");
}

notString: Given a string, return a new string where "not " has been added to the front. However, if the string already begins with "not", return the string unchanged.
public String notString(String str) {
  return str.replaceAll("^(?!not)", "not ");
}

delDel: Given a string, if the string "del" appears starting at index 1, return a string where that "del" has been deleted. Otherwise, return the string unchanged.
public String delDel(String str) {
  return str.replaceAll("(?<=^.)del", "");
}

starOut: Return a version of the given string, where for every star in the string, the star and the chars immediately to its left and right are gone.
public String starOut(String str) {
  return str.replaceAll("(.?)\\*+(.?)", "");
}

without2: Given a string, if a length 2 substring appears at both its beginning and end (possibly overlapping), return a string without the substring at the beginning. Otherwise, return the original string unchanged.
public String without2(String str) {
  return str.replaceAll("(?=(^..))(?=.*\\1$)..", "");
}

frontBack: Given a string, return a new string where the first and last chars (if present) have been exchanged.
public String frontBack(String str) {
  return str.replaceAll("(.)(.*)(.)", "$3$2$1"); 
}

backAround: Given a non-empty string, take the last char and return a new string with the last char added at the front and back
public String backAround(String str) {
  return str.replaceAll("(.+)(?<=(.))", "$2$1$2");
}

seeColor: Given a string, if the string begins with "red" or "blue" return that color string; otherwise return the empty string.
public String seeColor(String str) {
  return str.replaceAll("(red|blue)?.*", "$1");
}

No comments:

Post a Comment