Nano Hash - криптовалюты, майнинг, программирование

Рекурсивно найти слово в сетке

Я работаю над вопросом алгоритма, чтобы найти слово в сетке.

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

Я отслеживаю свои текущие позиции x и y, а затем увеличиваю позицию строки тогда и только тогда, когда в индексе слова есть совпадение с индексом в сетке. Однако с этим фрагментом кода что-то не так с моей рекурсией, вызывающей переполнение стека:

public static void findWord(int row, int col, char[][] grid, String w) {
    int rowLength = row;
    int colLength = col;

    char[] word = w.toCharArray();

    for(int j = 0; j < colLength; j++) {
        for(int i = 0; i < rowLength; i++) {
            // Check if first index of word is in this location
            if(word[0] == grid[j][i]) {
                // Iterate through each 8 directions to find the next word
                for(int dir = 0; dir < 8; dir++) {
                    recursiveFind(i, j, i, j, dir, 0, word, grid, rowLength, colLength);
                }
            }
        }
    }
}

public static boolean recursiveFind(
        int initialX, 
        int initialY, 
        int currentX, 
        int currentY, 
        int dir, 
        int currentPos, 
        char[] word, 
        char[][] grid, 
        int rowLength, 
        int colLength) 
{
    // base case is if currentPos == length of word
    if(word.length == currentPos) {
        System.out.println("Initial: " + initialX + " " + initialY);
        System.out.println("Final: " + currentX + " " + currentY);
    }

    if(dir == 0) { // 1
        currentX = currentX; // 0
        currentY -= 1; // -1
    } else if(dir == 1) {
        currentX += 1; // 1
        currentY -= 1; // -1
    } else if(dir == 2) {
        currentX += 1; // 1
        currentY = 0; // 0
    } else if(dir == 3) {
        currentX += 1; // 1
        currentY += 1; // 1
    } else if(dir == 4) {
        currentX = currentX; // 0
        currentY += 1;  // 1
    } else if(dir == 5) {
        currentX -= 1; // -1
        currentY += 1; // 1
    } else if(dir == 6) {
        currentX -= 1; // -1
        currentY = currentY; // 0
    } else {
        currentX -= 1; // -1
        currentY -= 1; // -1
    }

    if(currentX < 0 || 
            currentX == rowLength || 
            currentY < 0 || 
            currentY == colLength || 
            grid[currentY][currentX] != word[currentPos]){
        return false;
    }
    return recursiveFind(initialX, initialY, currentX, currentY, dir, currentPos + 1, word, grid, rowLength, colLength);
}

Main.java

    char[][] myGrid = new char[][]{
            {'H', 'Q', 'W', 'C', 'S'}, 
            {'E', 'S', 'P', 'K', 'D'}, 
            {'D', 'X', 'A', 'F', 'L'}, 
            {'O', 'C', 'H', 'K', 'H'}, 
            {'C', 'T', 'Y', 'C', 'A'}, 
    };

    String myWord = "CODE";

    findWord(5, 5, myGrid, myWord);

В настоящее время я пытаюсь разместить некоторые операторы отладки, чтобы понять, в чем проблема, однако, если кто-то готов помочь мне в этом, я буду очень признателен!

РЕДАКТИРОВАТЬ:

Я исправил проблему переполнения стека с помощью return true в базовом случае. Однако мои результаты следующие, которые не возвращают ожидаемые значения, которые я хотел.

Initial X: 3, Initial Y: 0, Dir: 0, Current X: 3, Current Y: 0
Initial X: 3, Initial Y: 0, Dir: 1, Current X: 3, Current Y: 0
Initial X: 3, Initial Y: 0, Dir: 2, Current X: 3, Current Y: 0
Initial X: 3, Initial Y: 0, Dir: 3, Current X: 3, Current Y: 0
Initial X: 3, Initial Y: 0, Dir: 4, Current X: 3, Current Y: 0
Initial X: 3, Initial Y: 0, Dir: 5, Current X: 3, Current Y: 0
Initial X: 3, Initial Y: 0, Dir: 6, Current X: 3, Current Y: 0
13.04.2016

Ответы:


1

Я изменил его, чтобы проверить правильность текущей позиции, а затем продолжить поиск. В противном случае вернуть ложь.

