Question

I need to program a Predicate in Prolog that inserts an element in the indicated position and consequently modifies the position number of the rest of the elements in the list. What I've achieved is the next snippet of code that implements a Predicate which inserts an element at the end of the list. In the database sector, apart from LIST we've got also LONG that indicates the amount of elements in the list. At the end there's some code on my try to implement de predicate. Could anyone tell me what's wrong in there? I'm lost in here.

Domains
name=symbol
position=integer
element=integer
Database
    list(name,position,element)
    long(name,integer)

Predicates
     nondeterm inserirf(element)

Clauses
    list(b,1,1). 
    list(b,2,5). 
    list(b,3,8). 
    list(b,4,3). 
    long(b,4).
    inserirf(V):-
        long(b,X),
        Y=X+1,
        assertz(list(b,Y,V)),
        assertz(long(b,Y)),
        retract(long(b,X)),
        long(b,Q),
        list(b,Q,P),
        write(P),nl.

Goal
    inserirf(7).

My last try:

Predicates
 nondeterm inserirl(nom,pos,element)

Clauses
    list(b,1,1). 
    list(b,2,5). 
    list(b,3,8). 
    list(b,4,3).
    list(b,5,10).
    list(b,6,11). 
    long(b,6).

  inserirl(L,Pos,E):-
  long(L,Long),
  Pos > Long,
  NouLong = Long+1,
  retract( long(L,Long) ),
  assertz( list(L,Pos,NouLong) ),
  assertz( long(L,NouLong) ).


inserirl(L,Pos,E):-
    long(L,X),
    XaPassar=X-1,
    retract(llista(L,Pos,E)),
    retract( long(L,X) ),
    assertz( long(L,XaPassar) ),

    inserirl(L, XaPassar,E),
    long(L,Y),
    Y2=Y+1,
    retract( long(L,Y) ),
    assertz( long(L,Y2) ),
    assertz(llista(L,Pos,E)).

Goal
    inserirl(b,3,9).
% 3 -> position
% 9 -> element
% b -> name of list

Hundreds thanks to any help.

Was it helpful?

Solution

Regarding "My last try":

  1. Why are you retracting the very list fact you are trying to (ultimately) assert?
  2. You have to shorten the list (that is, retract the last element & replace the length) before you can do the recursion (since it has to work on a shorter list).

Note: You'll end up spending a lot of time asserting & retracting long() facts, which you need to keep track of the length, but most of them will "cancel out". A more efficient approach would be to retract the original long(), then pass the length around as an argument, and only re-assert the new long when you're done. But get it working before you worry about optimizing!

OTHER TIPS

To get you started:

  1. Check to see if the inserted item goes at the end; if so, you can use your current code.
  2. If it DOESN'T go at the end: Remove (but remember!) the one currently at the end, recursively try to insert the new item, and then add the item you removed to the now-end (which can be done using your code).

Here's the base case:

inserirl(L,Pos,E):-
  long(L,Len),
  Pos > Len,
  NewLen is Len+1,
  retract( long(L,Len) ),
  assertz( list(L,Pos,NewLen) ),
  assertz( long(L,NewLen) ).

For the recursive case, change the facts to make the list 1 shorter, insert your new item into THAT, and then put back the item you removed onto the end.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top