Puzzle Utilities

From This Prolog Life
Revision as of 19:44, 19 October 2013 by John (talk | contribs) (Created page with "The following predicates are used in the puzzle solutions. ==Higher-order Predicates== ====unique_solution( +Goal )==== holds when <var>Goal</var> has one ground solution. ...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

The following predicates are used in the puzzle solutions.

Higher-order Predicates

unique_solution( +Goal )

holds when Goal has one ground solution. Operationally, Goal may produce several solutions, ("don't care" non-deterministically), but they must all be identical (==).

<syntaxhighlight lang="prolog">unique_solution( Goal ) :-

   findall( Goal, Goal, [Solution|Solutions] ),
   same_solution( Solutions, Solution ),
   Solution = Goal.

same_solution( [], _Solution ). same_solution( [Solution0|Solutions], Solution ) :-

   Solution0 == Solution,
   same_solution( Solutions, Solution ).</syntaxhighlight>

forall( +Enumerator, +Test )

is true if Enumerator and Test are goals and Test holds everywhere that Enumerator does. NB: forall/2 does not instantiate arguments further.

<syntaxhighlight lang="prolog">forall( Enumerator, Test ) :-

   \+ (call(Enumerator), \+ call(Test)).</syntaxhighlight>

count_solutions( +Goal, ?Count )

is true if Count is the number of solutions for Goal. The solutions might not be distinct.

count_solutions/2 enumerates the possible solutions to Goal but does not instantiate Goal's arguments further.

<syntaxhighlight lang="prolog"> count_solutions( Goal, Count ) :-

   findall( x, Goal, Xs ),
   length( Xs, Count ).

</syntaxhighlight>

Lists

member( ?Element, ?List )

holds when Element is a member of List.

<syntaxhighlight lang="prolog">member( H, [H|_] ). member( H, [_|T] ) :-

   member( H, T ).</syntaxhighlight>

select( ?Element, ?List0, ?List1 )

is true if List1 is equal to List0 with Element removed.

<syntaxhighlight lang="prolog">select( H, [H|T], T ). select( Element, [H|T0], [H|T1] ) :-

   select( Element, T0, T1 ).</syntaxhighlight>

memberchk( +Element, +List )

succeeds (once) if Element is a member of List.

<syntaxhighlight lang="prolog">memberchk( Element, List ) :-

   member( Element, List ),
   !.</syntaxhighlight>

Arithmetic

between( +Lower, +Upper, ?Index )

is true if Lower =< Index =< Upper. Two valid cases are possible:

  • Index is already instantiated to an integer, so the checks on order are applied (test).
  • Index is a logical variable: a series of alternative solutions may be generated as the monotonic sequence of values between Lower and Upper (non-deterministic generator).

<syntaxhighlight lang="prolog">between( Lower, Upper, Index ) :-

   integer( Lower ),
   integer( Upper ),
   Lower =< Upper,
   ( integer( Index ) ->    % Case 1: "test"
       Index >= Lower,
       Index =< Upper
   ; var( Index ) ->        % Case 2: "generate".
       generate_between( Lower, Upper, Index )
   ).

generate_between( Lower, Upper, Index ) :-

   ( Lower =:= Upper ->
       Index = Lower
   ;   Index = Lower
   ;   Next is Lower + 1,
       Next =< Upper,
       generate_between( Next, Upper, Index )
   ).</syntaxhighlight>

sum( +List, ?Sum )

holds when the List of numbers sum to Sum.

<syntaxhighlight lang="prolog">sum( [H|T], Sum ) :-

   sum1( T, H, Sum ).

sum1( [], Sum, Sum ). sum1( [H|T], Sum0, Sum ):-

   Sum1 is Sum0 + H,
   sum1( T, Sum1, Sum ).</syntaxhighlight>

Character Input/Output

put_chars( +Chars )

if Chars is a (possibly empty) list of character codes and the corresponding characters are written to the current output stream.

<syntaxhighlight lang="prolog">put_chars( [] ). put_chars( [Char|Chars] ) :-

   put( Char ),
   put_chars( Chars ).</syntaxhighlight>

get_chars( ?Chars )

if Chars is a (possibly empty) list of character codes read from the current input stream.

<syntaxhighlight lang="prolog">get_chars( Input ) :-

   get0( Char ),
   ( Char > -1 ->
       Input = [Char|Chars],
       get_chars( Chars )
   ; otherwise ->
       Input = []
   ).</syntaxhighlight>

The code is available as plain text here.