Square placing in Prolog - prolog

I have a nxn area. And I want to list all of the positions of possible kxk m squares (k < n) which don't touch each other in that area. I want to list the coordinates of the upper-leftmost squares of those kxk squares. Can you give me some hint about implementing this with Prolog? I'm very new to this language. I just read a small tutorial but now I don't know what to do.
They are also touching if their corners touch.
The input and output should be like this :(k : size of small square,n : size of big square, m: number of small squares)
>func(k,n,m,O).
>func(1,3,2,O).
O =[1-1,1-3];
O =[1-1,2-3];
O =[1-1,3-1];
O =[1-1,3-2];
O =[1-1,3-3];
O =[1-2,3-1];
O =[1-2,3-2];
O =[1-2,3-3];
O =[1-3,2-1];
O =[1-3,3-1];
O =[1-3,3-2];
O =[1-3,3-3];
O =[2-1,2-3];
O =[2-1,3-3];
O =[2-3,3-1];
O =[3-1,3-3];
No.

I post a solution showing a possible Prolog coding, in style generate and test. There is some slot where you'll place appropriate arithmetic, just to complete your assignment.
%% placing
place_squares(Big, Small, Squares) :-
place_not_overlapping(Big, Small, [], Squares).
place_not_overlapping(Big, Small, SoFar, Squares) :-
available_position(Big, Small, Position),
\+ overlapping(Small, Position, SoFar),
place_not_overlapping(Big, Small, [Position|SoFar], Squares).
place_not_overlapping(_Big, _Small, Squares, Sorted) :-
sort(Squares, Sorted).
overlapping(Size, R*C, Squares) :-
member(X*Y, Squares),
... % write conditions here
available_position(Big, Small, Row*Col) :-
Range is Big - Small + 1,
between(1, Range, Row),
between(1, Range, Col).
after placing, it's easy to display
%% drawing
draw_squares(Big, Small, Squares) :-
forall(between(1, Big, Row),
(forall(between(1, Big, Col),
draw_point(Row*Col, Small, Squares)),
nl
)).
draw_point(Point, Small, Squares) :-
( nth1(I, Squares, Square),
contained(Point, Square, Small)
) -> write(I) ; write('-').
contained(R*C, A*B, Size) :-
... % place arithmetic here
the result with requested dimensions, and drawing
?- place_squares(5,2,Q),draw_squares(5,2,Q).
1122-
1122-
3344-
3344-
-----
Q = [1*1, 1*3, 3*1, 3*3] ;
1122-
1122-
33-44
33-44
-----
Q = [1*1, 1*3, 3*1, 3*4] ;
1122-
1122-
33---
3344-
--44-
Q = [1*1, 1*3, 3*1, 4*3] .
...
the place_squares/3 output is sorted, to ease displaying, and could as well be used to get rid of symmetry, and get a count of all solutions:
9 ?- setof(Q, place_squares(5,2,Q), L), length(L, N).
L = [[], [1*1], [1*1, 1*3], [1*1, 1*3, 3*1], [1*1, 1*3, 3*1, ... * ...], [1*1, 1*3, ... * ...|...], [1*1, ... * ...|...], [... * ...|...], [...|...]|...],
N = 314.
You can note that this accepts boards with 'spare' space. You could filter out such incomplete solutions, to complete your task.

Related

Superpermutation in Prolog

