2016-03-12 1 views
5

Я должен решить головоломки Sudoku в формате вектора, содержащего 9 векторов (длиной 9 каждый). Видя, как векторы связаны списками в Prolog, я решил, что поиск будет идти быстрее, если я сначала преобразую головоломки в формате 2D-массива.Как преобразовать векторы в массивы в ECLiPSe (CLP)? (или Prolog)

Пример головоломки:

puzzle(P) :- P = 
[[_,_,8,7,_,_,_,_,6], 
[4,_,_,_,_,9,_,_,_], 
[_,_,_,5,4,6,9,_,_], 

[_,_,_,_,_,3,_,5,_], 
[_,_,3,_,_,7,6,_,_], 
[_,_,_,_,_,_,_,8,9], 

[_,7,_,4,_,2,_,_,5], 
[8,_,_,9,_,5,_,2,3], 
[2,_,9,3,_,8,7,6,_]]. 

Я использую ECLIPSE CLP для реализации решателя. Лучшее, что я придумал до сих пор, чтобы написать домен как это:

domain(P):- 
    dim(P,[9,9]), 
    P[1..9,1..9] :: 1..9. 

и конвертер для головоломки (параметр P является данная головоломка и Судоку новая определяется сетка с 2D-массив) , Но мне сложно связать значения из заданной начальной головоломки с моим 2D-массивом.

convertVectorsToArray(Sudoku,P):- 
    (for(I,1,9), 
     param(Sudoku,P) 
    do 
     (for(J,1,9), 
      param(Sudoku,P,I) 
     do 
      Sudoku[I,J] is P[I,J] 
    ) 
). 

До этого, я попытался с помощью array_list (http://eclipseclp.org/doc/bips/kernel/termmanip/array_list-2.html), но я продолжал получать ошибки типа. Как я сделал это раньше:

convertVectorsToArray(Sudoku,P):- 
    (for(I,1,9), 
     param(Sudoku,P) 
    do 
     (for(J,1,9), 
      param(Sudoku,P,I) 
     do 
      A is Sudoku[I], 
      array_list(A,P[I]) 
    ) 
). 

Когда мой судоку наконец выводит пример головоломки P в следующем формате:

Sudoku = []([](_Var1, _Var2, 8, 7, ..., 6), [](4, ...), ...) 

, то я буду счастлив.

обновление

Я попробовал еще раз с array_list; он работает почти со следующим кодом:

convertVectorsToArray(Sudoku,P):- 
    (for(I,1,9), 
     param(Sudoku,P) 
    do 
     X is Sudoku[I], 
     Y is P[I], 
     write(I),nl, 
     write(X),nl, 
     write(Y),nl, 
     array_list(X, Y) 
). 

В записи есть, чтобы увидеть, как векторы/массивы похожи. По какой-то причине он останавливается на второй итерации (вместо 9 раз) и выводит остальную часть головоломки примера как вектор векторов. Правильно назначается только первый вектор.

Update2

Хотя я уверен, что ответ дается jschimpf правильно, я понял, моя собственная реализация:

convertVectorsToArray(Sudoku,[],_). 
convertVectorsToArray(Sudoku,[Y|Rest],Count):- 
    X is Sudoku[Count], 
    array_list(X, Y), 
    NewCount is Count + 1, 
    convertVectorsToArray(Sudoku,Rest,NewCount). 

Спасибо за добавленным объяснения о том, почему он не сделал работа прежде, чем!

ответ

5

Самое простое решение - полностью отказаться от преобразования, написав свою спецификацию головоломки непосредственно в виде 2-мерного массива. ECLIPSE «массив» это просто структура с функтором '[]'/N, так что вы можете написать:

puzzle(P) :- P = [](
    [](_,_,8,7,_,_,_,_,6), 
    [](4,_,_,_,_,9,_,_,_), 
    [](_,_,_,5,4,6,9,_,_), 

    [](_,_,_,_,_,3,_,5,_), 
    [](_,_,3,_,_,7,6,_,_), 
    [](_,_,_,_,_,_,_,8,9), 

    [](_,7,_,4,_,2,_,_,5), 
    [](8,_,_,9,_,5,_,2,3), 
    [](2,_,9,3,_,8,7,6,_)). 

Вы можете использовать этот 2-D массив непосредственно в качестве контейнера для переменного домена:

sudoku(P) :- 
    puzzle(P), 
    P[1..9,1..9] :: 1..9, 
    ... 

Однако, если вы хотите сохранить спецификацию головоломки списка списков и преобразовать ее в формат массива массивов, вы можете использовать array_list/2.Но так как это работает только для 1-D массивов, вы должны преобразовать уровней вложенности индивидуально:

listoflists_to_matrix(Xss, Xzz) :- 
    % list of lists to list of arrays 
    (foreach(Xs,Xss), foreach(Xz,Xzs) do 
     array_list(Xz, Xs) 
    ), 
    % list of arrays to array of arrays 
    array_list(Xzz, Xzs). 

Как по причине ваш собственный код не работает: это связано с индексом обозначений P[I]. Это

  • требует P быть массив (вы использовали его в списках)
  • работает только в условиях, когда, как ожидается, арифметическое выражение, например правая сторона is/2, в арифметических ограничениях и т. д.