How to compare two lists of rules? - comparison

I need to compare two Lists of Rules of form var -> integer on the fact of mismatch.
To determine, if there are any rules the same by lhs and different by rhs.
For example:
{a->3, b->1, c->4} ~ ??? ~ {a->3, b->1, c->4} = true
{a->3, b->1, c->4} ~ ??? ~ {a->3, b->2, c->4} = false
{a->3, b->1, c->4} ~ ??? ~ {a->1, b->3, c->4} = false
{a->3, b->1, c->4} ~ ??? ~ {c->4, d->8, e->9} = true
{a->3, b->1, c->4} ~ ??? ~ {d->8, e->9, f->7} = true
In my case they are already sorted by lhs and all lhs are unique if it could help to make as simple function as possible.
UPD: forgot one thing! Lists can be of different length. But seems like all three current answers are still valid.

Here's another solution:
In[12]:= check[a:{__Rule}, b:{__Rule}] := FilterRules[a, b] === FilterRules[b, a]
In[18]:= {{a -> 3, b -> 1, c -> 4}~check ~ {a -> 3, b -> 1, c -> 4} ,
{a -> 3, b -> 1, c -> 4}~check ~ {a -> 3, b -> 2, c -> 4},
{a -> 3, b -> 1, c -> 4}~check ~ {a -> 1, b -> 3, c -> 4},
{a -> 3, b -> 1, c -> 4}~check ~ {c -> 4, d -> 8, e -> 9},
{a -> 3, b -> 1, c -> 4}~check ~ {d -> 8, e -> 9, f -> 7}}
Out[18]= {True, False, False, True, True}
(This relies on the fact that the lists of options are already sorted.)

You could do something like
check[{a__Rule}, {b__Rule}] :=
Module[{common = Intersection[{a}[[All, 1]], {b}[[All, 1]]]},
SameQ[common /. {a}, common /. {b}]]
Then
check[{a -> 3, b -> 1, c -> 4}, {a -> 3, b -> 1, c -> 4}]
check[{a -> 3, b -> 1, c -> 4}, {a -> 3, b -> 2, c -> 4}]
check[{a -> 3, b -> 1, c -> 4}, {a -> 1, b -> 3, c -> 4}]
yields
True
False
False

Perhaps simpler
check[a : {__Rule}, b : {__Rule}] := SameQ ## Transpose[a /. b /. a /. Rule -> List]
EDIT
Here is an even more esoteric version, which has the advantage of being completely high-level, in the sense that we don't need to know anything about the internal structure of the rules, only how they act:
checkAlt[a : {__Rule}, b : {__Rule}] := # === (# /. #) &[a /. b /. a]
EDIT 2
Well, let me throw in another one, just for fun:
check1[{a__Rule}, {b__Rule}] := SameQ ## ({a, b} /. {{a, b}, {b, a}})

Here's a slightly generalized approach:
In[24]:= check[lists__] :=
And ## (SameQ ### GatherBy[Join[lists], First])
In[25]:= {
{a -> 3, b -> 1, c -> 4}~check~{a -> 3, b -> 1, c -> 4},
{a -> 3, b -> 1, c -> 4}~check~{a -> 3, b -> 2, c -> 4},
{a -> 3, b -> 1, c -> 4}~check~{a -> 1, b -> 3, c -> 4},
{a -> 3, b -> 1, c -> 4}~check~{c -> 4, d -> 8, e -> 9},
{a -> 3, b -> 1, c -> 4}~check~{d -> 8, e -> 9, f -> 7}
}
Out[25]= {True, False, False, True, True}
This one doesn't require the elements to be rules, they could be lists, or pretty much any other head. It should also work on any number of inputs.

Related

How do I check if grammar is SLR(1)?