I want to watch 6 episodes of "friends" in all possible permutations. How can I arrange the episodes in one string so that the substrings of length 6 cover all permutations? What are the shortest such strings?
What would be the Prolog code for that?
Here is a brute-force implementation with an attempt to build shorter solutions first.
superpermutation(Atom, Superpermutation) :-
bagof(Permutation, permute(Atom, Permutation), Permutations),
select(Permutation, Permutations, RemainingPermutations),
join(RemainingPermutations, Permutation, Superpermutation).
join([], Superpermutation, Superpermutation).
join(Permutations, Superpermutation, FinalSuperpermutation) :-
member(OnePermutation, Permutations),
atom_length(OnePermutation, Length), !,
%
between(1, Length, Position),
select(Permutation, Permutations, RemainingPermutations),
sub_atom(Permutation, Position, _, 0, Suffix),
sub_atom(Superpermutation, 0, _, _, Suffix),
sub_atom(Permutation, 0, Position, _, Prefix),
atom_concat(Prefix, Superpermutation, NewSuperpermutation),
join(RemainingPermutations, NewSuperpermutation, FinalSuperpermutation).
permute(Atom, PermutedAtom) :-
atom_chars(Atom, Chars),
permutation(Chars, PermutedChars),
atom_chars(PermutedAtom, PermutedChars).
Here are the first solutions found for n = 2 to 7.
n = 2
212
n = 3 (length = 9)
321323123
n = 4 (length = 33)
432143241324312434213423142341234
n = 5 (length = 153)
543215432514325413254312543521435241352431524351243542135423154235142354123545
321453241532451324531245342153425134253142534125345213452314523415234512345
n = 6 (length = 873, known shorter length = 872)
654321654326154326514326541326543126543621543625143625413625431625436125436521
436524136524316524361524365124365421365423165423615423651423654123654632154632
514632541632546132546312546352146352416352461352463152463512463542163542613542
631542635142635412635462135462315462351462354162354612354653214653241653246153
246513246531246534216534261534265134265314265341265346215346251346253146253416
253461253465213465231465234165234615234651234656432156432516432561432564132564
312564352164352614352641352643152643512643562143562413562431562435162435612435
642135642315642351642356142356412356453216453261453264153264513264531264536214
536241536245136245316245361245364215364251364253164253614253641253645213645231
645236145236415236451236456321456324156324516324561324563124563421563425163425
613425631425634125634521634526134526314526341526345126345621345623145623415623
451623456123456
n = 7 (length = 5913, known shorter length = 5908) (computation time ~ 10 secs)
765432176543271654327615432765143276541327654312765437216543726154372651437265
413726543172654371265437621543762514376254137625431762543716254376125437652143
765241376524317652437165243761524376512437654213765423176542371654237615423765
142376541237654732165473261547326514732654173265471326547312654736215473625147
362541736254713625473162547361254736521473652417365247136524731652473615247365
124736542173654271365427316542736154273651427365412736547213654723165472361547
236514723654172365471236547632154763251476325417632547163254761325476312547635
214763524176352471635247613524763152476351247635421763542716354276135427631542
763514276354127635472163547261354726315472635147263541726354712635476213547623
154762351476235417623547162354761235476532147653241765324716532476153247651324
765312476534217653427165342761534276513427653142765341276534721653472615347265
134726531472653417265347126534762153476251347625314762534176253471625347612534
765213476523147652341765234716523476152347651234765743216574326157432651743265
714326574132657431265743621574362517436257143625741362574316257436125743652174
365271436527413652743165274361527436512743657214365724136572431657243615724365
172436571243657421365742316574236157423651742365714236574123657463215746325174
632571463257416325746132574631257463521746352714635274163527461352746315274635
127463572146357241635724613572463157246351724635712463574216357426135742631574
263517426357142635741263574621357462315746235174623571462357416235746123574653
217465327146532741653274615327465132746531274653721465372416537246153724651372
465317246537124653742165374261537426513742653174265371426537412653746215374625
137462531746253714625374162537461253746521374652317465237146523741652374615237
465123746573214657324165732461573246517324657132465731246573421657342615734265
173426571342657314265734126573462157346251734625713462573146257341625734612573
465217346527134652731465273416527346152734651273465721346572314657234165723461
572346517234657123465764321576432517643257164325761432576413257643125764352176
435271643527614352764135276431527643512764357216435726143572641357264315726435
172643571264357621435762413576243157624351762435716243576124357642135764231576
423517642357164235761423576412357645321764532716453276145327641532764513276453
127645372164537261453726415372645137264531726453712645376214537624153762451376
245317624537162453761245376421537642513764253176425371642537614253764125376452
137645231764523716452376145237641523764512376457321645732614573264157326451732
645713264573126457362145736241573624517362457136245731624573612457364215736425
173642571364257316425736142573641257364521736452713645273164527361452736415273
645127364572136457231645723614572364157236451723645712364576321457632415763245
176324571632457613245763124576342157634251763425716342576134257631425763412576
345217634527163452761345276314527634152763451276345721634572613457263145726341
572634517263457126345762134576231457623415762345176234571623457612345767543216
754326175432671543267514326754132675431267543621754362715436275143627541362754
316275436127543672154367251436725413672543167254361725436712543675214367524136
752431675243617524367152436751243675421367542316754236175423671542367514236754
123675463217546327154632751463275416327546132754631275463721546372514637254163
725461372546317254637125463752146375241637524613752463175246371524637512463754
216375426137542631754263715426375142637541263754621375462317546237154623751462
375416237546123754673215467325146732541673254617325467132546731254673521467352
416735246173524671352467315246735124673542167354261735426713542673154267351426
735412673546217354627135462731546273514627354162735461273546721354672315467235
146723541672354617235467123546753214675324167532461753246715324675132467531246
753421675342617534267153426751342675314267534126753462175346271534627513462753
146275341627534612753467215346725134672531467253416725346172534671253467521346
752314675234167523461752346715234675123467564321756432715643275164327561432756
413275643127564372156437251643725614372564137256431725643712564375216437526143
752641375264317526437152643751264375621437562413756243175624371562437516243756
124375642137564231756423715642375164237561423756412375647321564732516473256147
325641732564713256473125647352164735261473526417352647135264731526473512647356
214735624173562471356247315624735162473561247356421735642713564273156427351642
735614273564127356472135647231564723516472356147235641723564712356475321647532
614753264175326471532647513264753126475362147536241753624715362475136247531624
753612475364217536427153642751364275316427536142753641275364721536472513647253
164725361472536417253647125364752136475231647523614752364175236471523647512364
756321475632417563247156324751632475613247563124756342175634271563427516342756
134275631427563412756347215634725163472561347256314725634172563471256347521634
752613475263147526341752634715263475126347562134756231475623417562347156234751
623475612347567432156743251674325617432567143256741325674312567435216743526174
352671435267413526743152674351267435621743562714356274135627431562743516274356
127435672143567241356724315672435167243561724356712435674213567423156742351674
235617423567142356741235674532167453261745326714532674153267451326745312674536
217453627145362741536274513627453162745361274536721453672415367245136724531672
453617245367124536742153674251367425316742536174253671425367412536745213674523
167452361745236714523674152367451236745632174563271456327415632745163274561327
456312745637214563724156372451637245613724563172456371245637421563742516374256
137425631742563714256374125637452163745261374526317452637145263741526374512637
456213745623174562371456237415623745162374561237456732145673241567324516732456
173245671324567312456734215673425167342561734256713425673142567341256734521673
452617345267134526731452673415267345126734562173456271345627314562734156273451
627345612734567213456723145672341567234516723456172345671234567
n = 8 -> Stack overflow!
The stack overflow for n = 8 is mostly caused by the bagof predicate. Anyone can remove this error?
This is my attempt, which appears to have a bug, but I don't see where it is exactly. If you see it, please let me know where it is.
First, let's follow the algorithm sketched by Wikipedia for N<5:
super([X], [X], 1).
super([X|Xs], Super, N) :-
%% obtain the superpermutation of N-1
super(Xs, Super0, N0),
succ(N0, N),
%% split Super0 into its individual permutations
split_permutations(N0, Super0, Permutations),
%% insert X into the middle of a copy of each of these
maplist(insert_surrounded(X), Permutations, NewPermutations),
%% concatenate the new permutations and deduplicate them
append(NewPermutations, SuperWithDupes),
deduplicate(SuperWithDupes, Super).
Now to make this go, we will need quite a few utility predicates, starting with deduplication and testing whether a sublist is a permutation:
deduplicate([X], [X]).
deduplicate([X,Y|Xs], Dedup) :-
(X == Y ->
deduplicate([Y|Xs], Dedup)
;
deduplicate([Y|Xs], Dedup1),
Dedup = [X|Dedup1]
).
is_unique([]).
is_unique([X|Xs]) :-
\+ memberchk(X, Xs),
is_unique(Xs).
Now to obtain the permutations from the N-1 call, I have split_permutations/3 which gives you back the permutations (in order) of an earlier call to super/2:
split_permutations(_, [], []).
split_permutations(Length, [X|Xs], Permutations) :-
split_permutations(Length, Xs, Permutations1),
length(L, Length),
(prefix(L, [X|Xs]), is_unique(L) ->
Permutations = [L|Permutations1]
;
Permutations = Permutations1
).
insert_surrounded/3 uses SWI-Prolog trick append/2:
insert_surrounded(X, Permutation, NewPermutation) :-
append([Permutation, [X], Permutation], NewPermutation).
For my own edification, I wrote a thing to output a list slammed together so that I could compare my output to Wikipedia's:
write_string([]) :- nl.
write_string([X|Xs]) :- write(X), write_string(Xs).
For N=3, I get the same thing as Wikipedia:
?- super([3,2,1], X, Y), write_string(X).
123121321
X = [1, 2, 3, 1, 2, 1, 3, 2, 1],
Y = 3 .
I note with some dissatisfaction that using the first item in the list rather than the last is forcing me to present the input reversed. I would believe it if this was my problem with the next output, which is N=4:
12341232314231312431213421313241323214321 (mine)
123412314231243121342132413214321 (Wikipedia)
I am thinking now that it would have been better to generate some sort of superpermutation tree, and then have an output or serialization routine that handles the deduplication, and then constructing the tree leaves it in a broken-up state throughout the program until the last step. It seems inefficient and/or a good way to introduce bugs to do the concatenating and then immediately break the concatenated strings back apart. I don't think that is essential to the algorithm though. Perhaps another intrepid Prolog programmer will see a trick here!

