name = 'insert/3' slug = 'insert an element into list' description = '''\
insert(X, L1, L2)
: the list L2
is obtained from L1
by inserting the element X
at arbitrary position.
?- insert(1, [2,3], L). L = [1,2,3] ; L = [2,1,3] ; L = [2,3,1].''' plan = ['''
Where in the list can we insert a new element X
? Remember that a list has two parts: head and tail.
That means there are two possibilies. That's right, only two -- but in the tail we can again insert either as its
new head or into the tail of the tail. And so on. Recursion to the rescue!
What is the simplest option? Insert at the beginning!
''', '''\How do I insert into the list's tail? Just divide the list into its head and tail, recursively (as the problem is one element smaller now) insert into the tail, and at the end don't forget about the head previously taken away.
''', '''\Recursive step: if we assume NewTail
is the tail with already inserted element X
,
then [H|NewTail]
is the whole list with element X
inserted.
The operator ==
is "stricter" than operator =
in the sense that
for the latter it is enough to be able to make the two operands equal (unification). Perhaps by using =
you can make the predicate insert/3
more general (e.g. able to work with output arguments becoming inputs).
This might come in handy later on!
Of course, you can also solve the exercise without explicit use of either of these two operators, just remember that unification is implicitly performed with the predicate's arguments (head of clause).
''', 'eq_instead_of_equ_markup': '''\Perhaps the operator for unification (=) would be better?
''', 'base_case': '''\Did you think of a base case? In which place in the list is it the easiest to insert a new element?
''', 'recursive_case': '''\The base case is ok. However, what about the general recursive case?
''', 'predicate_always_false': '''\It seems your predicate is
If the name is correct, check whether something else is misspelled, perhaps there is a full stop instead of a comma or vice versa, or maybe you typed a variable name in lowercase?
It is, of course, also possible that your conditions are too restrictive, or even impossible to satisfy
(as would be, for example, the condition that an empty list []
is equal to a list with
exactly three elements [A,B,C]
,
or something similarly impossible).
Is there an infinite recursion at work here? How will it ever stop?
Or perhaps is there a missing, faulty, or simply incompatible (with the general recursive case) base case?
''', 'ins_results_in_empty_list': '''\How can the result of the insertion be an empty list?
If that is your base case, rethink it! What is the result of the insertion?
''', 'ins_results_in_arbitrary_result': '''\How can the result of the insertion be an arbitrary list or an unassigned variable?
If that is your base case, rethink it! What is the result of the insertion?
''', 'lost_heads': '''\The element has been successfully inserted, but all the others before it are lost, right? Did you forget to put the head back at the front of the list after returning from recursion?
Try asking the following query and check all the solutions:
?- insert(q, [a,b,c,d], L).
Did you forget (copy/paste?) and used [X|T]
instead of the more general [H|T]
in the recursive case?
Of the following two queries one works and the other doesn't.
?- insert(d, [d,d,d,d,e,f,g], L).
?- insert(d, [a,b,c,d,e,f,g], L).