public static boolean recursiveFind(
        int initialX,
        int initialY,
        int currentX,
        int currentY,
        int dir,
        int currentPos,
        char[] word,
        char[][] grid,
        int rowLength,
        int colLength) {
    // base case is if currentPos == length of word
    if (word.length == currentPos) {
        System.out.println("Initial: " + initialX + " " + initialY);
        System.out.println("Final: " + currentX + " " + currentY);
        return true;
    }

    if (currentX >= 0 && currentX < rowLength && currentY >= 0 && currentY < colLength && grid[currentY][currentX] == word[currentPos]) {
        if (dir == 0) { // 1
            currentX = currentX; // 0
            currentY -= 1; // -1
        } else if (dir == 1) {
            currentX += 1; // 1
            currentY -= 1; // -1
        } else if (dir == 2) {
            currentX += 1; // 1
            currentY = 0; // 0
        } else if (dir == 3) {
            currentX += 1; // 1
            currentY += 1; // 1
        } else if (dir == 4) {
            currentX = currentX; // 0
            currentY += 1; // 1
        } else if (dir == 5) {
            currentX -= 1; // -1
            currentY += 1; // 1
        } else if (dir == 6) {
            currentX -= 1; // -1
            currentY = currentY; // 0
        } else {
            currentX -= 1; // -1
            currentY -= 1; // -1
        }

        return recursiveFind(initialX, initialY, currentX, currentY, dir, currentPos + 1, word, grid, rowLength, colLength);
    }

    return false;

}

РЕДАКТИРОВАТЬ: с вашим последним редактированием проблема заключается в том, что вы меняете currentX/currentY перед проверкой текущей позиции.

Этот фрагмент кода:

if(currentX < 0 || 
        currentX == rowLength || 
        currentY < 0 || 
        currentY == colLength || 
        grid[currentY][currentX] != word[currentPos]){
    return false;
}

должно произойти до того, как вы сделаете:

if(dir == 0) { // 1
    currentX = currentX; // 0
    currentY -= 1; // -1
} else if(dir == 1) {
    currentX += 1; // 1
    currentY -= 1; // -1
} else if(dir == 2) {
    currentX += 1; // 1
    currentY = 0; // 0
} else if(dir == 3) {
    currentX += 1; // 1
    currentY += 1; // 1
} else if(dir == 4) {
    currentX = currentX; // 0
    currentY += 1;  // 1
} else if(dir == 5) {
    currentX -= 1; // -1
    currentY += 1; // 1
} else if(dir == 6) {
    currentX -= 1; // -1
    currentY = currentY; // 0
} else {
    currentX -= 1; // -1
    currentY -= 1; // -1
}

Или вы действительно не проверяете текущую позицию: P

13.04.2016
  • Вау Брендан - спасибо! Рад видеть, что я был на правильном пути, но перепутал порядок действий. 13.04.2016
  • Повторим еще раз: мы проверяем положение и действительность x и y, прежде чем увеличивать/уменьшать текущие положения x и y, верно? 13.04.2016
  • Да, это звучит правильно. Хотя я не уверен, что этот способ намного (если вообще) лучше, чем просто брать целые строки, столбцы и диагональные полосы и искать слово, используя подстроку :) 13.04.2016
  • На самом деле временная сложность этого кажется довольно высокой. Первые два цикла for сразу же учитывают O(row * length). Теперь убедитесь, какова сложность рекурсии и направления циклов for. 13.04.2016

  • 2

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

    Изменить: я уверен, что условие для каталога 2 должно быть:

    else if(dir == 2) {
            currentX += 1; // 1
            currentY = currentY; // 0
        }
    

    В противном случае вы перезапустите свой текущий Y, как сейчас.

    РЕДАКТИРОВАТЬ: Кроме того, вы не должны отправлять currentpos как 0 для начала рекурсии, потому что он снова будет сравниваться с первой буквой слова. Рекурсия должна начинаться со второго символа, так как вы уже сравнили первый. Не забудьте добавить return true, и ваша программа должна работать. Я только что попробовал это на своем компьютере.

    13.04.2016
  • О, похоже, мне не хватило возврата true! 13.04.2016
  • Я предположил, что проблема может быть в чем-то подобном. Это сработало? 13.04.2016
  • Неа. Это не дало бы мне ошибки переполнения стека, но не вернуло ожидаемые значения правильно. 13.04.2016
  • Ваша рекурсия должна остановиться, если x или y выходят за пределы границ, но я не вижу, чтобы вы где-либо принимали это во внимание. Если конечная цель состоит в том, чтобы найти слово, которое у вас есть, почему вы не сравниваете текущую позицию в сетке с искомым символом? 13.04.2016
  • Я могу ошибаться, но разве я не делаю это с помощью grid[currentY][currentX] != word[currentPos]? Что я делаю, так это увеличивает переменную pos только в том случае, если есть совпадение в сетке char и слове char. 13.04.2016
  • Извините, я сказал это до того, как вы изменили условие в if. Проверьте редактирование, не думаете ли вы, что это может вызвать проблемы? 13.04.2016
  • О, спасибо за этот улов. Нет, к сожалению, это не решило проблему. 13.04.2016
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

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

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

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

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..