0

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.

mkll
  • 41
  • 9

3 Answers3

0

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).
Scott Hunter
  • 48,888
  • 12
  • 60
  • 101
  • Ya, that's the point. I know how to insert at the end but not in the middle of the database. Thanks anyway. – mkll Jan 05 '12 at 17:17
  • If I want to insert an element in the middle of the list, how would you update the rest of the list? I mean we have to change the position of each element in the list. Would you update the position number,before the inserting, from the position to insert to the end of the list and then, finally, insert the element in the right position? – mkll Jan 08 '12 at 18:41
  • Note that the outline above says NOTHING about inserting in the middle: retract the last fact that's in the wrong position, recursively add your new fact, and re-assert the fact you retracted (with the position number appropriate to its new position, which looks like 1 more than before). – Scott Hunter Jan 08 '12 at 20:11
  • But I should implement that as if I wouldn't know the amount of facts after the position in which I want to insert the new element. I edited the code according to this last comment I've left. – mkll Jan 08 '12 at 21:52
  • You've changed both your insert clause and, apparently, what long now means. Maybe you should explain them via comments? – Scott Hunter Jan 08 '12 at 22:12
  • And after inserirl(b,3,9), should 8 be at position 4, 3 be at position 5, etc? – Scott Hunter Jan 09 '12 at 00:54
  • Exactly! That's the functioning. – mkll Jan 09 '12 at 09:25
0

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.

Scott Hunter
  • 48,888
  • 12
  • 60
  • 101
  • I'm so grateful for your help. Then My question is when I have to call recursively? Just after I've inserted the new item or at the end, after putting back the removed item? – mkll Jan 09 '12 at 09:29
  • The recursive call handles inserting the new item (that is what its written to do: insert an item into a list). – Scott Hunter Jan 09 '12 at 10:50
  • Sorry. It is the section "My last try" – mkll Jan 09 '12 at 15:27
  • By the way, what do you mean with "change the facts to make the list 1 shorter"? Thanks – mkll Jan 09 '12 at 16:33
0

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!

Scott Hunter
  • 48,888
  • 12
  • 60
  • 101
  • But what I want is to increase the "long" because I've inserted a new element in the list. – mkll Jan 09 '12 at 16:39
  • Ultimately, you will increase long, but you have to decrease it first so you can shrink the list to the point where your addition can be added to the end of the shrunken list; once your new guy has been added, then long will go back up as you put the items you took off back on, in their new positions. – Scott Hunter Jan 09 '12 at 17:06