How to validate day and time in Erlang? - erlang

How do I validate today is business day and also current time is in between two time? I tried below code but I can only check after or before time.
is_past_15() ->
{_, {Hour, _, _}} = calendar:local_time(),
Hour >= 15.

validate today is business day
-module(a).
-compile(export_all).
is_business_day(Date) ->
calendar:day_of_the_week(Date) =< 5.
In the shell:
7> c(a).
a.erl:2:2: Warning: export_all flag enabled - all functions will be exported
% 2| -compile(export_all).
% | ^
{ok,a}
8> {Date, _} = calendar:local_time().
9> a:is_business_day(Date).
true
also current time is in between two time.
-module(a).
-compile(export_all).
is_between(BeginDT, EndDT, DT) ->
BeginSecs = calendar:datetime_to_gregorian_seconds(BeginDT),
EndSecs = calendar:datetime_to_gregorian_seconds(EndDT),
DTSecs = calendar:datetime_to_gregorian_seconds(DT),
(BeginSecs =< DTSecs) and (DTSecs =< EndSecs).
In the shell:
13> BeginDT = {{2021, 1, 20}, {10, 15, 0}}. %% 1/20/21 10:15:00 AM
{{2021,1,20},{10,15,0}}
14> EndDT = {{2021, 1, 20}, {10, 20, 0}}. %% 1/20/2021 10:20:00 AM
{{2021,1,20},{10,20,0}}
15> DT = {{2021, 1, 20}, {10, 17, 0}}. %% 1/20/2021 10:17:00 Am
{{2021,1,20},{10,17,0}}
16> a:is_between(BeginDT, EndDT, DT).
true

Related

ERLANG: Spawning funs. Different behaviour

