Как я могу использовать Поиск в глубину для отображения номеров с телефонной панели?

1

Я пытаюсь решить проблему с номером телефона, используя 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
}
  • 1
    что ты уже испробовал?
  • 0
    Используя DFS (которая включает в себя рекурсию, возврат), вы можете сгенерировать все возможные перестановки длины n. Для каждой перестановки проследите, чтобы решить, является ли это возможным шаблоном или нет. Таким образом, вы можете сосчитать их.
Показать ещё 1 комментарий
Теги:
algorithm
data-structures
depth-first-search

1 ответ

3

Вы можете использовать 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))

Ещё вопросы

Сообщество Overcoder
Наверх
Меню