How do I check if this grammar is SLR(1)?
S' -> S
S -> [ B
A -> int
A -> [ B
B -> ]
B -> C
C -> A ]
C -> A , C
First I've created it's automaton, then computed the follow sets for non-terminals and then created the parsing table.
I'm not sure if my automaton is correct, but after doing the parsing table for SLR(1) grammar I did not find any errors.
Below is my attempt at the automaton.
I0:
S' -> .S
S -> .[B
I1 (I0 -> S):
S -> [.B
B -> .]
B -> .C
C -> .A]
C -> .A,C
A -> .int
A -> .[B
I3 (I2 -> B)
S -> [B.
I4 (I2 -> ])
B -> ].
I5 (I2 -> C)
B -> C.
I6 (I2 -> A)
C -> A.]
C -> A.,C
I7 (I2 -> int)
A -> int.
I8 (I2 -> [)
A -> [.B
B -> .]
B -> .C
C -> .A]
C -> .A,C
A -> .int
A -> .[B
I8 -> ] = I4
I8 -> C = I5
I8 -> A = I6
I8 -> int = I7
I8 -> [ = I8
I9 (I6 -> ])
C -> A].
I10 (I6 -> ,)
C -> A,.C
C -> .A]
C -> .A,C
A -> .int
A -> .[B
I11 (I8 -> B)
A -> [B.
I12 (I10 -> C)
C -> A,C.
I10 -> A = I6
I10 -> int = I7
I10 -> [ = I8
Considering that you have done the hard work, to find all the states, now it is time to check the Rules of SLR(1).
https://en.wikipedia.org/wiki/SLR_grammar
As you can realize, your question misses the Follow() set which is mandatory in the Rules.
Yes, you can find out on your table parser if there is a conflict or not, but this is an answer depended more on experience than actual science.
Check the Rules one-by-one and you will be fine :)
Depending on the fact that you are sure about the correctness of your states, I see no Shift/Reduce or Reduce/Reduce conflict, so the Grammar is SLR(1)

erlang; outsmarting compiler with memoization?

The following is my solution to Project Euler 14, which works (in 18 s):
%Which starting number, under one million, produces the longest Collartz chain?
-module(soln14).
-export([solve/0]).
collatz(L) ->
[H|T] = L,
F = erlang:get({'collatz', H}),
case is_list(F) of
true ->
R = lists:append(F, T);
false ->
if H == 1 ->
R = L;
true ->
if H rem 2 == 0 ->
R = collatz([H div 2 | L]);
true ->
R = collatz([3*H+1 | L])
end
end,
erlang:put({'collatz', lists:last(L)}, R),
R
end.
dosolve(N, Max, MaxN, TheList) ->
if N == 1000000 -> MaxN;
true ->
L = collatz([N]),
M = length(L),
if M > Max -> dosolve(N+1, M, N, L);
true ->
dosolve(N+1, Max, MaxN, TheList)
end
end.
solve() ->
{Megass, Ss, Micros} = erlang:timestamp(),
S = dosolve(1, -1, 1, []),
{Megase, Se, Microe} = erlang:timestamp(),
{Megase-Megass, Se-Ss, Microe-Micros, S}.
However, the compiler complains:
8> c(soln14).
soln14.erl:20: Warning: variable 'R' is unused
{ok,soln14}
9> soln14:solve().
{0,18,-386776,837799}
Is this a compiler scoping error, or do I have a legit bug?
It's not a compiler error, just a warning that in the true case of "case is_list(F) of", the bindning of R to the result of lists:append() is pointless, since this value of R will not be used after that point, just returned immediately. I'll leave it to you to figure out if that's a bug or not. It may be that you are fooled by your indentation. The lines "erlang:put(...)," and "R" are both still within the "false" case of "case is_list(F) of", and should be deeper indented to reflect this.
The error message and the code are not "synchronized". with the version you give, the warning is on line 10: R = lists:append(F, T);.
What it means is that you bind the result of the lists:append/2 call to R and that you don't use it later in the true statement.
this is not the case in the false statement since you use R in the function erlang:put/2.
You could write the code this way:
%Which starting number, under one million, produces the longest Collartz chain?
-module(soln14).
-export([solve/0,dosolve/4]).
collatz(L) ->
[H|T] = L,
F = erlang:get({'collatz', H}),
case is_list(F) of
true ->
lists:append(F, T);
false ->
R = if H == 1 ->
L;
true ->
if H rem 2 == 0 ->
collatz([H div 2 | L]);
true ->
collatz([3*H+1 | L])
end
end,
erlang:put({'collatz', lists:last(L)}, R),
R
end.
dosolve(N, Max, MaxN, TheList) ->
if N == 1000000 -> MaxN;
true ->
L = collatz([N]),
M = length(L),
if M > Max -> dosolve(N+1, M, N, L);
true ->
dosolve(N+1, Max, MaxN, TheList)
end
end.
solve() ->
timer:tc(?MODULE,dosolve,[1, -1, 1, []]).
Warning the code uses a huge amount of memory, collatz is not tail recursive, and it seems that there is some garbage collecting witch is not done.

return first {Key, Value} from Map where Predicate is true

The more formal definition of problem is
Write a function map_search_pred(Map, Pred) that returns the first
element {Key,Value} in the map for which Pred(Key, Value) is true.
My attempt, looks like
map_search_pred(Map, Pred) ->
M = [{Key, Value} || {Key, Value} <- maps:to_list(Map), Pred(Key, Value) =:= true],
case length(M) of
0 -> {};
_ -> lists:nth(1, M)
end.
When I run this, I get correct answer
1> lib_misc:map_search_pred(#{}, fun(X, Y) -> X =:= Y end).
{}
2> lib_misc:map_search_pred(#{1 => 1, 2 => 2}, fun(X, Y) -> X =:= Y end).
{1,1}
3> lib_misc:map_search_pred(#{1 => 1, 2 => 3}, fun(X, Y) -> X =:= Y end).
{1,1}
4> lib_misc:map_search_pred(#{1 => 2, 2 => 2}, fun(X, Y) -> X =:= Y end).
{2,2}
5>
Problem?
The problem is efficiency.
It uses list comprehension and runs for all the elements in the list. The better solution would be to return after the first match.
As a beginner to language, I do not know a better idiomatic way to solve this, so looking for better ideas and suggestions
You could walk the list yourself and return as soon as you find an element for which Pred(Key, Value) is true:
map_search_pred(Map, Pred) when is_map(Map) ->
map_search_pred(maps:to_list(Map), Pred);
map_search_pred([], _) ->
error;
map_search_pred([{Key,Value}=H|T], Pred) ->
case Pred(Key, Value) of
true ->
{ok, H};
false ->
map_search_pred(T, Pred)
end.

Iterate over a cartesian product in Erlang without generating a list first

What's the Erlang equivalent to the following Python code:
for x in range(9):
for y in range(9):
for z in range(9):
foo(x, y, z)
I know I can generate the product first with C = [{X,Y,Z} || X<- lists:seq(1,9), Y<- lists:seq(1,9), Z<- lists:seq(1,9)] then foo([])->done; foo([H|T])->blah blah.
How do I do it without an auxiliary list, using recursion only?
You could do it with three recursive functions.
You might be able to do it with some complex pattern-matching in function head.
But easiest way to skip creation of auxiliary list is to call your function inside list comprehension
C = [foo(X, Y, Z) || X<- lists:seq(1,9),
Y<- lists:seq(1,9),
Z<- lists:seq(1,9)]
Where foo/3 process one element.
List comprehension still forces you to create auxiliary lists in memory.
In case of dealing with huge data sets you should avoid it. Writing recursive functions every time is also awkward so i came up with my own generic for function. It's a little bit slower in traversing than direct recursion or list comprehension but it's memory stable, generic and easy to use.
Usage:
(for({10}))(
fun (X) -> io:format("~p ",[X]) end).
> 1 2 3 4 5 6 7 8 9 10
(for({10, -10, -2}))(
fun (X) -> io:format("~p ",[X]) end).
> 10 8 6 4 2 0 -2 -4 -6 -8 -10
Works with lists too:
(for(lists:seq(10, -10, -2)))(
fun (X) -> io:format("~p ",[X]) end).
> 10 8 6 4 2 0 -2 -4 -6 -8 -10
It's also possible to define step or guard as a function:
(for({256, 1.1, fun (X) -> math:sqrt(X) end, fun (X, Range) -> X > Range end}))(
fun (X) -> io:format("~p ",[X]) end).
> 256 16.0 4.0 2.0 1.4142135623730951 1.189207115002721
If you pass to for a two parameter function, then you can use accumulator feature just like with lists:foldl/3. You also need to pass initial accumulator to for:
Fact = (for(1, {1, 5}))(
fun(X, Acc) ->
X * Acc
end),
io:format("~p", [Fact]).
> 120
e_fact(N) ->
{_, E} = (for({1, 1}, {1, N}))( % i assumed 1/0! equals 1
fun(X, {LastFact, Sum}) ->
Fact = LastFact * X,
{Fact, Sum + 1 / Fact}
end),
E.
io:format("e=~p", [e_fact(10)]).
> e=2.7182818011463845
Also step and guard functions can be dependent on accumulator. Just pass function with one more parameter.
Nested loops finding Pythagorean triples. Easy with closures:
pyth_lists(N) ->
[io:format("~p ", [{A, B, C}]) ||
A <- lists:seq(1, N),
B <- lists:seq(A + 1, N),
C <- lists:seq(B + 1, N),
A * A + B * B == C * C].
pyth_for(N) ->
(for({1, N}))(
fun(A) ->
(for({A + 1, N}))(
fun(B) ->
(for({B + 1, N}))(
fun(C) ->
case A * A + B * B == C * C of
true -> io:format("~p ", [{A, B, C}]);
false -> ok
end
end)
end)
end).
It's too small for external repository. I keep it in my utilities module.
If you find it helpful, here is code:
-export([for/1, for/2]).
for(Through) ->
for([], Through).
for(InitAcc, Opts) when is_tuple(Opts) ->
{Init, Range, Step, Guard} = for_apply_default_opts(Opts),
fun(Fun) ->
UpdFun = if
is_function(Fun, 1) ->
fun(I, _FAcc) -> Fun(I) end;
is_function(Fun, 2) ->
Fun
end,
for_iter(UpdFun, InitAcc, Init, Range, Step, Guard) end;
for(InitAcc, List) when is_list(List) ->
fun(Fun) -> for_list_eval(Fun, InitAcc, List) end.
for_iter(Fun, Acc, I, Range, Step, Guard) ->
case Guard(I, Range, Acc) of
false ->
Acc;
true ->
NewAcc = Fun(I, Acc),
for_iter(Fun, NewAcc, Step(I, NewAcc), Range, Step, Guard)
end.
for_list_eval(Fun, Acc, List) ->
if
is_function(Fun, 1) ->
lists:foreach(Fun, List);
is_function(Fun, 2) ->
lists:foldl(Fun, Acc, List)
end.
for_apply_default_opts({Range}) ->
DefaultInit = 1,
for_apply_default_opts({DefaultInit, Range});
for_apply_default_opts({Init, Range}) ->
DefaultStep = 1,
for_apply_default_opts({Init, Range, DefaultStep});
for_apply_default_opts({Init, Range, Step}) ->
DefaultGuard = case (Step > 0) or is_function(Step) of
true -> fun(I, IterRange, _Acc) -> I =< IterRange end;
false -> fun(I, IterRange, _Acc) -> I >= IterRange end
end,
for_apply_default_opts({Init, Range, Step, DefaultGuard});
for_apply_default_opts({Init, Range, Step, Guard}) when is_function(Guard, 2) ->
for_apply_default_opts({Init, Range, Step, fun(I, IterRange, _Acc) -> Guard(I, IterRange) end});
for_apply_default_opts({Init, Range, Step, DefaultGuard}) when is_number(Step) ->
for_apply_default_opts({Init, Range, fun(I, _Acc) -> I + Step end, DefaultGuard});
for_apply_default_opts({Init, Range, Step, DefaultGuard}) when is_function(Step, 1) ->
for_apply_default_opts({Init, Range, fun(I, _Acc) -> Step(I) end, DefaultGuard});
for_apply_default_opts({_Init, _Range, _Step, _DefaultGuard} = Opts) ->
Opts.

Erlang Bubble sort

I'm learning Erlang and decided to implement bubble sort in it, it took me some effort and in result i've succeded, but i see that my way of thinking is incorrect, is there more effecient way to implement it or not?
bubble_sort(L) ->
if
length(L) > 1 ->
SL=bubble_sort_p(L),
bubble_sort(lists:sublist(SL,1,length(SL)-1)) ++ [lists:last(SL)];
true -> L
end.
bubble_sort_p([]) -> [];
bubble_sort_p([F | R]) ->
case length(R) > 0 of
true -> case F > hd(R) of
true -> [hd(R)] ++ bubble_sort_p([F|tl(R)]);
false -> [F] ++ bubble_sort_p([hd(R)|tl(R)])
end;
false -> [F]
end.
The implementation from the top of my head would be:
bubble_sort(L) -> bubble_sort(L, [], false).
bubble_sort([A, B | T], Acc, _) when A > B ->
bubble_sort([A | T], [B | Acc], true);
bubble_sort([A, B | T], Acc, Tainted) ->
bubble_sort([B | T], [A | Acc], Tainted);
bubble_sort([A | T], Acc, Tainted) ->
bubble_sort(T, [A | Acc], Tainted);
bubble_sort([], Acc, true) ->
bubble_sort(lists:reverse(Acc));
bubble_sort([], Acc, false) ->
lists:reverse(Acc).
If we are talking efficiency, we obvioulsy should not go for bubble sort in the first place.
Allow me to re-write your code in a much more readable fashion (without changing anything about the semantics):
bubble_sort(L) when length(L) =< 1 ->
L;
bubble_sort(L) ->
SL = bubble_sort_p(L),
bubble_sort(lists:sublist(SL,1,length(SL)-1)) ++ [lists:last(SL)].
bubble_sort_p([]) ->
[];
bubble_sort_p([F]) ->
[F];
bubble_sort_p([F,G|T]) when F > G ->
[G|bubble_sort_p([F|T])];
bubble_sort_p([F,G|T]) ->
[F|bubble_sort_p([G|T])].
This should allow for much easier contemplation of the things actually going on in the program.
And employing lists:foldr:
bubble(List) ->
Step = fun
(E,{S,[]}) -> {S,[E]};
(E,{_,[X|XS]}) when E > X -> {swapped,[X|[E|XS]]};
(E,{S,XS}) -> {S,[E|XS]}
end,
case lists:foldr(Step, {intact,[]}, List) of
{intact,XS} -> XS;
{swapped,XS} -> bubble(XS)
end.
There is an answer at http://en.literateprograms.org/Bubble_sort_%28Erlang%29
-module(bubblesort).
-export([sort/1]).
-import(lists, [reverse/1]).
sort(L) -> sort(L, [], true).
sort([], L, true) -> reverse(L);
sort([], L, false) -> sort(reverse(L), [], true);
sort([ X, Y | T ], L, _) when X > Y ->
sort([ X | T ], [ Y | L ], false);
sort([ X | T ], L, Halt) -> sort(T, [ X | L ], Halt).
An example for sorting 2,4,3,5,1
sort([2,4,3,5,1])
round 1
=> sort([2,4,3,5,1], [], true)
=> sort([4,3,5,1], [2], true)
=> sort([4,5,1], [3,2], false)
=> sort([5,1], [4,3,2], false)
=> sort([5], [1,4,3,2], false)
=> sort([], [5,1,4,3,2], false)
=> sort([2,3,4,1,5], [], true)
round 2
=> sort([3,4,1,5], [2], true)
=> sort([4,1,5], [3,2], true)
=> sort([4,5], [1,3,2], false)
=> sort([5], [4,1,3,2], false)
=> sort([], [5,4,1,3,2], false)
=> sort([2,3,1,4,5], [], true)
round 3
=> sort([3,1,4,5], [2], true)
=> sort([3,4,5], [1,2], false)
=> sort([4,5], [3,1,2], false)
=> sort([5], [4,3,1,2], false)
=> sort([], [5,4,3,1,2], false)
=> sort([2,1,3,4,5], true)
round 4
=> sort([2,3,4,5], [1], false)
=> sort([3,4,5], [2,1], false)
=> sort([4,5], [3,2,1], false)
=> sort([5], [4,3,2,1], false)
=> sort([], [5,4,3,2,1], false)
=> sort([1,2,3,4,5], [], true)
round 5
=> sort([2,3,4,5], [1], true)
=> sort([3,4,5],[2,1], true)
=> sort([4,5],[3,2,1], true)
=> sort([5],[4,3,2,1], true)
=> sort([], [5,4,3,2,1], true)
=> [1,2,3,4,5]
-module(bubbleSort).
-compile(export_all).
-include_lib("eunit/include/eunit.hrl").
sort(L) ->
sort(L, length(L), []).
sort(_L, 0, _Res) -> [];
sort([H | _T], 1, Res) -> [H | Res];
sort(L, Len, Res) ->
T1 = lists:sublist(L, 1, Len),
T2 = inner_sort(T1, []),
Last = lists:last(T2),
sort(T2, Len - 1, [Last | Res]).
inner_sort([A, B], Res) when (A < B)->
Res ++ [A, B];
inner_sort([A, B], Res) ->
Res ++ [B, A];
inner_sort([A, B | T], Res) when (A < B) ->
inner_sort([B | T], Res ++ [A]);
inner_sort([A, B | T], Res) ->
inner_sort([A | T], Res ++ [B]).
test()->
L = [5, 3, -1, 10, 6, 100, 99],
?assert(sort([]) =:= []),
?assert(sort([1]) =:= [1]),
?assert(sort([1, 2, 3, 4]) =:= [1, 2, 3, 4]),
?assert(sort([10, 5, 3, 2, 1]) =:= [1, 2, 3, 5, 10]),
?assert(sort(L) =:= [-1, 3, 5, 6, 10, 99, 100]).
Easy to read & understand implementation w ascending sort direction.
Tail recursion employed, computational complexity & memory usage are classic.
bsort([]) -> [];
bsort([H|T]) -> bsort([H|T],[]).
bsort([],[]) -> [];
bsort([],[H|T]) -> [H|T];
bsort([A|B], Sorted) when is_list(Sorted) -> M = lists:max([A|B]), bsort([A|B] -- [M], [M] ++ Sorted).

Resources