Рекурсивное отслеживание проблем Судоку, C ++. - PullRequest
1 голос
/ 24 октября 2011

Я впервые имею дело с рекурсией в качестве задания на низкоуровневом курсе. Я просмотрел интернет и не могу найти кого-то, кто использует метод, похожий на тот, который я придумал (который, вероятно, говорит о том, почему это не работает). Ошибка - ошибка сегментации в std::__copy_move..., которая, как я полагаю, есть в c ++ STL. Во всяком случае, мой код выглядит следующим образом:

bool sudoku::valid(int x, int y, int value)
{
    if (x < 0) {cerr << "No valid values exist./n";}

    if (binary_search(row(x).begin(), row(x).end(), value))
        {return false;}                 //if found in row x, exit, otherwise:
    else if (binary_search(col(y).begin(), col(y).end(), value))
        {return false;}                 //if found in col y, exit, otherwise:
    else if (binary_search(box((x/3), (y/3)).begin(), box((x/3), (y/3)).end(), value))
        {return false;}                 //if found in box x,y, exit, otherwise:
    else
        {return true;}                  //the value is valid at this index
}

int sudoku::setval(int x, int y, int val)
{
    if (y < 0 && x > 0) {x--; y = 9;}   //if y gets decremented past 0 go to previous row.
    if (y > 8) {y %= 9; x++;}           //if y get incremented past 8 go to next row.

    if (x == 9) {return 0;}             //base case, puzzle done.
    else {
        if (valid(x,y,val)){            //if the input is valid
            matrix[x][y] = val;         //set the element equal to val
            setval(x,y++,val);          //go to next element
        }
        else {
            setval(x,y,val++);          //otherwise increment val
            if(val > 9) {val = value(x,y--); setval(x,y--,val++); }
        }                               //if val gets above 9, set val to prev element,  
    }                                   //and increment the last element until valid and start over
}

Я пытался обернуть голову вокруг этой штуки некоторое время, и я не могу понять, что происходит не так. Любые предложения высоко ценятся! :)

Ответы [ 5 ]

1 голос
/ 24 октября 2011

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

1 голос
/ 24 октября 2011

Без дополнительной информации невозможно сказать.Такие вещи, как задействованные структуры данных и что, например, row и col возвращают.Тем не менее, существует ряд очевидных проблем:

  • В sudoku::valid вы проверяете наличие ошибки (x < 0), но не возвращаете;Вы все еще продолжаете свои тесты, используя отрицательное значение x.

  • Также в sudoku:valid: действительно ли row и col возвращают ссылки на отсортированные значения?Если значения не отсортированы, то binary_search будет иметь неопределенное поведение (и если они есть, имена несколько вводят в заблуждение).И если они возвращают значения (копии чего-либо), а не ссылку на один и тот же объект, то функции begin() и end() будут ссылаться на разные объекты - опять же, неопределенное поведение.

  • Наконец, я не вижу возврата в вашем алгоритме и не вижу, как он переходит к решению.

FWIW: когда я написал нечто подобное, яиспользовал простой массив из 81 элемента для доски, затем создал статические массивы, которые отображали индекс (0–80) в соответствующую строку, столбец и поле.И для каждой из девяти строк, столбцов и полей я сохранил набор используемых значений (растровое изображение);это делало проверку на легальность очень тривиальной, и это означало, что я мог увеличивать до следующего квадрата для проверки, просто увеличивая индекс.Полученный код был чрезвычайно прост.

Независимо от используемого представления данных, вам понадобится: какой-то «глобальный» (вероятно, член sudoku) способ узнать, нашли ли вы решение или нет;цикл где-то пробует каждое из девяти возможных значений для квадрата (останавливается, когда решение найдено) и рекурсии.Если вы не используете простой массив для доски, как я, я бы предложил класс или структуру для индекса с функцией, которая позаботится о приращении раз и навсегда.

0 голосов
/ 24 октября 2011

Похоже, ваш алгоритм немного "грубая сила".Как правило, это не очень хорошая тактика с проблемами удовлетворения ограничений (CSP).Некоторое время назад я написал решатель судоку (жаль, что у меня еще не было исходного кода, это было до того, как я открыл github), и самый быстрый алгоритм, который я смог найти, - это имитация отжига:

http://en.wikipedia.org/wiki/Simulated_annealing

Это вероятностное решение, но в целом оно было на несколько порядков быстрее, чем другие методы решения этой проблемы IIRC.

HTH!

0 голосов
/ 24 октября 2011

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

Совет: напишите в своих словах назначение любой функции - если это слишком сложно написать - функцию, вероятно, следует разделить ...

0 голосов
/ 24 октября 2011

Все нижеизложенное относится к Unix, а не к Windows.

std::__copy_move... в порядке STL.Но STL ничего не делает сам по себе, какой-то вызов функции из вашего кода вызвал бы его с неверными аргументами или в неправильном состоянии.Вы должны это выяснить.

Если у вас есть дамп ядра из seg-fault, тогда просто выполните pstack <core file name>, и вы увидите полный стек вызовов сбоя.Затем просто посмотрите, какая часть вашего кода была задействована, и начните отладку (добавьте traces / couts / ...) оттуда.

Обычно вы получаете этот файл ядра с хорошими читаемыми именами, но в случаеВы не можете использовать nm или c++filt и т. д., чтобы разобрать имена.

Наконец, pstack - это просто небольшая утилита строки cmd, вы всегда можете загрузитьдвоичный файл (который создал ядро) и файл ядра в отладчик, такой как gdb , Sun Studio или отладчик, встроенный в вашу среду IDE, и он видит то же самое вместе со множеством другой информации и опций.

HTH

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...