Skip to content

Instantly share code, notes, and snippets.

@janosgyerik
Last active August 29, 2015 14:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save janosgyerik/9bc571fd122767f00f5d to your computer and use it in GitHub Desktop.
Save janosgyerik/9bc571fd122767f00f5d to your computer and use it in GitHub Desktop.

http://codereview.stackexchange.com/questions/83601/finding-the-mth-to-last-element

If I'm interpreting the definition right, the input contains single letters, all delimited by precisely one space character, and at the end of the line is a single digit (1 to 9). This is the way it seems to make the most sense. I will assume this interpretation in my answer.

First, to make the solution testable, I'd extract the main logic to a function that takes a line and returns the mth-to-last character or 0 (that's different from '0', mind you) if m is out of range.

static char retrieveAndPrintMToLast0(String line) {
    String sanitized = line.replaceAll("\\s", "");
    if (!sanitized.isEmpty()) {
        int limit = sanitized.length() - 1;
        int targetIndex = Character.getNumericValue(sanitized.charAt(limit));
        sanitized = sanitized.substring(0, limit);

        if (targetIndex <= limit) {
            return sanitized.charAt(limit - targetIndex);
        }
    }
    return 0;
}

Now it's possible to add some unit tests to verify the behavior:

private char getMthToLast(String line) {
    return MToLast.retrieveAndPrintMToLast(line);
}

@Test
public void test_hello_1() {
    assertEquals('o', getMthToLast("h e l l o 1"));
}

@Test
public void test_hello_5() {
    assertEquals('h', getMthToLast("h e l l o 5"));
}

@Test
public void test_hello_9() {
    assertEquals(0, getMthToLast("h e l l o 9"));
}

With the unit tests covering my back, I can boldly go and refactor the original code:

  • It seems it should be possible to calculate the right position without removing the spaces
    • Removing the spaces doesn't look great in general: it's an extra $O(N)$ operation (though I do realize we're talking about a N that's maximum 9, but still...)
    • Removing the spaces would clearly not have a place in a little bit extended problem where there may be multiple character sequences, not just single letters
  • The sanitized.isEmpty check seems redundant, as that should be illegal input in the challenge

The modified implementation incorporating these ideas:

static char retrieveAndPrintMToLast(String line) {
    int limit = (line.length() - 1) / 2;
    int targetIndex = line.charAt(line.lastIndexOf(' ') + 1) - '0';

    if (targetIndex <= limit) {
        return line.charAt(line.length() - 2 * targetIndex - 1);
    }
    return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment