Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Again, just use the structural recursion on lists. Lists are built of nodes, <code>[H|T]</code>, i.e. compound data structures with two fields - <em>head</em>, <code>H</code>, and <em>tail</em>, <code>T</code>. Head is the data (list element) held in the node, and <code>T</code> is the rest of the list.</p> <p>We find minimum element by rolling along the list, while keeping an additional data - the minimum element from all seen so far:</p> <pre><code>minimum_elt([H|T],X):- minimum_elt(T,H,X). </code></pre> <p>There is no definition for the empty list case - empty lists do not have minimum elements.</p> <pre><code>minimum_elt([],X,X). </code></pre> <p>If there are no more elements in the list, the one we have so far is the answer.</p> <pre><code>minimum_elt([A|B],M,X):- </code></pre> <p>two cases here: <code>A &lt; M</code>, or otherwise:</p> <pre><code> A &lt; M, minimum_elt(B,A,X). minimum_elt([A|B],M,X):- A &gt;= M, minimum_elt(B,M,X). </code></pre> <p>Nothing more to say about it, so this completes the program.</p> <hr> <p>edit: except, you wanted to also delete that element. This changes things. Hmm. One obvious approach is first find the minimum elt, then delete it. We'll have to compare all elements once again, this time against the minimal element found previously. Can we do this in one scan? </p> <p>In Lisp we could have. To remove any element from a list, surgically, we just reset the tail pointer of a <em>previous</em> node to point to the <em>next</em> node after the one being removed. Then using this approach, we'd scan the input list once, keeping the reference to the previous node to the minimum element found so far, swapping it as we find the smaller and smaller elements. Then when we've reached the end of the list, we'd just surgically remove the minimal node.</p> <p>But in Prolog, we can't <em>reset</em> things. Prolog is a <em>set once</em> language. So looks like we're stuck with the need to pass over the list twice ... or we can try to be very smart about it, and construct all possible lists as we go, sorting them out each time we find the new candidate for the smallest element. </p> <pre><code>rem_min([A|B],L):- % two possibilities: A is or isn't the minimum elt rem_min(B,A,([A|Z],Z,Z),L). rem_min([],A,(With,Without,Tail),L):- Tail = [], % A is indeed the minimal element L = Without. rem_min([H|T],A,(With,Without,Tail),L):- H &gt;= A, Tail=[H|Z], rem_min(T,A,(With,Without,Z),L). rem_min([H|T],A,(With,Without,Tail),L):- H &lt; A, % use this H copy_the_list(With,Tail,W2,T2), % no good - quadratic behaviour Tail=[H|Z], T2=Z, rem_min(T,A,(With,W2,Z),L). copy_the_list([A|B],T,[A|C],C):- var(B), !, T=B. % fresh tail copy_the_list([A|B],T,[A|C],T2):- copy_the_list(B,T,C,T2). </code></pre> <hr> <p>So looks like we can't avoid the second pass, but at least we can save all the superfluous comparisons:</p> <pre><code>rem_min([A|B],L):- N=[A|_], rem_min(B,A,N,[N|Z],Z,L). rem_min([],_A,N,L2,Z,L):- Z=[], N=[_,1], % finalize the minimal entry scan(L2,L). rem_min([H|T],A,N,L2,Z,L):- H &gt;= A, Z=[H|Z2], rem_min(T,A,N,L2,Z2,L). rem_min([H|T],A,N,L2,Z,L):- H &lt; A, % use this H N2=[H|_], N=[_], % finalize the non-minimal entry Z=[N2|Z2], rem_min(T,H,N2,L2,Z2,L). scan( [], []). scan( [[_,1]|B],C):- !, scan(B,C). % step over the minimal element scan( [[A]|B],[A|C]):- !, scan(B,C). % previous candidate scan( [A|B], [A|C]):- !, scan(B,C). </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload