Source in markdown for the 'factorial using ISO-Prolog arithmetic' example

\title An example of an exercise

# Exercise: code factorial using ISO-Prolog arithmetic 

Consider again the factorial example, using Peano arithmetic:
```ciao_runnable
:- module(_, _, [sr/bfall]).
%! \begin{focus}
factorial(0,s(0)).
factorial(s(N),F) :-
    factorial(N,F1),
    times(s(N),F1,F).
%! \end{focus}

nat_num(0).
nat_num(s(X)) :- nat_num(X).

times(0,Y,0) :- nat_num(Y).
times(s(X),Y,Z) :- plus(W,Y,Z), times(X,Y,W).

plus(0,Y,Y) :- nat_num(Y).
plus(s(X),Y,s(Z)) :- plus(X,Y,Z).
```

Load the program (click on **?**) and note some facts about this version:
  - It is fully reversible!
```ciao_runnable
?- factorial(X,s(s(s(s(s(s(0))))))).
```
  - But also inefficient (try progressively increasing the input below): 
```ciao_runnable
?- factorial(s(s(s(s(0)))),Y).
```

An alternative is to code it using ISO-Prolog arithmetic, i.e., `is/2`:
```ciao
 ... Z is X * Y ... 
```

Try in the following window to encode the factorial program using
`is/2`, following the instructions: 
```ciao_runnable
:- module(_, _, [assertions]).

:- test factorial(A, B) : (A = 0) => (B = 1) + (not_fails, is_det).
:- test factorial(A, B) : (A = 1) => (B = 1) + (not_fails, is_det).
:- test factorial(A, B) : (A = 2) => (B = 2) + (not_fails, is_det).
:- test factorial(A, B) : (A = 3) => (B = 6) + (not_fails, is_det).
:- test factorial(A, B) : (A = 4) => (B = 24) + (not_fails, is_det).
:- test factorial(A, B) : (A = 5) => (B = 120) + (not_fails, is_det).
:- test factorial(A, B) : (A = 0, B = 0) + (fails, is_det).
:- test factorial(A, B) : (A = 5, B = 125) + (fails, is_det).
:- test factorial(A, B) : (A = -1) + (fails, is_det).

%! \begin{hint}
% TASK 1 - Rewrite with Prolog arithmetic 
factorial(0,s(0)).    % TODO: Replace s(0) by 1
factorial(M,F) :-     % TODO: Make sure that M > 0
    M = s(N),         % TODO: Compute N from M using is/2 (note that N is 
    factorial(N,F1),  %       unbound, so you need to compute N from M!)
    times(M,F1,F).    % TODO: Replace times/3 by a call to is/2 (using *)
% When you are done, press the face ("Run tests") to check you program.
% You can also use the arrow to "Load into playground".
%! \end{hint}
%! \begin{solution}
factorial(0,1). 
factorial(N,F) :-
    N > 0,
    N1 is N-1,
    factorial(N1,F1),
    F is F1*N.
%! \end{solution}
```

You can also click on **Show solution** to load the solution in the
edit area. 

Note that this type of arithmetic provides a (large!) performance
gain. But it also has limitations: it only works in one direction,
i.e., the second argument of `is/2` must be bound to an arithmetic
term. Thus, wrong goal order in your solution above can raise an error
(e.g., moving the last call to `is/2` before the call to factorial).

Meta-logical tests (see later) can be used to improve this, but we
will see later a more elegant solution: using constraints!