Sliding tile puzzle with varying tile size using logic programming

So I am trying to solve this Booth arrangement problem given here. It is basically a sliding tile puzzle where one (booth)tile has to reach a target spot and in the end all other (booths)tiles should be in their original location. Each tile/booth has a dimension and following are the input fact and relation descriptions:
One fact of the form room(W,H), which specifies the width W and
height H of the room (3 ≤ W, H ≤ 20).
One fact booths(B), which
specifies the number of booths (1 ≤ B ≤ 20).
A relation that consists
of facts of the form dimension(B, W, H), which specifies the width W
and height H of booth B.
A relation consisting of facts of the form
position(B, W, H), specifying the initial position (W, H) of booth B.
One fact target(B, W, H), specifying the destination (W, H) of the
target booth B.
An additional fact horizon(H) gives an upper bound on
the number of moves to be performed.
The program is supposed to read input facts from a file but I am just trying to do the solving so I have just copy pasted one possible input for now, and I have written some basic clauses:
room(3, 3).
booths(3).
dimension(1, 2, 1).
dimension(2, 2, 1).
dimension(3, 1, 1).
position(1, 0, 1).
position(2, 1, 2).
position(3, 0, 0).
target(3, 0, 2).
horizon(10).
xlim(X) :- room(X,_).
ylim(X) :- room(_,X).
sum(X,Y,Z) :- Z is X+Y .
do(position(B,X,Y),movedown,position(B,X,Z)) :- Y > 0 , sum(Y,-1,Z) .
do(position(B,X,Y),moveup,position(B,X,Z)) :- ylim(L), Y < L , sum(Y,1,Z) .
do(position(B,X,Y),moveleft,position(B,Z,Y)) :- X > 0 , sum(X,-1,Z) .
do(position(B,X,Y),moveright,position(B,Z,Y)) :- xlim(L), X < L, sum(X,1,Z) .
noverlap(B1,B2) :-
position(B1,X1,Y1),
position(B2,X2,Y2),
ends(Xe1,Ye1,B1),
ends(Xe2,Ye2,B2),
( Xe1 < X2 ;
Xe2 < X1 ;
Ye1 < Y2 ;
Ye2 < Y1 ).
ends(Xe,Ye,B) :-
dimension(B,W,H),
position(B,X,Y),
Xe is X+W-1,
Ye is Y+H-1.
between(X,Y,Z) :-
X > Y ,
X < Z .
validMove(M,B) :- do(position(B,X,Y),M,position(B,Xn,Yn)) .
I am new to Prolog and I am stuck on how to go from here, I have the no_overlap rule so I can test if a move is valid or not but I am not sure how with the current clauses that I have. My current clauses for moves do/3 probably needs some modification. Any pointers?.
You need to express the task in terms of relations between states of the puzzle. Your current clauses determine the validity of a single move, and can also generate possible moves.
However, that is not sufficient: You need to express more than just a single move and its effect on a single tile. You need to encode, in some way, the state of the whole puzzle, and also encode how a single move changes the state of the whole task.
For a start, I recommend you think about a relation like:
world0_move_world(W0, M, W) :- ...
and express the relation between a given "world" W0, a possible move M, and the resulting world W. This relation should be so general as to generate, on backtracking, each move M that is possible in W0. Ideally, it should even work if W0 is a free variable, and for this you may find clpfd useful: Constraints allow you to express arithmetic relations in a much more general way than you are currently using.
Once you have such a relation, the whole task is to find a sequence Ms of moves such that any initial world W0 is transformed to a desired state W.
Assuming you have implemented world0_move_world/3 as a building block, you can easily lift this to lists of moves as follows (using dcg):
moves(W0) --> { desired_world(W0) }.
moves(W0) --> [M], { world0_move_world(W0, M, W) }, moves(W).
You can then use iterative deepening to find a shortest sequence of moves that solves the puzzle:
?- length(Ms, _), initial_world(W0), phrase(moves(W0), Ms).

