Я пытаюсь решить проблему с номером телефона, используя Java и Python. Код, который я написал, можно найти ниже.
Учитывая цифру и переменную длины, возвращает список номеров, которые будут сгенерированы с клавиатуры телефона.
Пример: f (4, 3) вернется [474, 454, 478, 414, 412, 458, 456, 452,
Это то, что я пробовал до сих пор (на Java):
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class PhonePadExercise {
public static void main(String[] args) {
Integer selectedDigit = 4;
Integer maxIteration = 4;
PhonePadNumberGenerator generator = new PhonePadNumberGenerator();
List<List<Integer>> result = generator.findUniqueNumberFromPhonePad(selectedDigit, maxIteration);
System.out.println(result);
}
}
class PhonePadNumberGenerator {
private List<List<Integer>> result = new ArrayList<>();
private List<Integer> subresult = new ArrayList<>();
private Map<DirectionEnum, DirectionEnum> opposites = new HashMap<>();
private List<PhonePadWithDirection> phonePadWithDirectionList = new ArrayList<>();
public PhonePadNumberGenerator() {
initPad();
initOpposites();
}
private static Map<DirectionEnum, Integer> createMap(Integer up, Integer down, Integer left, Integer right) {
return new HashMap<DirectionEnum, Integer>() {
{
put(DirectionEnum.UP, up);
put(DirectionEnum.DOWN, down);
put(DirectionEnum.LEFT, left);
put(DirectionEnum.RIGHT, right);
}
};
}
private void initPad() {
phonePadWithDirectionList.add(new PhonePadWithDirection(0, createMap(8, null, null, null)));
phonePadWithDirectionList.add(new PhonePadWithDirection(1, createMap(null, 4, null, 2)));
phonePadWithDirectionList.add(new PhonePadWithDirection(2, createMap(null, 5, 1, 3)));
phonePadWithDirectionList.add(new PhonePadWithDirection(3, createMap(null, 6, 2, null)));
phonePadWithDirectionList.add(new PhonePadWithDirection(4, createMap(1, 7, null, 5)));
phonePadWithDirectionList.add(new PhonePadWithDirection(5, createMap(2, 8, 4, 6)));
phonePadWithDirectionList.add(new PhonePadWithDirection(6, createMap(3, 5, 9, null)));
phonePadWithDirectionList.add(new PhonePadWithDirection(7, createMap(4, null, null, 8)));
phonePadWithDirectionList.add(new PhonePadWithDirection(8, createMap(5, 0, 7, 9)));
phonePadWithDirectionList.add(new PhonePadWithDirection(9, createMap(6, null, 8, null)));
}
private void initOpposites() {
opposites.put(DirectionEnum.UP, DirectionEnum.DOWN);
opposites.put(DirectionEnum.DOWN, DirectionEnum.UP);
opposites.put(DirectionEnum.LEFT, DirectionEnum.RIGHT);
opposites.put(DirectionEnum.RIGHT, DirectionEnum.LEFT);
}
public List<List<Integer>> findUniqueNumberFromPhonePad(Integer selectedDigit, Integer maxIteration) {
PhonePadWithDirection pad = phonePadWithDirectionList.get(selectedDigit);
for (DirectionEnum direction : DirectionEnum.values()) {
subresult.add(pad.getNumber());
recursivelyFindPath(pad, direction, maxIteration);
result.add(subresult);
subresult = new ArrayList<>();
}
// remove subresult which doesn't fulfil max iteration (which contains less elements) //java 8 solution
result.removeIf(r -> r.size() < maxIteration);
return result;
}
private void recursivelyFindPath(PhonePadWithDirection pad, DirectionEnum directionEnum, Integer maxIteration) {
if (subresult.size() < maxIteration) {
System.out.printf("With Number %d and New Direction %s%n", pad.getNumber(), directionEnum.name());
Integer valueAtNewDirection = pad.getValue(directionEnum);
if (valueAtNewDirection != null) {
PhonePadWithDirection newPad = phonePadWithDirectionList.get(valueAtNewDirection);
// should not go back to the same number again
if (subresult.indexOf(newPad.getNumber()) == -1) {
subresult.add(valueAtNewDirection); printPretty(newPad);
for (DirectionEnum direction : DirectionEnum.values()) {
if (direction != opposites.get(directionEnum))
recursivelyFindPath(newPad, direction, maxIteration);
}
}
}
}
}
private void printPretty(PhonePadWithDirection pad) {
System.out.printf("For Number = %d : Up = %d, Down = %d, Left = %d, Right = %d%n",
pad.getNumber(),
pad.getValue(DirectionEnum.UP),
pad.getValue(DirectionEnum.DOWN),
pad.getValue(DirectionEnum.LEFT),
pad.getValue(DirectionEnum.RIGHT)
);
}
}
class PhonePadWithDirection {
private Integer number;
private Map<DirectionEnum, Integer> directionWithValue = new HashMap<>();
public PhonePadWithDirection(Integer number, Map<DirectionEnum, Integer> directionWithValue) {
this.number = number;
this.directionWithValue = directionWithValue;
}
public Integer getNumber() {
return number;
}
public Map<DirectionEnum, Integer> getDirectionWithValue() {
return directionWithValue;
}
public Integer getValue(DirectionEnum directionEnum) {
return this.getDirectionWithValue().get(directionEnum);
}
}
enum DirectionEnum {
UP,
DOWN,
LEFT,
RIGHT
}
Вы можете использовать backtracking
для генерации всех возможных цифр. Вот возможная реализация: https://ideone.com/Qiy3mt. Как видно, в псевдокоде ниже функция f(d, n)
выполняет рекурсивный поиск по глубине, чтобы исследовать все возможные цифры, которые соответствуют данному ограничению.
pad = [
"123",
"456",
"789",
" 0 "
]
def valid(i, j):
if i >= 4 or i < 0 or j < 0 or j >= 3:
return False
return (pad[i][j] != ' ')
delta_x = [-1, 1, 0, 0]
delta_y = [0, 0, -1, 1]
def f(d, n):
if n == 1:
return [d]
if n <= 0:
return []
x = None; y = None
# The following line of code can be replaced by a dict lookup which
# stores the indices of every digit, say { 5: (1, 1), 1: (0, 0) .. }
for i in range(0,4):
for j in range(0,3):
if pad[i][j] == str(d):
x = i; y = j
digits = []
for i in range(0,4):
next_x = x + delta_x[i]
next_y = y + delta_y[i]
if valid(next_x, next_y):
digits.extend(f(pad[next_x][next_y], n - 1))
return [str(d) + str(w) for w in digits]
print(f(5, 1))
print(f(1, 3))
print(f(0, 3))