name = 'max/2' slug = 'find the largest element in list' description = '''\
max(L, Max)
: Max
is the largest value in list L
.
?- max([5,4,1,6], M). M = 6. ?- max([3,2,2], M). M = 3.''' plan = ['''\
As usual, try to reduce the problem to a smaller one. Say you already have the largest element of the tail...
''', '''\Compare the largest element in the tail (list without head H
) with the value of head H
,
the larger of the two wins and gets returned.
If the given list L
is composed of head H
and tail T
, and if we
assume that some MaxT
is the largest element in T
, and if it's also true that
the value of H
is greater than MaxT
, then H
is the largest element
in L
. Or it is true that H
is smaller than MaxT
, and in this
case MaxT
is the largest element in L
.
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 max/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': '''\Did you think of a base case? What's the shortest list with an obvious largest 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 N
is equal to N + 1
,
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?
''', 'empty_list_base_case': '''\You'll be hard pressed to find the largest element of an empty list. What if you stop the recursion a bit earlier this time?
''', 'list_instead_of_elem_base_case': '''\You should return an element, not a list!
''', 'duplicates_not_covered': '''\The list can contain duplicate elements. Did you think of that?
''', 'args_not_instantiated': '''\The error that prolog reported means that when it encountered an arithmetic operation, not all the values were known.
Did you perhaps forget that conjunction has higher precedence that disjunction and that every prolog's sentence (branch, rule) is independent in terms of the scope of the variables? This could be the problem. Carefully inspect both blocks of code (before and after the semicolon) or both rules.
''', 'unprotected_branch': '''\It seems you didn't "protect" one of the (conditional) branches. Both branches (of the disjunction) typically require a condition. Don't rely that if the execution reached the second branch that the first branch is false. The relation between them is OR and not XOR. It's your job to make them mutually exclusive. Try the following query and check all possible solutions and you'll notice the problem.
?- max([6,9,3,8,1], Max).
Maybe you forgot one of the possibilities? The head can be either greater or smaller than the largest element in the tail.
''', }