From 8-Queens solution to more generic n-Queens solution in Prolog

I am studying Prolog for an universitary exame and I have some problem with the following exercise.
I have the following classic solution of 8-Queens problem (and this is not a problem for me), Modifying this solution I have to create a new solution for the more generic n-Queens problem that handle a variable number of queens.
solution([]).
solution([X/Y|Others]) :- solution(Others),
member(Y,[1,2,3,4,5,6,7,8]),
noattack(X/Y, Others).
noattack(_,[]).
noattack(X/Y, [X1/Y1 | Others]) :-
Y =\= Y1, % Q e Q1 sono su righe diverse
% Q e Q1 sono su diagonali diverse:
Y1-Y =\= X1-X,
Y1-Y =\= X-X1,
% Q non attacca regine nella sottolista Others:
noattack( X/Y, Others).
% TEMPLATE DELLE SOLUZIONI: c'è una regina su ogni colonna:
template([1/Y1,2/Y2,3/Y3,4/Y4,5/Y5,6/Y6,7/Y7,8/Y8]).
Ok, this program look pretty simple: I have a list of queen that have that they must not attack each other.
If the list of queen is empty there is not the possibility that a queen attack another queen in the list, so the empty list is a solution of the problem (it is the base case of the solution)
*If the list of queen is not empty I can divide it into [X/Y|Others] where X/Y rappresent position on the board of the first queen in the list *(the position is rappresentend by the couple (X,Y) where X is the column and Y the line)
So, it is TRUE that the list [X/Y|Others] is a SOLUTION of the problem if the following relations are true:
The sublist Others is itself a solution (Others don't contain queen that attack some other queen in the list)
Y belongs belongs to an integer value between 1 and 8 (because I have 8 line)
The first queen of the list don't attacck the others queens in the sublist Others
Then it is defined the noattack relation that specify when I can say that it is true that a queen don't attack another queen (this is pretty simple: they can't stay on the same line, on the same column, on the same diagonal)
Finally I have a solution template that simplify my life constraining the X value with value from 1 to 8 (because I know that 2 queens can't stay on the same columns...so every queen in the solution stay on a different column from all others queens)
So I think that the biggest problem it is on the line in which I specify the number of columns:
member(Y,[1,2,3,4,5,6,7,8])
and on the line in which I define the solution template:
template([1/Y1,2/Y2,3/Y3,4/Y4,5/Y5,6/Y6,7/Y7,8/Y8]).
I have no idea about how to extend the previous solution to handle a variable number of queens.
seems easy, passing around the size:
solution(_, []).
solution(N, [X/Y|Others]) :-
solution(N, Others),
between(1, N, Y),
noattack(X/Y, Others).
noattack(_,[]).
noattack(X/Y, [X1/Y1 | Others]) :-
Y =\= Y1, % Q e Q1 sono su righe diverse
Y1-Y =\= X1-X, % Q e Q1 sono su diagonali diverse
Y1-Y =\= X-X1,
noattack( X/Y, Others). % Q non attacca regine nella sottolista Others
% TEMPLATE DELLE SOLUZIONI: c'è una regina su ogni colonna:
template(N, L) :-
findall(I/_, between(1,N,I), L).
test:
?- N=6, template(N, L), solution(N, L).
N = 6,
L = [1/5, 2/3, 3/1, 4/6, 5/4, 6/2] ;
N = 6,
L = [1/4, 2/1, 3/5, 4/2, 5/6, 6/3] ;
N = 6,
L = [1/3, 2/6, 3/2, 4/5, 5/1, 6/4] ;
N = 6,
L = [1/2, 2/4, 3/6, 4/1, 5/3, 6/5] ;
false.
(I should draw it to say if it's ok...)

8-puzzle has a solution in prolog using manhattan distance

The 8-puzzle will be represented by a 3x3 list of lists positions where the empty box will be represented by the value 9, as shown below: [[9,1,3],[5,2,6],[4,7,8]]
Possibility Solution: Only half of the initial positions of the 8-puzzle are solvable. There is a formula that allows to know from the beginning if you can solve the puzzle.To determine whether an 8-puzzle is solvable, for each square containing a value N is calculated how many numbers less than N there after the current cell. For example, to the initial status:
1 no numbers less then = 0
Empty (9) - has to subsequently 3,5,2,6,4,7,8 = 7
3 have = 1 to 2
5 has subsequently to 2,4 = 2
2 no number under it happen = 0
6 is subsequently 4 = 1
4 no numbers less then = 0
7 no minor numbers after = 0
8 no numbers less then = 0
After that, we calculate the Manhattan distance between the position of the empty and
position (3.3). For the above example, the empty box is in the position (1.2), so
Manhattan distance that is:
d = abs (3-1) + abs (3-2) = 3
Finally, add up all the calculated values​​. If the result is even, implies that the
puzzle is solvable, but it is odd not be resolved.
0 +7 +1 +2 +0 +1 +0 +0 +0 +3 = 14
The solution is designed to create a knowledge base with all possible states of a number on the board and we'll see how many numbers less than N there after the current position.
Here's my code:
%***********************Have Solution*********************************
posA(9,8). posA(8,7). posA(7,6). posA(6,5). posA(5,4). posA(4,3). posA(3,2). posA(2,1). posA(1,0).
posB(9,7). posB(8,7). posB(8,6). posB(7,6). posB(7,5). posB(7,4).
posB(6,5). posB(6,4). posB(6,3). posB(6,2). posB(5,4). posB(5,3). posB(5,2). posB(5,1). posB(5,0).
posB(4,3). posB(4,2). posB(3,2). posB(3,1). posB(2,1). posB(2,0). posB(1,0).
posC(9,6). posC(8,6). posC(8,5). posC(7,6). posC(7,5). posC(7,4). posC(6,5). posC(6,4). posC(6,3).
posC(5,4). posC(5,3). posC(5,2). posC(4,3). posC(4,2). posC(4,1). posC(4,0).
posC(3,2). posC(3,1). posC(3,0). posC(2,1). posC(1,0).
posD(9,5). posD(8,5). posD(8,4). posD(7,5). posD(7,4). posD(7,3). posD(6,5). posD(6,4). posD(6,3).
posD(6,2). posD(5,4). posD(5,3). posD(5,2). posD(5,1). posD(4,3). posD(4,2). posD(4,1). posD(5,0).
posD(3,2). posD(3,1). posD(3,0). posD(2,1). posD(1,0).
posE(9,4). posE(8,4). posE(8,3). posE(7,4). posE(7,3). posE(7,2). posE(6,4). posE(6,3). posE(6,2). posE(6,1).
posE(5,4). posE(5,3). posE(5,2). posE(5,1). posE(5,0). posE(4,3). posE(4,2). posE(4,1). posE(4,0).
posE(3,2). posE(3,1). posE(3,0). posE(2,1). posE(2,0). posE(1,0).
posF(9,3). posF(8,3). posF(8,2). posF(7,1). posF(7,2). posF(7,3). posF(6,0). posF(6,1). posF(6,2).
posF(6,3). posF(5,0). posF(5,1). posF(5,2). posF(5,3). posF(4,0). posF(4,1). posF(4,2). posF(4,3).
posF(2,0). posF(2,1). posF(3,0). posF(3,1). posF(3,2). posF(1,0).
posG(9,2). posG(8,0). posG(8,1). posG(8,2). posG(7,0). posG(7,1). posG(7,2).
posG(6,0). posG(6,1). posG(6,2). posG(5,0). posG(5,1). posG(5,2). posG(4,0). posG(4,1). posG(4,2).
posG(3,0). posG(3,1). posG(3,2). posG(2,0). posG(2,1). posG(1,0).
posH(9,1). posH(8,0). posH(8,1). posH(7,0). posH(7,1). posH(6,0). posH(6,1). posH(5,0). posH(5,1).
posH(4,0). posH(4,1). posH(3,0). posH(3,1). posH(2,0). posH(1,1). posH(1,0).
posI(9,0). posI(8,0). posI(7,0). posI(6,0). posI(5,0). posI(4,0). posI(3,0). posI(2,0). posI(1,0).
haveSolution([[A,B,C],[D,E,F],[G,H,I]]):- distManhattan([A,B,C,D,E,F,G,H,I], Z),
posA(A,Pa), posB(B,Pb), posC(C,Pc),
posD(D,Pd), posE(E,Pe), posF(F,Pf),
posG(G,Pg), posH(H,Ph), posI(I,Pi),
P is Pa+Pb+Pc+Pd+Pe+Pf+Pg+Ph+Pg+Pi+Z, 0 is P mod 2,
write('The 8-puzzle have solution').
%%*************************Manhattan distance***********************
distManhattan([A,B,C,D,E,F,G,H,I], Dist):- A=9, Dist is abs(3-1)+abs(3-1), !;
B=9, Dist is abs(3-1)+abs(3-2), !;
C=9, Dist is abs(3-1)+abs(3-3), !;
D=9, Dist is abs(3-2)+abs(3-1), !;
E=9, Dist is abs(3-2)+abs(3-2), !;
F=9, Dist is abs(3-2)+abs(3-3), !;
G=9, Dist is abs(3-3)+abs(3-1), !;
H=9, Dist is abs(3-3)+abs(3-2), !;
I=9, Dist is abs(3-3)+abs(3-3).
The problem is that I am making a mistake because there are situations where I can have more than one alternative, eg>:
| 1 | 9 | 3 |
| 5 | 2 | 6 |
| 4 | 7 | 8 |
posA(1,0)+posB(9,7)+posC(3,1)+posD(5,2)+posE(2,0)+posF(6,1)+posG(4,0)+posH(7,0)+posI(8,0).
The right solution for posC(C,Pc) is posC(3,1), that is 1; but there are other ramifications that sometimes cause incorrect outputs ... what am I doing wrong in my code and how I can change it?
This answer looks at the problem from a different point of view:
Single board configurations are represented using the compound structure board/9.
Configurations that are equal up to sliding a single piece are connected by relation m/2.
So let's define m/2!
m(board(' ',B,C,D,E,F,G,H,I), board(D, B ,C,' ',E,F,G,H,I)).
m(board(' ',B,C,D,E,F,G,H,I), board(B,' ',C, D ,E,F,G,H,I)).
m(board(A,' ',C,D,E,F,G,H,I), board(' ',A, C , D, E ,F,G,H,I)).
m(board(A,' ',C,D,E,F,G,H,I), board( A ,C,' ', D, E ,F,G,H,I)).
m(board(A,' ',C,D,E,F,G,H,I), board( A ,E, C , D,' ',F,G,H,I)).
m(board(A,B,' ',D,E,F,G,H,I), board(A,' ',B,D,E, F ,G,H,I)).
m(board(A,B,' ',D,E,F,G,H,I), board(A, B ,F,D,E,' ',G,H,I)).
m(board(A,B,C,' ',E,F,G,H,I), board(' ',B,C,A, E ,F, G ,H,I)).
m(board(A,B,C,' ',E,F,G,H,I), board( A ,B,C,E,' ',F, G ,H,I)).
m(board(A,B,C,' ',E,F,G,H,I), board( A ,B,C,G, E ,F,' ',H,I)).
m(board(A,B,C,D,' ',F,G,H,I), board(A, B ,C,' ',D, F ,G, H ,I)).
m(board(A,B,C,D,' ',F,G,H,I), board(A,' ',C, D ,B, F ,G, H ,I)).
m(board(A,B,C,D,' ',F,G,H,I), board(A, B ,C, D ,F,' ',G, H ,I)).
m(board(A,B,C,D,' ',F,G,H,I), board(A, B ,C, D ,H, F ,G,' ',I)).
m(board(A,B,C,D,E,' ',G,H,I), board(A,B,' ',D, E ,C,G,H, I )).
m(board(A,B,C,D,E,' ',G,H,I), board(A,B, C ,D,' ',E,G,H, I )).
m(board(A,B,C,D,E,' ',G,H,I), board(A,B, C ,D, E ,I,G,H,' ')).
m(board(A,B,C,D,E,F,' ',H,I), board(A,B,C,' ',E,F,D, H ,I)).
m(board(A,B,C,D,E,F,' ',H,I), board(A,B,C, D ,E,F,H,' ',I)).
m(board(A,B,C,D,E,F,G,' ',I), board(A,B,C,D,' ',F, G ,E, I )).
m(board(A,B,C,D,E,F,G,' ',I), board(A,B,C,D, E ,F,' ',G, I )).
m(board(A,B,C,D,E,F,G,' ',I), board(A,B,C,D, E ,F, G,I,' ')).
m(board(A,B,C,D,E,F,G,H,' '), board(A,B,C,D,E,' ',G, H ,F)).
m(board(A,B,C,D,E,F,G,H,' '), board(A,B,C,D,E, F ,G,' ',H)).
Almost done!
To connect the steps, we use the meta-predicate path/4 together
with length/2 for performing iterative deepening.
The following problem instances are from #CapelliC's answer:
?- length(Path,N), path(m,Path,/* from */ board(1,' ',3,5,2,6,4,7, 8 ),
/* to */ board(1, 2 ,3,4,5,6,7,8,' ')).
N = 6, Path = [board(1,' ',3,5,2,6,4,7,8), board(1,2,3,5,' ',6,4,7,8),
board(1,2,3,' ',5,6,4,7,8), board(1,2,3,4,5,6,' ',7,8),
board(1,2,3,4,5,6,7,' ',8), board(1,2,3,4,5,6,7,8,' ')] ? ;
N = 12, Path = [board(1,' ',3,5,2,6,4,7,8), board(1,2,3,5,' ',6,4,7,8),
board(1,2,3,5,7,6,4,' ',8), board(1,2,3,5,7,6,' ',4,8),
board(1,2,3,' ',7,6,5,4,8), board(1,2,3,7,' ',6,5,4,8),
board(1,2,3,7,4,6,5,' ',8), board(1,2,3,7,4,6,' ',5,8),
board(1,2,3,' ',4,6,7,5,8), board(1,2,3,4,' ',6,7,5,8),
board(1,2,3,4,5,6,7,' ',8), board(1,2,3,4,5,6,7,8,' ')] ? ;
...
?- length(Path,N), path(m,Path,/* from */ board(8,7,4,6,' ',5,3,2, 1 ),
/* to */ board(1,2,3,4, 5 ,6,7,8,' ')).
N = 27, Path = [board(8,7,4,6,' ',5,3,2,1), board(8,7,4,6,5,' ',3,2,1),
board(8,7,4,6,5,1,3,2,' '), board(8,7,4,6,5,1,3,' ',2),
board(8,7,4,6,5,1,' ',3,2), board(8,7,4,' ',5,1,6,3,2),
board(' ',7,4,8,5,1,6,3,2), board(7,' ',4,8,5,1,6,3,2),
board(7,4,' ',8,5,1,6,3,2), board(7,4,1,8,5,' ',6,3,2),
board(7,4,1,8,5,2,6,3,' '), board(7,4,1,8,5,2,6,' ',3),
board(7,4,1,8,5,2,' ',6,3), board(7,4,1,' ',5,2,8,6,3),
board(' ',4,1,7,5,2,8,6,3), board(4,' ',1,7,5,2,8,6,3),
board(4,1,' ',7,5,2,8,6,3), board(4,1,2,7,5,' ',8,6,3),
board(4,1,2,7,5,3,8,6,' '), board(4,1,2,7,5,3,8,' ',6),
board(4,1,2,7,5,3,' ',8,6), board(4,1,2,' ',5,3,7,8,6),
board(' ',1,2,4,5,3,7,8,6), board(1,' ',2,4,5,3,7,8,6),
board(1,2,' ',4,5,3,7,8,6), board(1,2,3,4,5,' ',7,8,6),
board(1,2,3,4,5,6,7,8,' ')] ? ;
N = 29, Path = [...] ? ;
...
Here is a solver, not an answer to the original question. Joel76 already addressed the problem in comments, and thus he will get the deserved reputation when he will answer.
But the 8-puzzle was interesting to solve, and pose some efficiency problem. Here is my best effort, where I used library(nb_set) in attempt to achieve reasonable efficiency on full solutions enumeration.
Note: nb_set is required to keep track of visited also on failed paths. The alternative is a :- dynamic visited/1. but that turned out to be too much slow.
/* File: 8-puzzle.pl
Author: Carlo,,,
Created: Feb 4 2013
Purpose: solve 8-puzzle
*/
:- module(eight_puzzle,
[eight_puzzle/3
]).
:- use_module(library(nb_set)).
% test cases from Stack Overflow thread with Joel76
test0(R) :- eight_puzzle([1,2,3,4,5,6,7,8,0], [1,0,3, 5,2,6, 4,7,8], R).
test1(R) :- eight_puzzle([1,2,3,4,5,6,7,8,0], [8,7,4, 6,0,5, 3,2,1], R).
%% eight_puzzle(+Target, +Start, -Moves) is ndet
%
% public interface to solver
%
eight_puzzle(Target, Start, Moves) :-
empty_nb_set(E),
eight_p(E, Target, Start, Moves).
%% -- private here --
eight_p(_, Target, Target, []) :-
!.
eight_p(S, Target, Current, [Move|Ms]) :-
add_to_seen(S, Current),
setof(Dist-M-Update,
( get_move(Current, P, M),
apply_move(Current, P, M, Update),
distance(Target, Update, Dist)
), Moves),
member(_-Move-U, Moves),
eight_p(S, Target, U, Ms).
%% get_move(+Board, +P, -Q) is semidet
%
% based only on coords, get next empty cell
%
get_move(Board, P, Q) :-
nth0(P, Board, 0),
coord(P, R, C),
( R < 2, Q is P + 3
; R > 0, Q is P - 3
; C < 2, Q is P + 1
; C > 0, Q is P - 1
).
%% apply_move(+Current, +P, +M, -Update)
%
% swap elements at position P and M
%
apply_move(Current, P, M, Update) :-
assertion(nth0(P, Current, 0)), % constrain to this application usage
( P > M -> (F,S) = (M,P) ; (F,S) = (P,M) ),
nth0(S, Current, Sv, A),
nth0(F, A, Fv, B),
nth0(F, C, Sv, B),
nth0(S, Update, Fv, C).
%% coord(+P, -R, -C)
%
% from linear index to row, col
% size fixed to 3*3
%
coord(P, R, C) :-
R is P // 3,
C is P mod 3.
%% distance(+Current, +Target, -Dist)
%
% compute Manatthan distance between equals values
%
distance(Current, Target, Dist) :-
aggregate_all(sum(D),
( nth0(P, Current, N), coord(P, Rp, Cp),
nth0(Q, Target, N), coord(Q, Rq, Cq),
D is abs(Rp - Rq) + abs(Cp - Cq)
), Dist).
%% add_to_seen(+S, +Current)
%
% fail if already in, else store
%
add_to_seen(S, [A,B,C,D,E,F,G,H,I]) :-
Sig is
A*100000000+
B*10000000+
C*1000000+
D*100000+
E*10000+
F*1000+
G*100+
H*10+
I,
add_nb_set(Sig, S, true)
Test case that Joel76 posed to show the bug in my first effort:
?- time(eight_puzzle:test1(R)).
% 25,791 inferences, 0,012 CPU in 0,012 seconds (100% CPU, 2137659 Lips)
R = [5, 8, 7, 6, 3, 0, 1, 2, 5|...] ;
% 108,017 inferences, 0,055 CPU in 0,055 seconds (100% CPU, 1967037 Lips)
R = [5, 8, 7, 6, 3, 0, 1, 2, 5|...] ;
% 187,817,057 inferences, 93,761 CPU in 93,867 seconds (100% CPU, 2003139 Lips)
false.

How to add polynoms in Prolog?

I have the following task:
Write a method that will add two polynoms. I.e 0+2*x^3 and 0+1*x^3+2*x^4 will give 0+3*x^3+2*x^4.
I also wrote the following code:
add_poly(+A1*x^B1+P1,+A2*x^B2+P2,+A3*x^B3+P3):-
(
B1=B2,
B3 = B2,
A3 is A1+A2,
add_poly(P1,P2,P3)
;
B1<B2,
B3=B1,
A3=A1,
add_poly(P1,+A2*x^B2+P2,P3)
;
B1>B2,
B3=B2,
A3=A2,
add_poly(+A1*x^B1+P1,P2,P3)
).
add_poly(X+P1,Y+P2,Z+P3):-
Z is X+Y,
add_poly(P1,P2,P3).
My problem is that I don't know how to stop. I would like to stop when one the arguments is null and than to append the second argument to the third one. But how can I check that they are null?
Thanks.
Several remarks:
Try to avoid disjunctions (;)/2 in the beginning. They need special indentation to be readable. And they make reading a single rule more complex — think of all the extra (=)/2 goals you have to write and keep track of.
Then, I am not sure what you can assume about your polynomials. Can you assume they are written in canonical form?
And for your program: Consider the head of your first rule:
add_poly(+A1*x^B1+P1,+A2*x^B2+P2,+A3*x^B3+P3):-
I will generalize away some of the arguments:
add_poly(+A1*x^B1+P1,_,_):-
and some of the subterms:
add_poly(+_+_,_,_):-
This corresponds to:
add_poly(+(+(_),_),_,_) :-
Not sure you like this.
So this rule applies only to terms starting with a prefix + followed by an infix +. At least your sample data did not contain a prefix +.
Also, please remark that the +-operator is left associative. That means that 1+2+3+4 associates to the left:
?- write_canonical(1+2+3+4).
+(+(+(1,2),3),4)
So if you have a term 0+3*x^3+2*x^4 the first thing you "see" is _+2*x^4. The terms on the left are nested deeper.
For your actual question (how to stop) - you will have to test explicitly that the leftmost subterm is an integer, use integer/1 - or maybe a term (*)/2 (that depends on your assumptions).
I assume that polynomials you are speaking of are in 1 variable and with integer exponents.
Here a procedure working on normal polynomial form: a polynomial can be represented as a list (a sum) of factors, where the (integer) exponent is implicitly represented by the position.
:- [library(clpfd)].
add_poly(P1, P2, Sum) :-
normalize(P1, N1),
normalize(P2, N2),
append(N1, N2, Nt),
aggregate_all(max(L), (member(M, Nt), length(M, L)), LMax),
maplist(rpad(LMax), Nt, Nn),
clpfd:transpose(Nn, Tn),
maplist(sumlist, Tn, NSum),
denormalize(NSum, Sum).
rpad(LMax, List, ListN) :-
length(List, L),
D is LMax - L,
zeros(D, Z),
append(List, Z, ListN).
% the hardest part is of course normalization: here a draft
normalize(Ts + T, [N|Ns]) :-
normalize_fact(T, N),
normalize(Ts, Ns).
normalize(T, [N]) :-
normalize_fact(T, N).
% build a list with 0s left before position E
normalize_fact(T, Normal) :-
fact_exp(T, F, E),
zeros(E, Zeros),
nth0(E, Normal, F, Zeros).
zeros(E, Zeros) :-
length(Zeros, E),
maplist(copy_term(0), Zeros).
fact_exp(F * x ^ E, F, E).
fact_exp(x ^ E, 1, E).
fact_exp(F * x, F, 1).
fact_exp(F, F, 0).
% TBD...
denormalize(NSum, NSum).
test:
?- add_poly(0+2*x^3, 0+1*x^3+2*x^4, P).
P = [0, 0, 0, 3, 2]
the answer is still in normal form, denormalize/2 should be written...

Resources