prolog print a fact like goal or initial - printing

I am new in prolog and I would like to print an initial and a goal fact
like below
initial([8,1,3,7,0,2,6,5,4]).
goal([1,2,3,8,0,4,7,6,5]).
=============
= 8 = 1 = 3 =
=============
= 7 = 0 = 2 =
=============
= 6 = 5 = 4 =
=============
Could you help me do it ?

simple hardcoded way :
pretty_print([A, B, C, D, E, F, G, H, I]) :-
write(=============), nl, nl,
write('= '), write(A), write(' = '), write(B), write(' = '), write(C), write(' ='), nl, nl,
write(=============), nl, nl,
write('= '), write(D), write(' = '), write(E), write(' = '), write(F), write(' ='), nl, nl,
write(=============), nl, nl,
write('= '), write(G), write(' = '), write(H), write(' = '), write(I), write(' ='), nl, nl,
write(=============), nl, nl.
with format :
pretty_print(L) :-
format('=============~n
= ~w = ~w = ~w =~n
=============~n
= ~w = ~w = ~w =~n
=============~n
= ~w = ~w = ~w =~n
=============', L).
with some functionnal help :
length_(A, B) :- length(B, A).
pretty_print(L) :-
length(Rows, 3),
maplist(length_(3), Rows),
append(Rows, L),
maplist(format('=============~n~n= ~w = ~w = ~w =~n~n'), Rows),
write(=============), nl.
with the lambda module :
pretty_print(L) :-
length(Rows, 3),
maplist(\X^length(X, 3), Rows),
append(Rows, L),
maplist(format('=============~n~n= ~w = ~w = ~w =~n~n'), Rows),
write(=============), nl.
Usage :
?- initial(X), pretty_print(X).
or
?- goal(X), pretty_print(X).

Related

How to print this in one line statement in Prolog

How can i print this string in prolog in the best way:
predicate([], L, Id, L2):-
length(L2, N),
write('The length '),
write(Id),
write(' is '),
write(N),
write(' elements.'),
nl.
In SWI-Prolog, you can use the built-in predicate format/2:
predicate([], L, Id, L2):-
length(L2, N),
format('The length of ~w is ~w elements\n', [Id, N]).

Optimizing max Collatz sequence

I'm looking to optimize my solution for the maximum Collatz sequence problem in Erlang. Right now I've tried using ETS, and the following solution uses maps, but I'm getting worse performance than I feel I should. Is there perhaps some optimization I could do to improve it?
-module(collatzMaps).
-export([start/2, s/4]).
collatz(0, Map) ->
{0, Map};
collatz(M, Map) ->
Exists = maps:is_key(M, Map),
case Exists of
false ->
case M rem 2 == 0 of
true ->
Result = collatz(M div 2, Map),
Val = (1 + element(1, Result)),
Map1 = maps:put(M, Val, element(2, Result)),
{maps:get(M, Map1), Map1};
false ->
Result = collatz((3 * M + 1), Map),
Val = (1 + element(1, Result)),
Map2 = maps:put(M, Val, element(2, Result)),
{maps:get(M, Map2), Map2}
end;
true ->
{maps:get(M, Map), Map}
end.
s(N, M, Max, Map) ->
if
N =< M ->
Result = collatz(N, Map),
if
element(1, Result) > Max ->
NextMax = element(1, Result),
MapNext = element(2, Result),
s(N + 1, M, NextMax, MapNext);
true ->
MapNext = element(2, Result),
s(N + 1, M, Max, MapNext)
end;
true ->
Max
end.
start(N, M)->
statistics(runtime),
statistics(wall_clock),
Map = maps:new(),
Map1 = maps:put(1, 1, Map),
G = s(N, M, 0, Map1),
{_, Time2} = statistics(wall_clock),
U2 = Time2 / 1000,
io:format("~p seconds~n", [U2]),
G.
Well, first let's tweak up invocation which will allow us to make some simple statistics and compare different approaches
-export([start/2, max_collatz/2]).
...
max_collatz(N, M) ->
Map = maps:new(),
Map1 = maps:put(1, 1, Map),
s(N, M, 0, Map1).
start(N, M)->
{T, Result} = timer:tc( fun() -> max_collatz(N, M) end),
io:format("~p seconds~n", [T / 1000000]),
Result.
So let's write it more Erlang idiomatic way
-module(collatz).
-export([start/2, max_collatz/2]).
collatz_next(N) when N rem 2 =:= 0 ->
N div 2;
collatz_next(N) ->
3 * N + 1.
collatz_length(N, Map) ->
case Map of
#{N := L} -> {L, Map};
_ ->
{L, Map2} = collatz_length(collatz_next(N), Map),
{L + 1, Map2#{N => L + 1}}
end.
max_collatz(N, M) ->
Map = lists:foldl(fun(X, Map) -> {_, Map2} = collatz_length(X, Map), Map2 end,
#{1 => 1}, lists:seq(N, M)),
lists:max(maps:values(Map)).
start(N, M) ->
{T, Result} = timer:tc(fun() -> max_collatz(N, M) end),
io:format("~p seconds~n", [T / 1000000]),
Result.
Then we can compare speed using for example eministat.
Clone in
git clone https://github.com/jlouis/eministat.git
cd eministat
make
If you run in a problem like
DEPEND eministat.d
ERLC eministat.erl eministat_analysis.erl eministat_ds.erl eministat_plot.erl eministat_report.erl eministat_resample.erl eministat_ts.erl
compile: warnings being treated as errors
src/eministat_resample.erl:8: export_all flag enabled - all functions will be exported
erlang.mk:4940: recipe for target 'ebin/eministat.app' failed
make[1]: *** [ebin/eministat.app] Error 1
erlang.mk:4758: recipe for target 'app' failed
make: *** [app] Error 2
You can fix it
diff --git src/eministat_resample.erl src/eministat_resample.erl
index 1adf401..0887b2c 100644
--- src/eministat_resample.erl
+++ src/eministat_resample.erl
## -5,7 +5,7 ##
-include("eministat.hrl").
-export([resample/3, bootstrap_bca/3]).
--compile(export_all).
+-compile([nowarn_export_all, export_all]).
%% #doc resample/3 is the main resampler of eministat
%% #end
So then run it
$ erl -pa eministat/ebin/
Erlang/OTP 21 [erts-10.1] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]
Eshell V10.1 (abort with ^G)
1> c(collatzMaps), c(collatz).
{ok,collatz}
2> eministat:x(95.0, eministat:s(orig, fun() -> collatzMaps:max_collatz(1, 100000) end, 30), eministat:s(new, fun() -> collatz:max_collatz(1, 100000) end, 30)).
x orig
+ new
+--------------------------------------------------------------------------+
|+ ++++++++ +++++ * + +x+**+xxxx**x xxx xx+x xxx *x x + x x|
| + + + x x xx x |
| + |
| |_______M___A__________| |
| |________M_____A______________| |
+--------------------------------------------------------------------------+
Dataset: x N=30 CI=95.0000
Statistic Value [ Bias] (Bootstrapped LB‥UB)
Min: 1.76982e+5
1st Qu. 1.81610e+5
Median: 1.82954e+5
3rd Qu. 1.87030e+5
Max: 1.94944e+5
Average: 1.84280e+5 [ 8.00350] ( 1.82971e+5 ‥ 1.85749e+5)
Std. Dev: 3999.87 [ -102.524] ( 3128.74 ‥ 5431.13)
Outliers: 0/0 = 0 (μ=1.84288e+5, σ=3897.35)
Outlier variance: 3.22222e-2 (slight)
------
Dataset: + N=30 CI=95.0000
Statistic Value [ Bias] (Bootstrapped LB‥UB)
Min: 1.69179e+5
1st Qu. 1.72501e+5
Median: 1.74614e+5
3rd Qu. 1.79850e+5
Max: 1.90638e+5
Average: 1.76517e+5 [ 3.11862] ( 1.74847e+5 ‥ 1.78679e+5)
Std. Dev: 5343.46 [ -147.802] ( 4072.99 ‥ 7072.53)
Outliers: 0/0 = 0 (μ=1.76520e+5, σ=5195.66)
Outlier variance: 9.43164e-2 (slight)
Difference at 95.0% confidence
-7762.60 ± 2439.69
-4.21240% ± 1.32391%
(Student's t, pooled s = 4719.72)
------
ok
So it seems like 4% faster now which is not much. First, we can inline collatz_next/1 which is basically what you have in your collatz/2 function. I like to be specific so I put between -export and a first function
-compile({inline, [collatz_next/1]}).
It have very little effect
Difference at 95.0% confidence
-9895.27 ± 5524.91
-5.24520% ± 2.92860%
(Student's t, pooled s = 1.06882e+4)
Then we can try roll out lists:fold/2, lists:seq/2 and lists:max/1 as in your s/4 function but let's do it more idiomatic way.
max_collatz(N, M) ->
max_collatz(N, M, 1, #{1 => 1}).
max_collatz(M, M, Max, _) -> Max;
max_collatz(N, M, Max, Map) ->
case collatz_length(N + 1, Map) of
{L, Map2} when L > Max ->
max_collatz(N + 1, M, L, Map2);
{_, Map2} ->
max_collatz(N + 1, M, Max, Map2)
end.
Well it's better but still not much
Difference at 95.0% confidence
-1.78775e+4 ± 1980.35
-9.66832% ± 1.07099%
Now, when we removed all external code calls it's worth to try native compiling (external function call usually ruins any native compilation benefit). We could also add little type hint for HiPE but it seems to have barely any effect (it is usually worth to try for floating point arithmetic which is not this case and heavy usage of maps is probably issuing problem here as well).
max_collatz(N, M) when N < M, is_integer(N), is_integer(M) ->
max_collatz(N, M, 1, #{1 => 1}).
Not much better
c(collatz, [native]).
...
Difference at 95.0% confidence
-2.26703e+4 ± 2651.32
-12.1721% ± 1.42354%
(Student's t, pooled s = 5129.13)
So its time try it dirty. Process dictionary is not the recommended place to store your data but if it is inside special process it is an acceptable solution.
collatz_length(N) ->
case get(N) of
undefined ->
L = collatz_length(collatz_next(N)),
put(N, L + 1),
L + 1;
L -> L
end.
max_collatz(N, M) when N < M, is_integer(N), is_integer(M) ->
P = self(),
W = spawn_link(fun() ->
put(1, 1),
P ! {self(), max_collatz(N, M, 1)}
end),
receive {W, Max} -> Max end.
max_collatz(M, M, Max) -> Max;
max_collatz(N, M, Max) ->
case collatz_length(N + 1) of
L when L > Max ->
max_collatz(N + 1, M, L);
_ ->
max_collatz(N + 1, M, Max)
end.
Yes, its dirty but working solution and its worth it (even without native)
Difference at 95.0% confidence
-1.98173e+5 ± 5450.92
-80.9384% ± 2.22628%
(Student's t, pooled s = 1.05451e+4)
So here we are from 3.6s down to 0.93s using some dirty tricks but anyway, if you would do this sort of tasks, you would probably use NIF written in C. It is not a type of task where Erlang shine.
> collatzMaps:start(1, 1000000).
3.576669 seconds
525
> collatz:start(1, 1000000).
0.931186 seconds
525

Nested loop and functional programming

Please consider a C program that, given x, will return y and z such that y + z * 2 = x, for the smallest possible y. Roughly, I could create a nested loop:
for(y = 0; y < x; ++ y){
for(z = 0; z < x; ++z){
if(y + 2 * z == x){
printf("%d + 2 * %d = %d", y, z, x);
}
}
}
How could I translate this kind of nested loop in the functional way? Is it feasible? Is it reasonable or am I just misjudging the approach? My best attempt so far:
let foo x =
let rec aux (y, z, q) =
match (y + z * 2) with
r when r = q -> (y, z)
|_ -> aux(y + 1, z + 1, q) //How to check different values of z
aux(0, 0, x) //for each value of y?
It will not work, since it will just increment both y and z. How can I check different values of z, for every value of y?
You have to add those checks in the match.
See here what your code is missing:
let foo x =
let rec aux (y, z, q) =
match (y + z * 2) with
| r when r = q -> (y, z)
| _ when y = q -> failwith "not found !"
| _ when z = q -> aux (y + 1, 0, q)
| _ -> aux (y, z + 1, q)
aux (0, 0, x)
And here's a different approach, equally functional but without recursion:
let foo2 x =
let s =
{0 .. x} |> Seq.collect (fun y ->
{0 .. x} |> Seq.collect (fun z ->
seq [y, z]))
Seq.find (fun (y, z) -> y + z * 2 = x) s
which in F# can be written using seq expressions:
let foo3 x =
let s = seq {
for y in {0 .. x} do
for z in {0 .. x} do
yield (y, z)}
Seq.find (fun (y, z) -> y + z * 2 = x) s
and it resembles your original C program.

How to sum "any three elements" in a tuple in F#

I recently started learning how to program in F# and I have an assignment that is giving me some serious headaches.
I have to make a function that takes two arguments, an integer and a five element tuple of integers, and returns true if the sum of any three elements of the tuple is greater than the first argument, else false.
I started designing my code this way
{
let t3 = (1, 2, 3, 4, 5)
let intVal = 1
let check intVal t3 =
for t3
if (*sum of any three elements*) > intVal then true
else false
}
but at this point I am stuck and do not know how to proceed.
Easy way define - sort elements of tuple and compare with sum last three elements (ascending sort) :
let inline isAnyThreeGreaterThan2 limit (x1, x2, x3, x4, x5) =
[x1;x2;x3;x4;x5] |> List.sort |> Seq.skip 2 |> Seq.sum > limit
Example:
isAnyThreeGreaterThan2 15 (1, 2, 5, 5, 5) |> printfn "%A"
isAnyThreeGreaterThan2 14 (1, 2, 5, 5, 5) |> printfn "%A"
isAnyThreeGreaterThan2 15 (1, 2, 5, 5, 6) |> printfn "%A"
isAnyThreeGreaterThan2 15 (1, 2, 3, 4, 5) |> printfn "%A"
isAnyThreeGreaterThan2 12 (1, 2, 3, 4, 5) |> printfn "%A"
isAnyThreeGreaterThan2 11 (1, 2, 3, 4, 5) |> printfn "%A"
Print:
false
true
true
false
false
true
Link:
https://dotnetfiddle.net/7XR1ZA
It could be solved by converting the tuple into an array, getting the possible combinations out of it, summing those combinations and then verify if the any of the sums is greater than your parameter
(1,2,3,4,5)
|> Microsoft.FSharp.Reflection.FSharpValue.GetTupleFields
|> Array.toList
//Implementing this is left as and exercise to the reader
|> combinations 3
//converts the obj list as a int list and then sums the elements
|> List.map (fun x -> x |> List.map unbox<int> |> List.sum)
//Verifies if any sum is greater than intVal
|> List.exists (fun x -> x > intVal)
Something like this ought to do it:
let cross3 l1 l2 l3 =
[
for x in l1 do
for y in l2 do
for z in l3 do
yield x, y, z ]
module Tuple3 =
let distinct (x, y, z) =
let l = [x; y; z]
l |> List.distinct |> List.length = l.Length
let snd (x, y, z) = snd x, snd y, snd z
let inline sum (x, y, z) = x + y + z
let inline isAnyThreeGreaterThan limit (x1, x2, x3, x4, x5) =
let l = [x1; x2; x3; x4; x5] |> List.indexed
let legalCombinations =
cross3 l l l
|> List.filter Tuple3.distinct
|> List.map Tuple3.snd
legalCombinations |> List.exists (fun t3 -> Tuple3.sum t3 > limit)
Since this is an assignment, I'll leave it as an exercise to understand what's going on, but here's a sample FSI session:
> isAnyThreeGreaterThan 15 (1, 2, 5, 5, 5);;
val it : bool = false
> isAnyThreeGreaterThan 14 (1, 2, 5, 5, 5);;
val it : bool = true
> isAnyThreeGreaterThan 15 (1, 2, 5, 5, 6);;
val it : bool = true
> isAnyThreeGreaterThan 15 (1, 2, 3, 4, 5);;
val it : bool = false
> isAnyThreeGreaterThan 12 (1, 2, 3, 4, 5);;
val it : bool = false
> isAnyThreeGreaterThan 11 (1, 2, 3, 4, 5);;
val it : bool = true

Initial state in F# List.scan

I have a simple problem and as I'm an F# newbie I can't seem to figure out how to do this. I have a list of tuples:
let l = [ (a, 2); (b, 3); (c, 2); (d, 6) ]
that I want to transform into this:
let r = [ (a, 2); (b, 5); (c, 7); (d, 13) ]
This simply adds the values of the second element in each tuple: 2 + 3 + 2 + 6. The objects a, b, c and d are complex objects that I simply want to keep.
I thought I should use List.scan for this. It takes a list, threads an accumulator through the computation and returns a list:
let r = l |> List.scan (fun (_, s) (o, i) -> (o, s + i)) (??, 0) |> List.tail
But I don't know what to fill in for the question marks. I'm not interested in the initial state except for the 0. And I don't want to specify some 'empty' instance of the first tuple element.
Or is there a simpler way of doing this?
You can use first element as an initial state:
let l = [ ("a", 2); ("b", 3); ("c", 2); ("d", 6) ]
let x::xs = l
let res = (x, xs) ||> List.scan (fun (_, x) (o, n) -> o, x + n) // [("a", 2); ("b", 5); ("c", 7); ("d", 13)]
Special case with empty list should be processed separately

Resources