Реализация рекурсии в Java

просто для ясности, это не домашнее задание, Я изучаю CS в свое время!

вставьте математический оператор ( + , -,÷, x) в каждое из пространств для решения уравнения:

6 _ 3 _ 5 _ 7 _ 4 _ 8 = 13

насколько я понимаю, для решения этой проблемы с помощью рекурсии мне сначала нужно определить базовый случай. Однако у меня проблемы с этим.

Итак, мой вопрос в том, что такое возможный базовый случай и как я должен начать его реализовывать? Как может выглядеть рекурсивная функция (аргументы, тип возврата и т. д.)? (код полезен, пожалуйста)!

это то, что у меня есть до сих пор:почти работает я думай!--2-->

см. мой ответ для реализации

N. b. Я использую Java

4 ответов


Я думаю, что условие остановки должно означать, что уравнение выполнено: все операторы заполнены, а операции приводят к правильному равенству.

Я бы выразил уравнение как дерево разбора, с листьями как числами и родителями как операторами. Дерево, естественно, поддается рекурсии, потому что это иерархическая структура данных.

сделать предположение оператора, где корневая операция является знаком минус, правильный ребенок является желаемым значение (13), а левый дочерний элемент-левая сторона. Добавьте оператор, оцените дерево и вернитесь назад, пока не будет выполнено условие остановки.


базовый случай, когда все пробелы заполняются операторами. Вы можете решить эту проблему, используя поиск по глубине:

algorithm dfs(i):
    if i == num_blanks:  # base case: filled in all the blanks
        if equation_solved():
            return the operators you filled in
    else:
        for op in (+, -, ÷, ×):
            blank[i] = op
            if dfs(i + 1) returns a solution:
                return that solution
            blank[i] = _     # restore to previous state

это рекурсивный способ поиска по всему комбинаторному пространству. (Надеюсь, это не испортит вам упражнение; я написал его в псевдокоде, чтобы оставить реализацию вам.)


вы можете думать об этом как о дереве решений.

              6
        /    /    \    \
        +   -     *    /
        3                    Assuming you choose + for the first operator
/    /       \    \
+   -        *    /
5   5        5    5
    ^             ^
    6 + 3 - 5     6 + 3 / 5

затем вы можете использовать алгоритм обхода графика, такой как DFS или BFS, чтобы проверить результат. Оба они рекурсивны.


вот реализация, с которой я закончил, но сначала объяснение решения проблемы:

  • базовый вариант (как сказал larsmans и Ян Дворжак) - это когда все "_" заполняются операторы (такие как "+").
  • функция вызывает себя, добавляя каждый раз другой параметр, пока он не достигнет неверного базового случая (например "6+3+5+7+4-8=13") или у него есть правильный ответ.
  • если базовый случай неверен, то мы продолжаем появляться уровни мы получаем на уровень с оператором, который мы можем изменить.

вот код:

class GapFill {

    private static String numbers; //E.g. 6_5_4=15
    private static String[] blank; //Array of operators to go in the blanks

    //Where:
    //p = plus
    //m = minus
    //d = divide
    //t = times
    private static String[] operators = {"p", "m", "d,", "t"};

    public static void main(String[] args) {
        numbers = args[0];
        blank = new String[numbers.split("_").length - 1];
        if(dfs(0)) { //If a solution was found
            int count = 0;
            while(numbers.indexOf("_")!=-1) {
                int index = numbers.indexOf("_");
                numbers = numbers.substring(0,index)+blank[count]+numbers.substring(index+1);
                count++;
            }
            System.out.println(numbers);
        }
    }

    private static boolean dfs(int i) {
        if(i == blank.length) {  //base case: filled in all the blanks
            return solveEquation();
        }
        for(String op : operators) {
            blank[i] = op;
            if(dfs(i + 1)) {
                return true;
            }
        }
        blank[i] = "_"; //restore to previous state
        return false;
    }

    private static boolean solveEquation() {
        String[] eachNumber = numbers.substring(0, numbers.indexOf("=")).split("_");
        String finalResult = numbers.substring(numbers.indexOf("=")+1, numbers.length());
        double currentResult = Double.parseDouble(eachNumber[0]);
        for(int i=1;i<eachNumber.length;i++) {
            String op = blank[i-1];
            if(op==operators[0]) {
                currentResult = currentResult + Integer.parseInt(eachNumber[i]);
            } else if(op==operators[1]) {
                currentResult = currentResult - Integer.parseInt(eachNumber[i]);
            } else if(op==operators[2]) {
                currentResult = currentResult / Integer.parseInt(eachNumber[i]);
            } else if(op==operators[3]) {
                currentResult = currentResult * Integer.parseInt(eachNumber[i]);
            }
        }
        return (currentResult==Integer.parseInt(finalResult));
    }

}

вывод java GapFill 6_3_5_7_4_8=13 is 6m3p5m7p4p8=13.

символы "p,m,d,t" используются вместо"+, -,÷,×", так как терминал не любит × или ÷