arrays - tipos - ¿Cómo convertir vectores a matrices en ECLiPSe(CLP)?(o Prolog)
vector java ejemplo (1)
Tengo que resolver acertijos Sudoku en el formato de un vector que contiene 9 vectores (de longitud 9 cada uno). Viendo que los vectores son listas enlazadas en Prolog, pensé que la búsqueda sería más rápida si primero transformara los rompecabezas en un formato de matriz 2D.
Ejemplo de rompecabezas:
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,_]].
Estoy usando ECLiPSe CLP para implementar un solucionador. Lo mejor que he logrado hasta ahora es escribir un dominio como este:
domain(P):-
dim(P,[9,9]),
P[1..9,1..9] :: 1..9.
y un convertidor para el rompecabezas (el parámetro P es el rompecabezas dado y Sudoku es la nueva cuadrícula definida con la matriz 2D). Pero estoy teniendo problemas para vincular los valores del rompecabezas inicial dado a mi matriz 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]
)
).
Antes de esto, traté de usar array_list ( http://eclipseclp.org/doc/bips/kernel/termmanip/array_list-2.html ), pero seguí recibiendo errores de tipo. Cómo lo hice antes:
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])
)
).
Cuando mi Sudoku finalmente emite el ejemplo de rompecabezas P en el siguiente formato:
Sudoku = []([](_Var1, _Var2, 8, 7, ..., 6), [](4, ...), ...)
entonces seré feliz
actualizar
Lo intenté de nuevo con array_list; casi funciona con el siguiente código:
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)
).
Las escrituras están ahí para ver cómo se ven los vectores / matrices. Por alguna razón, se detiene en la segunda iteración (en lugar de 9 veces) y emite el resto del rompecabezas de ejemplo como un vector de vectores. Solo el primer vector se asigna correctamente.
actualización2
Aunque estoy seguro de que la respuesta dada por jschimpf es correcta, también descubrí mi propia implementación:
convertVectorsToArray(Sudoku,[],_).
convertVectorsToArray(Sudoku,[Y|Rest],Count):-
X is Sudoku[Count],
array_list(X, Y),
NewCount is Count + 1,
convertVectorsToArray(Sudoku,Rest,NewCount).
¡Gracias por la explicación adicional sobre por qué no funcionó antes!
La solución más fácil es evitar la conversión escribiendo la especificación de los rompecabezas directamente como una matriz 2-D. Una "matriz" ECLiPSe es simplemente una estructura con el funtor ''[]''/N
, por lo que puede escribir:
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,_)).
A continuación, puede utilizar esta matriz bidimensional directamente como el contenedor de las variables de su dominio:
sudoku(P) :-
puzzle(P),
P[1..9,1..9] :: 1..9,
...
Sin embargo, si desea mantener su especificación de rompecabezas de la lista de listas y convertirla en un formato de matriz de arreglos, puede usar array_list/2
. Pero como eso solo funciona para matrices en 1-D, debe convertir los niveles de anidación individualmente:
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).
En cuanto a la razón por la que su propio código no funcionó: esto se debe a la notación del subíndice P[I]
. Esta
- requiere que
P
sea una matriz (lo estabas utilizando en las listas) - funciona solo en contextos donde se espera una expresión aritmética, por ejemplo, el lado derecho de
is/2
, en restricciones aritméticas, etc.