Why is the difference between two spawning methods listed below?
1> G = fun(X) -> io:format("~p ", [X]) end.
#Fun<erl_eval.44.97283095>
2> [spawn(fun() -> G(X) end) || X <- [1, 2, 3] ].
1 2 3 [<0.82.0>,<0.83.0>,<0.84.0>]
3> [spawn(fun() -> fun(X) -> io:format("~p ", [X]) end end) || X <- [1, 2, 3] ].
[<0.86.0>,<0.87.0>,<0.88.0>]
4>
In the last example, here is the function being spawned:
fun() ->
fun(X) -> io:format("~p ", [X]) end
end
It doesn't actually do anything - it creates an anonymous function but doesn't call it.
To call the function, you'd do something like this:
fun() ->
TheFunction = fun(Y) -> io:format("~p ", [Y]) end,
TheFunction(X)
end
(I changed the argument name from X to Y for clarity. It doesn't really matter, as function arguments overshadow variables from an outer scope.)
Or to fit it back in the one-liner:
4> [spawn(fun() -> TheFunction = fun(Y) -> io:format("~p ", [Y]) end, TheFunction(X) end) || X <- [1, 2, 3] ].
1 2 3 [<0.94.0>,<0.95.0>,<0.96.0>]
Now it behaves the same as the other example.
Thank you!
It's clear enough.
The anonymous function have to be named to be called. For example, if we pass anonymous function as a parameter to another function, it only can be called as a named argument inside wrapping function.

Erlang records printing

I am writing a program in erlang and I created this record:
-record(tree, {node, left, right}).
I want to print a list of different trees, and this is how prints it:
[{tree,x1,{x3,0,1},{tree,x2,1,{x3,0,1}}}, {tree,x1,{tree,x3,0,1},{tree,x3,{x2,1,0},1}}]
Is there an easy to print it without the word "tree"? (the name of the record).
Sure I can just define it as a tuple and not a record, but I want to try to work with a record so the code will be more organized.
Yes, there is. Inside shell you can use:
Eshell V9.1 (abort with ^G)
1> Trees = [
{tree, x1, {x3, 0, 1}, {tree, x2, 1, {x3, 0, 1}}},
{tree, x1, {tree, x3, 0, 1}, {tree, x3, {x2, 1, 0}, 1}}
].
[{tree,x1,{x3,0,1},{tree,x2,1,{x3,0,1}}},{tree,x1,{tree,x3,0,1},{tree,x3,{x2,1,0},1}}]
2> Format = fun({tree, Node, Left, Right}, F) ->
{
Node,
if
element(1, Left) == tree -> F(Left, F);
true -> Left
end,
if
element(1, Right) == tree -> F(Right, F);
true -> Right
end
}
end.
#Fun<erl_eval.12.99386804>
3> [Format(X, Format) || X <- Trees].
[
{{x3, 0, 1}, {1, {x3, 0, 1}}},
{{0, 1}, {{x2, 1, 0}, 1}}
]
And in your module you can place for example a format/1 function:
-module(tree).
-record(tree, {node, left, right}).
-export([format/1]).
format(#tree{node = Node, left = L, right = R}) ->
{Node, maybe_format(L), maybe_format(R)};
format([#tree{}=Tree | Trees]) ->
[format(Tree) | format(Trees)];
format([]) ->
[].
maybe_format(X) when erlang:is_record(X, tree) ->
format(X);
maybe_format(X) ->
X.
And use it in shell or wherever you want:
Eshell V9.1 (abort with ^G)
% Compile my module which is inside current directory:
1> c(tree).
{ok,tree}
% format single tree:
2> tree:format({tree, node, left, right}).
{node,left,right}
% format list of trees:
3> tree:format([{tree,x1,{x3,0,1},{tree,x2,1,{x3,0,1}}}, {tree,x1,{tree,x3,0,1},{tree,x3,{x2,1,0},1}}]).
[
{x1, {x3, 0, 1}, {x2, 1, {x3, 0, 1}}},
{x1, {x3, 0, 1}, {x3, {x2, 1, 0}, 1}}
]

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

Elixir Queue (Erlang :queue) - Enum.Take

Going through the docs of the erlang queue here: http://erlang.org/doc/man/queue.html#member-2
I don't see a way to pull off a range of items like Enum.Take. Has anyone solved this?
Erlang is proud of using recursion wherever possible instead of imperative calls. The desired behaviour might be easily implemented:
def take(q, amount), do: do_take(q, {amount, []})
defp do_take(q, {n, acc}) when n > 0 do
case :queue.out(q) do
{{:value, e}, rest} ->
do_take(rest, {n - 1, [e | acc]})
{:empty, q} -> {acc, q}
end
end
defp do_take(q, {_, acc}), do: {acc, q}
I have not tested this code, but I believe the idea is clear.
Or, with a fancy else syntax:
def take(q, amount), do: do_take(q, {amount, []})
defp do_take(q, {n, acc}) when n > 0 do
:queue.out(q)
else
{{:value, e}, rest} -> do_take(rest, {n - 1, [e | acc]})
{:empty, q} -> {acc, q}
end
defp do_take(q, {_, acc}), do: {acc, q}
I don't see a way to pull off a range of items like Enum.Take. Has
anyone solved this?
Yep. From the page you linked:
split(N :: integer() >= 0, Q1 :: queue(Item)) ->
{Q2 :: queue(Item), Q3 :: queue(Item)}
Splits Q1 in two. The N front items are put in Q2 and the rest in Q3.
So, you can do this:
-module(my).
-compile(export_all).
take(N, Q) ->
{Taken, _Rest} = queue:split(N, Q),
Taken.
In the shell:
1> c(my).
my.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,my}
2> Q = queue:from_list([1,2,3,4]).
{[4],[1,2,3]}
3> T1 = my:take(1, Q).
{[],[1]}
4> queue:to_list(T1).
[1]
5> T3 = my:take(3, Q).
{[3],[1,2]}
6> queue:to_list(T3).
[1,2,3]
All operations have an amortized O(1) running time, except filter/2,
join/2, len/1, member/2, split/2 that have O(n).

Is there any function in erlang to check if the list is a proplist? [duplicate]

This question already has answers here:
is_proplist in erlang?
(2 answers)
Closed 8 years ago.
I have a data in format of tuple :
{data, [[{a, 2}, {b, 3}], [{x, 1}, {v,2}], [1,2,3,4], "hello world", 1111]}
Since,
{data, [[{a, 2}, {b, 3}], [{x, 1}, {v,2}], [1,2,3,4], "hello world", 1111]} = {data, L}.
And need to check if the element of L is a proplist, like here : [{a, 2}, {b, 3}] and [{x, 1}, {v,2}] are proplists.
Is there any function in erlang to check whether the list is proplist?
is_proplist(List) should return true or false
The function F1 below checks for proplists (assuming that a single atom 'a' is equivalent to {'a',true})
1> F = fun(X) when is_atom(X) -> true; ({X,_}) when is_atom(X) -> true; (_) -> false end.
#Fun<erl_eval.6.80484245>
2> L = [[{a, 2}, {b, 3}], [{x, 1}, {v,2}], [1,2,3,4], "hello world", 1111].
[[{a,2},{b,3}],[{x,1},{v,2}],[1,2,3,4],"hello world",1111]
3> F1 = fun(X) when is_list(X) -> lists:all(F,X); (_) -> false end.
#Fun<erl_eval.6.80484245>
4> [X || X <- L, F1(X)].
[[{a,2},{b,3}],[{x,1},{v,2}]]
5>

Resources