diff options
author | Martin Možina <martin.mozina@fri.uni-lj.si> | 2016-09-27 15:19:07 +0200 |
---|---|---|
committer | Martin Možina <martin.mozina@fri.uni-lj.si> | 2016-09-27 15:19:07 +0200 |
commit | 01eb98c7a5e86325e1243f0d0f4e111a18d1e535 (patch) | |
tree | 7871a2a0d30fd7761b6ac0f40846fbd004e10b25 /prolog/problems/lists/conc_3 | |
parent | 5a00cf460426af73cb1fef953acf01f460887f77 (diff) | |
parent | 3bfcb3e651980f1675807b8f82826dcb3e4e1013 (diff) |
Merge branch 'master' of 192.168.15.97:codeq-problems
Diffstat (limited to 'prolog/problems/lists/conc_3')
-rw-r--r-- | prolog/problems/lists/conc_3/en.py | 111 | ||||
-rw-r--r-- | prolog/problems/lists/conc_3/sl.py | 10 |
2 files changed, 115 insertions, 6 deletions
diff --git a/prolog/problems/lists/conc_3/en.py b/prolog/problems/lists/conc_3/en.py index e25ae32..be32b7d 100644 --- a/prolog/problems/lists/conc_3/en.py +++ b/prolog/problems/lists/conc_3/en.py @@ -10,4 +10,113 @@ description = '''\ X = [1,2,3]. </pre>''' -hint = {} +plan = ['''\ +<p><img src="[%@resource plan.svg%]" /></p> +''', '''\ +<p>Let's start with an easy question. What do I get if I concatenate an empty list and a list <code>L2</code>?</p> +''', '''\ +<p>Now, assume that the first list has exactly one element. Let's temporarily take it out which leaves us +with an empty list. But wait! Isn't this situation now similar to the one we dealt with before? Of course, we just +reduced the problem into a smaller one (by one element smaller). Let recursion solve this smaller problem. Just don't +forget to expand the recursion's result with the element you have taken out at the beginning...</p> +''', '''\ +<p>Declarative/logic reasoning: Assume the first list <code>L1</code> has head <code>H</code> and tail +<code>T</code>. If the recursive result of concatenating <code>T</code> and <code>L2</code> is some list +<code>L3</code>, and if we add element <code>H</code> at the beginning of list <code>L3</code>, what do we get? +A concatenation of <code>L1</code> and <code>L2</code>!</p> +'''] + +hint = { + 'eq_instead_of_equ': '''\ +<p>The operator <code>==</code> is "stricter" than operator <code>=</code> in the sense that +for the latter it is enough to be able to make the two operands equal (unification). Perhaps by using <code>=</code> +you can make the predicate <code>conc/3</code> more general (e.g. able to work with output arguments becoming inputs).</p> +<p>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).</p> +''', + + 'eq_instead_of_equ_markup': '''\ +<p>Perhaps the operator for unification (=) would be better?</p> +''', + + 'base_case': '''\ +<p>Did you think of a base case? What is the simplest possible case? +What's the answer if, for example, the first list is empty? (Just the first list should be empty, +the second one can be arbitrary.)</p> +''', + + 'base_case_arbitrary': '''\ +<p>How can the result of concatenating two lists be an arbitrary list (a variable without an assigned value)?</p> +<p>If your base case is similar to <code>conc([], L, _)</code>, +then you should rethink it: what is the result of the concatenation, what do you return as the result? +The base case <em>always</em> fully specifies the result, usually there are no unknowns (<code>_</code> +or variables without assigned values) in what is being returned as the result.</p> +''', + + 'predicate_always_false': '''\ +<p>It seems your predicate is <emph>always</emph> "false". Did you give it the correct name, +or is it perhaps misspelled?</p> +<p>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?</p> +<p>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 <code>[]</code> is equal to a list with +exactly three elements <code>[A,B,C]</code>, or something similarly impossible).</p> +''', + + 'timeout': '''\ +<p>Is there an infinite recursion at work here? How will it ever stop?</p> +<p>Or perhaps is there a missing, faulty, or simply incompatible (with the general recursive case) base case? +Are you maybe reducing the first list, but your base case stops with an empty second list (or vice versa)?</p> +''', + + 'second_list_iteration': '''\ +<p>It seems you're processing (reducing) the second list. The mechanism at work is correct, however, +the final ordering of the elements is not. It's better to process the first list in this way and +leave the second one as is.</p> +<p>There's another reason to process the first list: in this way the solution of this essential exercise +will be the same for everyone, and we'll be able to use <code>conc/3</code> in a standardised way. This +will be very important later on.</p> +''', + + 'insertion_into_second_list': ''' +<p>Is your recursive call of the form <code>conc(T, [H|L2], ...)</code>? +Don't insert the first list's head into the second list as this will result in the wrong ordering +of the elements. Let the recursion alone take care of concatenating the first list's tail +<code>T</code> with the second list <code>L2</code>, and then, when returning the complete result, +add the first list's head <code>H</code> into its proper place.</p> +''', + + 'two_heads': '''\ +<p>Do you really need two list heads? Are you trying to reduce both lists? This is not a good idea, it is +difficult to solve the exercise in this way. Rather simply reduce the first list only, and leave the +other list as is.</p> +''', + + 'two_heads_markup': '''\ +<p>Do you really need two list heads?</p> +''', + + 'forcing_result_onto_recursion': ''' +<p>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.</p> +<p>Is your recursive call of the form <code>conc(T, L2, [H|...])</code>? This forces the recursive call to +<em>return</em> the head at the start of the concatenated list. But it doesn't know of this head, because you just +took it away! Inserting the head into the result, returned by the recursive call, is your job. To put it shortly, +insert <code>H</code> outside of the recursive call.</p> +''', + + 'final_hint': '''\ +<p>Predicate <code>conc/3</code> will be useful for much more than just concatenating two lists. +Among other things it can be used "in the other direction" -- for dividing a list into two parts. Try the +following queries:</p> +<p><code>?- conc(L1, L2, [a,b,c,d]).</code></p> +<p><code>?- conc([X,Y], L2, [a,b,c,d,e,f]).</code></p> +<p>Did you notice that the second query returned the first two elements from the list <code>[a,b,c,d,e,f]</code>?</p> +<p>Furthermore, <code>conc/3</code> is useful to search for patterns in a list, e.g.:</p> +<p><code>?- conc(_, [X,X|_], [a,b,c,c,d,e,f,f,g,h,h]).</code></p> +<p>Right, this query finds all possibilities where two identical elements appear one after the other in a list +(pattern X,X). Basically the query said that "there are some elements (possibly zero) in front, then follow two +identical elements, and then again some elements (possibly zero) at the end."</p> +<p>There are many other usages of <code>conc/3</code>, you will discover them along the way.</p> +''', +} diff --git a/prolog/problems/lists/conc_3/sl.py b/prolog/problems/lists/conc_3/sl.py index be2590e..5b0a639 100644 --- a/prolog/problems/lists/conc_3/sl.py +++ b/prolog/problems/lists/conc_3/sl.py @@ -92,8 +92,8 @@ res težko prišel do pravilne rešitve. Raje zmanjšuj samo prvi seznam in pust 'forcing_result_onto_recursion': ''' <p>Ne vsiljuj rekurziji kaj naj vrne, prepusti se ji. To je tisti del, ko narediš predpostavko, če je ta izpolnjena, potem bo tvoje pravilo delovalo za večji primer.</p> -<p>Je tvoj rekurzivni klic oblike <code>conc(T, L2 [H|...])</code>? S tem vsiljuješ rekurziji -da mora <emph>vrniti</emph> tudi glavo, ki si jo prej že dal začasno stran. Glavo moraš na koncu na primerno mesto +<p>Je tvoj rekurzivni klic oblike <code>conc(T, L2, [H|...])</code>? S tem vsiljuješ rekurziji +da mora <em>vrniti</em> tudi glavo, ki si jo prej že dal začasno stran. Glavo moraš na koncu na primerno mesto vstaviti ti. Skratka, glavo <code>H</code> dodaj izven rekurzivnega klica.</p> ''', @@ -105,9 +105,9 @@ Med drugim je uporaben "v obratni smeri" za delitev seznama na dva dela, poskusi <p>Si opazil, da je drugo vprašanje v bistvu vrnilo prva dva elementa iz seznama <code>[a,b,c,d,e,f]</code>?</p> <p>Nadalje je <code>conc/3</code> uporaben za iskanje vzorcev v seznamu, npr. takole:</p> <p><code>?- conc(_, [X,X|_], [a,b,c,c,d,e,f,f,g,h,h]).</code></p> -<p>Tako je, to vprašanje najde vse možnosti, kjer se dva elementa ponovita drug za drugim v seznamu (vzorec X,X). +<p>Tako je, to vprašanje najde vse možnosti, kjer se dva enaka elementa ponovita drug za drugim v seznamu (vzorec X,X). V bistvu smo rekli "nekaj poljubnih elementov (lahko tudi nič) je spredaj, potem sta dva enaka, potem pa spet nekaj -poljubnih elementov (lahko nič) zadaj." -Še veliko drugih koristi bo od <code>conc/3</code>, jih boš že še sproti spoznal.</p> +poljubnih elementov (lahko nič) zadaj."</p> +<p>Še veliko drugih koristi bo od <code>conc/3</code>, jih boš že še sproti spoznal.</p> ''', } |