name = 'dup/2' slug = 'duplicate the elements of a list' description = '''\

dup(L1, L2): the list L2 is obtained from L1 by duplicating every element.

?- dup([1,2], X).
  X = [1,1,2,2].
?- dup([1,2,3], X).
  X = [1,1,2,2,3,3].
''' plan = ['''

This is an exercise in classic recursion. Let's be brave and assume that we already have a duplicated tail of the list. Then all we need to do is to duplicate the head (H becomes H, H) and add this at the start of the duplicated tail.

''', '''\

A base case must be elementary, right? What if the list doesn't contain any elements at all, what is the result in this case?

''', '''\

If we have a duplicated tail DT and put two heads [H, H] in front of it, then that is exactly the duplicated list.

And how do we get the duplicated tail? Since the tail is smaller than the whole list, we can use recursion on it!

'''] hint = { 'eq_instead_of_equ': '''\

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 dup/2 more general (e.g. able to work with output arguments becoming inputs).

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_missing_[]': '''\

Your base case makes perfect sense, but it doesn't work for a very specific case: an empty list. Tweak it a little bit. However, don't write two base cases, because that will result in a new problem: the (albeit correct) solutions will all be repeated twice.

''', 'base_case_arbitrary': '''\

How can the result of duplicating an empty list be an arbitrary list or an unassigned variable? As the mathematicians would say: "Two times zero is zero and not just anything!"

If your base case is dup([], _)., rethink it! What is the result of duplicating the elements of an empty list?

''', 'base_case': '''\

Did you think of a base case? Which list is the easiest to "duplicate"?

''', '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 an empty list [] is equal to a list with exactly three elements [A,B,C], or something similarly impossible).

''', 'timeout': '''\

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?

''', 'forcing_result_onto_recursion': '''

Don't force the result onto recursion, don't tell it what it should return. Just assume it will do its job. If this assumption is correct, then the rule will work for a larger case.

Is your recursive call of the form dup(T, [H,H|...])? This forces the recursive call to return the duplicated head at the start of the list. But it doesn't know of this head, because you just took it away! Adding the duplicated head to the result, returned by the recursive call, is your job. To put it shortly, add the duplicated H outside of the recursive call.

''', }