name = 'sins/3' slug = 'insert an element at correct position into a sorted list' description = '''\
sins(X, SortedList, NewList)
: the list NewList
is obtained by inserting X
into SortedList
at the correct position to preserve the non-decreasing order of elements.
?- sins(4, [1,2,3,5], L). L = [1,2,3,4,5]. ?- sins(3, [1,2,3,4], L). L = [1,2,3,3,4].''' plan = ['''\
For starters, let's remember that we're inserting into a sorted list. Let's go through the list, element by element, until we find a proper place for the new element.
''', '''\Step by step you compare the new element with the list's current head. The heads will be increasing in value as the list is sorted. Which means that at some point the new element will become smaller than the current head, right?
''', '''\If the new element X
is larger than the current head H
, then we insert it
somewhere in the tail -- this will be taken care of by the recursion, as always, right? And if it's not larger,
then we found the proper place for the new element and we insert it now in front of the current
head H
! You know how to put two elements before the tail at the same time, right? (It's the
same as taking two elements out.)
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).
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?
Did you think of a base case? This will probably be the case when you (finally) insert a new element into the list.
''', 'recursive_case': '''\The base case is ok. However, what about the general recursive case?
''', 'predicate_always_false': '''\It seems your predicate is always "false". Did you give it the correct name, or is it perhaps misspelled?
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 X
is simultaneously smaller and greater than
Y
, 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?
''', 'bad_[]_case': '''\What's the result of inserting an element into an empty list? Surely not an empty list or even an arbitrary result (a variable without an assigned value)?
''', 'returns_elem_instead_of_list': '''\You have to return a list, not an element.
''', 'maxEl_base_case_missing': '''\The solution is almost correct. But you probably forgot one specific case. What happens if you're trying to insert a new largest element into the list? Try the following query.
?- sins(9, [1,2,3,4,5], L).
Hmmm, what should be the ordering of the new element and the current head of the list?
?- sins(3, [1,2,4,5,6], L).
Did you forget that duplicates are also allowed? The first query below works fine, the other one doesn't.
?- sins(3, [1,2,4,5,6], L).
?- sins(3, [1,2,3,4,5], L).
Did you "protect" (with a condition) both options (branches)? Be careful, if one branch doesn't have a condition, the first solution returned will probably be correct, but it will leave the door open for other solutions which will not be correct. The semicolon stands for logical OR, not logical XOR. This means that prolog can still search for solutions in the other branch even if the first branch's condition is satisfied! That's why you need both conditions.
Try the following query and ask for more solutions.
?- sins(3, [1,2,4,5,6], L).
Did you forget to return the heads, removed before the recursion, into the list? I did that, too... ;)
Look what happens with the query below and you'll immediately understand the error.
?- sins(4, [1,2,3,5,6], L).