You will see my code consists of placing a mosaic of 8 pieces (a list of lists) and a number N that indicates the number of steps you will take, and you have to show if with that number N you can reach the final state (state resolved) of the mosaic, if it is not equal gives false. example:
puzzle (X, N): Given an initial position X and a number of steps N, check if the minimum number of steps to get from X to the final state is equal to N. If it is not resolvable, you must return false.
mosaic: [[1,9,3], [5,2,6], [4,7,8]] resolved status is: [[1,2,3], [4,5,6 ], [7,8,9]] where nine is the vacuum, I found the code to interconnect with the algorithm A * that they asked me to use
and the function returns true in the case that it fulfills the correct case, example: puzzle ([[1,9,3], [5,2,6], [4,7,8]], 5 ) -True but if instead of 5 it is 3 that is not enough or 7 when it is too many, it gives me an exception and stays stuck.
my function puzzle use faltten and I use a function that replaces the 9 with the 0 since the code I got used the 0 as empty
GoalState([1,2,3,4,5,6,7,8,0]).
rompecabezas([X|T],N):- flatten([X|T],ListaAux), replace(9,0,ListaAux,ListaAux2), idsearch(ListaAux2,Val), Val == N.
replace(_, _, [], []).
replace(O, R, [O|T], [R|T2]) :- replace(O, R, T, T2).
replace(O, R, [H|T], [H|T2]) :- H \= O, replace(O, R, T, T2).
solution(ProblemName, Solution) :-
retractall(problem(_,_)),
[ProblemName],
problem(I,G),
solutionAux(problem(I,G), Solution).
% solutionAux(problem(+InitialState, +GoalState), -Solution)
solutionAux(problem(InitialState, GoalState), Solution) :-
retractall(is_goal(_)),
assert(is_goal(GoalState)),
idsearch(InitialState, RevSolution),
reverse(RevSolution, Solution).
% idsearch(N,P) is true if path P is a path found from node N
% using iterative deepening A* search
% Example query: idsearch(o103,P).
idsearch(N,P) :-
h(N,HN),
%%writeln(['Trying Depth bound: ',HN]),
dbsearch([node(N,[],0)],HN,[node(N,[],0)],natural,Q), P is HN.
% dbsearch(F,DB,Q,How1,P) is true if a depth bound search from frontier F
% can find a path P of length >= DB.
% where Q is the initial frontier to (re)start from,
% How specifies whether the previous bound failed naturally or gives
% the minimum f-value for which the search failed.
% The frontier is a list of node(Node,Path,PathLength)
% where Node is a node, Path is the path found to Node,
% PathLength is the length of the path.
%dbsearch(F,_,_,_,_) :-
% writeln(['Frontier: ',F]),
% fail.
dbsearch([],_,Q,NDB,S) :-
number(NDB),
writeln(['Trying Depth bound: ',NDB]),
dbsearch(Q,NDB,Q,natural,S).
dbsearch([node(N,P,DB)|_],DB,_,_,[N|P]) :-
is_goal(N).
dbsearch([node(N,P,PL)|F1],DB,Q,H,S) :-
h(N,HN),
HN+PL =< DB,
neighbors(N,NewNs),
subtract(NewNs, P, NNs), % loop elimination
add_paths_db(NNs,N,[N|P],PL,F1,F2),
dbsearch(F2,DB,Q,H,S).
dbsearch([node(N,_,PL)|F1],DB,Q,H,S) :-
h(N,HN),
HN+PL > DB,
min1(HN+PL,H,LUB),
dbsearch(F1,DB,Q,LUB,S).
% add_paths(NNs,N,Path,PL,F0,F1)
add_paths_db([],_,_,_,F,F).
add_paths_db([NN|R],N,Path,PL,F0,[node(NN,Path,PL1)|F1]) :-
cost(N,NN,AC),
PL1 is PL+AC,
add_paths_db(R,N,Path,PL,F0,F1).
min1(E,natural,V) :- !, V is E.
min1(E,V,V) :- V =< E.
min1(E,V,V1) :- V > E, V1 is E.
% **************************************************
% writeln(L) is true if L is a list of items where each
% item is written on a separate line, followed by a newline.
writeln([]) :- nl.
writeln([H|T]) :- write(H), nl, writeln(T).
%% we are making all edge costs to be 1
%% if you want different edges to have
%% different costs you must comment this out
%% and include a cost predicate in the domain
%% file
cost(_,_,1).
%---------------------------------------------------%
neighbors(State, Neighbors) :-
findall(Neighbor, successor(State, Neighbor), Neighbors).
successor(State, Neighbor) :-
moveUp(State, Neighbor);
moveDown(State, Neighbor);
moveLeft(State, Neighbor);
moveRight(State, Neighbor).
location(State, X, Y, Elem) :-
nth0(Index, State, Elem),
divmod(Index, 3, X, Y).
index(Index, X, Y) :-
Index is 3 * X + Y.
swap(State, I1, I2, Final) :-
same_length(State, Final),
length(BeforeI1, I1),
length(BeforeI2, I2),
append(BeforeI1, [EI1|PastI1], State),
append(BeforeI1, [EI2|PastI1], Temp),
append(BeforeI2, [EI2|PastI2], Temp),
append(BeforeI2, [EI1|PastI2], Final).
moveUp(State, Final) :-
location(State, X, Y, 0),
X > 0,
Z is X - 1,
index(Index, X, Y),
index(NewIndex, Z, Y),
swap(State, Index, NewIndex, Final).
moveDown(State, Final) :-
location(State, X, Y, 0),
X < 2,
Z is X + 1,
index(Index, X, Y),
index(NewIndex, Z, Y),
swap(State, Index, NewIndex, Final).
moveLeft(State, Final) :-
location(State, X, Y, 0),
Y > 0,
Z is Y - 1,
index(Index, X, Y),
index(NewIndex, X, Z),
swap(State, Index, NewIndex, Final).
moveRight(State, Final) :-
location(State, X, Y, 0),
Y < 2,
Z is Y + 1,
index(Index, X, Y),
index(NewIndex, X, Z),
swap(State, Index, NewIndex, Final).
h(State, HeuristicValue) :-
is_goal(GoalState),
manhattan(State, GoalState, 1, 0, HeuristicValue).
manhattan(State, GoalState, Elem, InValue, InValue) :-
same_length(State, GoalState),
length(State, Length),
Elem =:= Length.
manhattan(State, GoalState, Elem, InValue, HeuristicValue) :-
location(State, X, Y, Elem),
location(GoalState, A, B, Elem),
Value is InValue + abs(X - A) + abs(Y - B),
NewElem is Elem + 1,
manhattan(State, GoalState, NewElem, Value, HeuristicValue).