This problem screams for recursion. Here's a quick and dirty implementation that introduces a "number" as a string and uses substring()
to use numbers. You can adapt it to use numerical methods to get the first (or first two) decimal digits from an integer if you want.
If you decide to work directly with int
, it would be easier to start at the end (working with the least significant digits) than at the beginning - lastDigit = number % 10; otherDigits = number / 10
lastDigit = number % 10; otherDigits = number / 10
public List<String> encodings(String number) { List<String> out = new ArrayList<>(); addEncodings("", number, out); return out; } private void addEncodings(String prefix, String number, List<String> out) { if (number.length() == 0) { out.add(prefix); } else { addParsingNDigits(1, prefix, number, out); addParsingNDigits(2, prefix, number, out); } } private void addParsingNDigits(int digits, String prefix, String number, List<String> out) { if (number.length() >= digits) { char encodedChar = parseChars(number, digits); if (encodedChar >= 'A' && encodedChar <= 'Z') { addEncodings(prefix + encodedChar, number.substring(digits), out); } } } private char parseChars(String number, int length) { int intVal = Integer.parseInt(number.substring(0, length)); return (char) ('A' + intVal - 1); }
I do not think that your solution will find all possible encodings - I think you need some kind of stack to solve it. The solution above implicitly uses the execution stack due to recursive method calls. Another solution might explicitly put objects representing the "todo" calculations in the stack data structure on the heap:
private static class StackItem { public StackItem(String prefix, String number) { this.prefix = prefix; this.number = number; } public String prefix; public String number; } public List<String> encodings(String number) { List<String> results = new ArrayList<>(); Stack<StackItem> stack = new Stack<>(); stack.push(new StackItem("", number)); while (!stack.isEmpty()) { StackItem current = stack.pop(); if (current.number.equals("")) { results.add(current.prefix); } else { addToStackTakingNChars(2, current, stack); addToStackTakingNChars(1, current, stack); } } return results; } private void addToStackTakingNChars(int n, StackItem current, Stack<StackItem> stack) { if (current.number.length() >= n) { char c = parseChars(current.number, n); if (c >= 'A' && c <= 'Z') { stack.push(new StackItem(current.prefix + c, current.number.substring(n))); } } }
Although "debugging println" is usually a bad habit, it would probably be a good exercise to teach these examples with some println()
to see how it works.