Split list into 2 lists of equal sum erlang - erlang

I want to know how to split a given list into two lists such that both lists have the same sum. I want to do that by using concurrency. I am doing this in erlang.
So, I'm doing something like this:
Read the list, if its sum is even, then proceed else fail. Take the first element of the list and check if it is greater than half of the sum, if not, then I add this element to a new list. Next, I take the second element of the list, check the sum of this element and that of the new list and do the same operation. And so on.. Such that when the sum in the new list is equal to half of the sum of the first list, it calls another function to send the remaining elements.
-module(piles_hw).
-compile(export_all).
start([]) -> 0;
start(List) ->
Total = lists:foldl(fun(X, Sum)-> X+Sum end,0,List),
if (Total rem 2) == 0 ->
Total/2,
copy_to_list_one([],List,start(List));
true ->
func_fail()
end.
copy_to_list_one(L1,[H|T],X)->
Y =lists:sum(L1)+H,
if Y<X ->
copy_to_list_one(lists:append(L1,[H]),lists:delete(H,[H|T]),X);
Y==X ->
take(lists:append(L1,[H]));
Y>X ->
copy_to_list_one(L1,lists:delete(H,[H|T]),X)
end;
copy_to_list_one(L1,[],X)->
copy_func_two([1,2,3,4,19,20,28,14,11],X).
copy_func_two([H|T],X)->
copy_to_list_one([],lists:append(T,[H]),X).
take(L3)->
io:format("~w",[L3]).
func_fail() ->
io:format("~n fail ~n").
But, in this way I go into an infinite loop sometimes. Could somebody help?

Edit:
Pascal was entirely correct: there is no algorithm (at least not that I could come up with) that can solve certain sets by running down the list one item at a time. (In particular when half the sum of the list equals X * N where X is present in the list N times.) I initially put a flawed algorithm here.
That got me excited in the nerdiest of ways, so here is an exhaustive algorithm involving the pairs of [{P, (List - P)} || P <- powerset(List)].
There are some lists:usort/1 shenanigans in there that I didn't clean up to uniquify the list prior to the final comparison (otherwise you get duplicate similar pairs, which is ugly). Anyway, ugly, but now correct:
comblit(List) ->
Power = powerset(List),
Lists = lists:usort([lists:sort([Z, lists:subtract(List, Z)]) || Z <- Power]),
Pairs = lists:map(fun([H|[B|[]]]) -> {H, B} end, Lists),
[{Z, X} || {Z, X} <- Pairs, lists:sum(Z) == lists:sum(X)].
powerset([H|T]) ->
Part = powerset(T),
powerset(Part, H, Part);
powerset([]) -> [[]].
powerset(A, Part, [H|T]) ->
powerset([[Part|H]|A], Part, T);
powerset(A, _, []) -> A.
This is still not a concurrent solution, but the path to making it concurrent is a lot more obvious now.
Thanks for pointing that out, Pascal. That was sort of fun.

I have this solution that is not concurrent:
-module(split).
-export([split/1,t_ok/0,t_too_long/0,t_fail/0,t_crash/0]).
%% [EDIT]
%% Don't use this code, it fails with negative integers!
% Exported
%% take a list and split it in 2 list which sum are equals
split(L=[_|_]) ->
T2 = lists:sum(L),
{ok, TRef} = timer:send_after(20000,too_long),
R = case T2 rem 2 of
1 -> {error,fail};
0 -> split(tl(L),[hd(L)],[],T2 div 2,hd(L),0)
end,
timer:cancel(TRef),
R.
% test
t_ok() -> split([1,2,3,4,5,6,7]).
t_too_long() -> split(lists:seq(1,3+4*100000)).
t_fail() -> split([2,4,6,10000,8,6]).
t_crash() -> split([]).
% private
split([H|Q],A,B,T,Asf,_Bsf) when H + Asf == T -> {ok,{[H|A],B ++ Q}};
split([H|Q],A,B,T,_Asf,Bsf) when H + Bsf == T -> {ok,{A ++ Q,[H|B]}};
split([H|Q],A,B,T,Asf,Bsf) when H + Asf > T, H + Bsf < T -> c_split(Q,A,[H|B],T,Asf,Bsf+H);
split([H|Q],A,B,T,Asf,Bsf) when H + Asf < T, H + Bsf > T -> c_split(Q,[H|A],B,T,Asf+H,Bsf);
split([H|Q],A,B,T,Asf,Bsf) when H + Asf < T, H + Bsf < T ->
case c_split(Q,A,[H|B],T,Asf,Bsf+H) of
{error,fail} -> c_split(Q,[H|A],B,T,Asf+H,Bsf);
R -> R
end;
split([],A,B,_T,_T,_T)-> {ok,{A,B}};
split(_,_,_,_,_,_) -> {error,fail}.
c_split(L,A,B,T,Asf,Bsf) ->
receive
too_long -> {error,too_long}
after 0 ->
split(L,A,B,T,Asf,Bsf)
end.
To turn it concurrent, you could replace the line 0 -> split(tl(L),[hd(L)],[],T2 div 2,hd(L),0) by a call to a function which spawn_link several processes (as much as there are core available) which start the split/6 function with different initial conditions. The split/6 must have a 7th parameter: the Pid of the main process where it will send back its answer. The main process wait for answers and stop
if a solution is found
if all processes fail to find one
if the time out occurs
I have edited the code following #Odobenus remark (but it still fail on [] -> {ok,[],[]} :o), and I also made a concurrent version. The funny thing is that for this kind of problem, and with the input list I use (a lists:seq) there are so many solution that any start sequence I choose can give a solution, so the concurrent version is slower.

Related

Applying function repeatedly to generate List

I currently have this f# function
let collatz' n =
match n with
| n when n <= 0 -> failwith "collatz' :n is zero or less"
| n when even n = true -> n / 2
| n when even n = false -> 3 * n + 1
Any tips for solving the following problem in F#?
As said in the comments, you need to give a bit more information for any really specific advice, but based on what you have I'll add the following.
The function you have declared satisfies the definition of the Collatz function i.e. even numbers -> n/2 ,and
odd number -> 3n + 1.
So really you only need applyN, let's break it down into its pieces
( `a -> `a) -> `a -> int -> `a list
applyN f n N
That definition is showing you exactly what the function expects.
lets look at f through to N
f -> a function that takes some value of type 'a (in your case likely int) and produces a new value of type 'a.
This corresponds to the function you have already written collatz`
n -> is your seed value. I don't think elaboration is required.
N -> This looks like a maximum amount of steps to go through. In the example posted, if N was larger, you would see a loop [ 1 ;4; 2; 1; 4... ]
and if it was smaller it would stop sooner.
So that is what the function takes and need to do, so how can we achieve this?
I would suggest making use of scan.
The scan function is much like fold, but it returns each interim state in a list.
Another option would be making use of Seq.unfold and then only taking the first few values.
Now, I could continue and give some source code, but I think you should try yourself for now.

Find the length of the longest substring

I see questions similar like this ones, but eventually, for different programming languages. I'm trying to solve this little problem:
Given a string, find the length of the longest substring without
repeating characters. For example, the longest substring without
repeating letters for abcabcbb is abc, which the length is 3. For
bbbbb the longest substring is b, with the length of 1.
I don't need the anwer to it but why what I have so far fails in the second iteration.
1> longest_substring:main("abcabcbb").
H: 97, T: "bcabcbb", Sub: []
Is 97 in []? false
H: 98, T: "cabcbb", Sub: 97
** exception error: no function clause matching string:chr(97,98,1) (string.erl, line 99)
in function longest_substring:process/2 (src/leetcode/algorithms/longest_substring.erl, line 28)
2>
This is the source code:
-module(longest_substring).
-export([main/1]).
-spec main(S :: string()) -> string().
%%%==================================================================
%%% Export
%%%==================================================================
main(S) -> process(S, "").
%%%==================================================================
%%% Internal
%%%==================================================================
process([], Sub) -> string:len(Sub);
process([H | T], Sub) ->
io:format("H: ~w, T: ~p, Sub: ~p~n", [H, T, Sub]),
Found = string:chr(Sub, H),
io:format("Is ~w in ~p? ~p~n", [H, Sub, Found =/= 0]),
% Don't know how to make this `if` thing better...
if
Found > 0 -> process(T, H);
_ -> process(T, string:concat(Sub, H))
end.
You have two places where you are treating character H as a string, both within the if:
if
Found > 0 -> process(T, H);
_ -> process(T, string:concat(Sub, H))
end.
Both appearances of H here need to be [H] instead, to form a string from the single character. (Also, your final clause in the if needs to use true, not an underscore — you should be getting a compiler error about this.)
Currently your solution returns a number, not a string. It also fails to remember any longer substring that might appear early in the string. To fix that, you need to remember the longest substring you've seen so far, which means you need another accumulator:
-module(longest_substring).
-export([main/1]).
-spec main(S :: string()) -> string().
main(S) -> process(S, {0,[]}, {0,[]}).
process([], {LL,Last}, {LG,_}) when LL > LG -> Last;
process([], _, {_,Long}) -> Long;
process([H | T], {LL,Last}=Sub, {LG,_}=Long) ->
case string:rchr(Last, H) of
0 ->
process(T, {LL+1,string:concat(Last,[H])}, Long);
N ->
NewLast = {1+LL-N,string:substr(Last,N+1)++[H]},
process(T, NewLast,
case LL > LG of
true ->
Sub;
false ->
Long
end)
end.
The main/1 function passes two accumulators to process/3, each of which is a pair of a length and a list. The first accumulator tracks the current substring, and the second tracks the longest substring seen so far.
In the last clause of process/3, we first check if H is in the current substring; if not, we add it to the current substring, increase its length by 1, and call process/3 again with the tail of the string. But if H is found in the current substring, we calculate the new current substring using the return value of string:rchr/2 to preserve the longest portion of the previous substring that we can (the original solution does not do this). We then check to see if the length of the current substring is greater than the current longest substring, and if so, we make it the longest substring, or if not we throw it away and keep the current longest substring, and then continue with the tail of the string. (Note that we could also make this check for greater or equal instead of greater; this would make our function return the last longest substring we find rather than the first.)
The first two clauses of process/3 handle the case where the input string has been fully processed. They just decide if the current substring is longer than the longest seen so far and return the longer of the two. (The alternative of using a greater or equal comparison applies here as well.)
for fun, I propose you to avoid complex search. In this solution I create a process for each element of the list holding: the element itself, the Pid of the next process/element in the list, and the Pid of the caller.
To initiate the search, I send to each process/element an empty list.
Each time a process/element receives a list, it checks if its stored element is a member of the received list. If yes, the list is send back to the caller, if not the element is prepend to the list and the new list is sent to the next process/element to continue the evaluation.
The caller process simply waits for as many returned messages as it has sent.
I have added a stop message and a special case for the last element of the list.
-module (longer).
-compile([export_all]).
char_proc(V,Next,Caller) ->
receive
stop -> ok;
Str ->
case lists:member(V,Str) of
true -> Caller ! Str;
false -> send(Next,Caller,[V|Str])
end,
char_proc(V,Next,Caller)
end.
send(noproc,Caller,Str) -> Caller ! Str;
send(Next,_,Str) -> Next ! Str.
find(Str) ->
Me = self(),
Pids = tl(lists:reverse(lists:foldl(fun(X,Acc) -> Pid = spawn(?MODULE,char_proc,[X,hd(Acc),Me]), [Pid|Acc] end,[noproc],Str))),
[X ! [] || X <- Pids],
R = receive_loop(0,[],length(Str)),
[X ! stop || X <- Pids],
R.
receive_loop(N,S,0) -> {N,S};
receive_loop(N,S,I) ->
receive
M when length(M) > N ->
receive_loop(length(M),M,I-1);
_ ->
receive_loop(N,S,I-1)
end.
tested in the shell:
1> c(longer).
{ok,longer}
2> longer:find("abcdad").
{4,"abcd"}
3> longer:find("abcdadtfrseqgepz").
{9,"adtfrseqg"}
4> longer:find("aaaaaaaaaaaa").
{1,"a"}
5> longer:find("abcdatfrseqgepz").
{11,"bcdatfrseqg"}
6>
Note there is no guarantee about witch sub-string will be returned if it exists several solutions, it is very easy to modify the code to return either the first sub-string or all of them.

Simple exercise of OCaml about list

Good Morning everyone,
I must do an exercise of Programming, but i'm stuck!
Well, the exercise requires a function that given a list not empty of integers, return the first number with maximum number of occurrences.
For example:
mode [1;2;5;1;2;3;4;5;5;4:5;5] ==> 5
mode [2;1;2;1;1;2] ==> 2
mode [-1;2;1;2;5;-1;5;5;2] ==> 2
mode [7] ==> 7
Important: the exercise must be in functional programming
My idea is:
let rec occurences_counter xs i = match xs with
|[] -> failwith "Error"
|x :: xs when x = i -> 1 + occurences_counter xs i
|x :: xs -> occurences_counter xs i;;
In this function i'm stuck:
let rec mode (l : int list) : int = match l with
|[] -> failwith "Error"
|[x] -> x
|x::y::l when occurences_counter l x >= occurences_counter l y -> x :: mode l
|x::y::l when occurences_counter l y > occurences_counter l x -> y :: mode l;;
Thanks in advance, i'm newbie in programming and in stackoverflow
Sorry for my english
one solution : calculate first a list of couples (number , occurences).
hint : use List.assoc.
Then, loop over that list of couple to find the max occurrence and then return the number.
One suggestion:
your algorithm could be simplified if you sort the list before. This has O(N log(N)) complexity. Then measure the longest sequence of identical numbers.
This is a good strategy because you delegate the hard part of the work to a well known algorithm.
It is probably not the most beautiful code, but here is with what i came up (F#). At first i transform every element to an intermediate format. This format contains the element itself, the position of it occurrence and the amount it occurred.
type T<'a> = {
Element: 'a
Position: int
Occurred: int
}
The idea is that those Records can be added. So you can first transform every element, and then add them together. So a list like
[1;3]
will be first transformed to
[{Element=1;Position=0;Occurred=1}; {Element=3;Position=1;Occurred=1}]
By adding two together you only can add those with the same "Element". The Position with the lower number from both is taken, and Occurred is just added together. So if you for example have
{Element=3;Position=1;Occurred=2} {Element=3;Position=3;Occurred=2}
the result will be
{Element=3;Position=1;Occurred=4}
The idea that i had in mind was a Monoid. But in a real Monoid you had to come up that you also could add different Elements together. By trying some stuff out i feel that the restriction of just adding the same Element where way more easier. I created a small Module with the type. Including some helper functions for creating, adding and comparing.
module Occurred =
type T<'a> = {
Element: 'a
Position: int
Occurred: int
}
let create x pos occ = {Element=x; Position=pos; Occurred=occ}
let sameElements x y = x.Element = y.Element
let add x y =
if not <| sameElements x y then failwith "Cannot add two different Occurred"
create x.Element (min x.Position y.Position) (x.Occurred + y.Occurred)
let compareOccurredPosition x y =
let occ = compare x.Occurred y.Occurred
let pos = compare x.Position y.Position
match occ,pos with
| 0,x -> x * -1
| x,_ -> x
With this setup i now wrote two additional function. One aggregate function that first turns every element into a Occurred.T, group them by x.Element (the result is a list of list). And then it uses List.reduce on the inner list to add the Occurred with the same Element together. The result is a List that Contains only a single Occurred.T for every Element with the first Position and the amount of Occurred items.
let aggregate =
List.mapi (fun i x -> Occurred.create x i 1)
>> List.groupBy (fun occ -> occ.Element)
>> List.map (fun (x,occ) -> List.reduce Occurred.add occ)
You could use that aggregate function to now implement different aggregation logic. In your case you only wanted the one with the highest Occurrences and the lowest position. I wrote another function that did that.
let firstMostOccurred =
List.sortWith (fun x y -> (Occurred.compareOccurredPosition x y) * -1) >> List.head >> (fun x -> x.Element)
One note. Occurred.compareOccurredPosition is written that it sorts everything in ascending order. I think people expecting it in this order to go to the smallest to the biggest element by default. So by default the first element would be the element with the lowest occurrence and the biggest Position. By multiplying the result of it with -1 you turn that function into a descending sorting function. The reason why i did that is that i could use List.head. I also could use List.last to get the last element, but i felt that it would be better not to go through the whole list again just to get the last element. On top of it, you didn't wanted an Occurred.T you wanted the element itself, so i unwrap the Element to get the number.
Here is everything in action
let ll = [
[1;2;5;1;2;3;4;5;5;4;5;5]
[2;1;2;1;1;2]
[-1;2;1;2;5;-1;5;5;2]
[7]
]
ll
|> List.map aggregate
|> List.map firstMostOccurred
|> List.iter (printfn "%d")
This code will now print
5
2
2
7
It has still some rough edges like
Occurred.add throws an exception if you try to add Occurred with different Elements
List.head throws an exception for empty lists
And in both cases no code is written to handle those cases or making sure an exception will not raise.
You need to process you input list while maintaining a state, that stores the number of occurrences of each number. Basically, the state can be a map, where keys are in the domain of list elements, and values are in domain of natural numbers. If you will use Map the algorithm would be of O(NlogN) complexity. You can also use associative list (i.e., a list of type ('key,'value) list) to implement map. This will lead to quadratic complexity. Another approach is to use hash table or an array of the length equal to the size of the input domain. Both will give you a linear complexity.
After you collected the statistics, (i.e., a mapping from element to the number of its occurrences) you need to go through the set of winners, and choose the one, that was first on the list.
In OCaml the solution would look like this:
open Core_kernel.Std
let mode xs : int =
List.fold xs ~init:Int.Map.empty ~f:(fun stat x ->
Map.change stat x (function
| None -> Some 1
| Some n -> Some (n+1))) |>
Map.fold ~init:Int.Map.empty ~f:(fun ~key:x ~data:n modes ->
Map.add_multi modes ~key:n ~data:x) |>
Map.max_elt |> function
| None -> invalid_arg "mode: empty list"
| Some (_,ms) -> List.find_exn xs ~f:(List.mem ms)
The algorithm is the following:
Run through input and compute frequency of each element
Run through statistics and compute spectrum (i.e., a mapping from frequency to elements).
Get the set of elements that has the highest frequency, and find an element in the input list, that is in this set.
For example, if we take sample [1;2;5;1;2;3;4;5;5;4;5;5],
stats = {1 => 2; 2 => 2; 3 => 1; 4 => 2; 5 => 5}
mods = {1 => [3]; 2 => [1;2]; 5 => [5]}
You need to install core library to play with it. Use coretop to play with this function in the toplevel. Or corebuild to compile it, like this:
corebuild test.byte --
if the source code is stored in test.ml

Counting down from N to 1

I'm trying to create a list and print it out, counting down from N to 1. This is my attempt:
%% Create a list counting down from N to 1 %%
-module(list).
-export([create_list/1]).
create_list(N) when length(N)<hd(N) ->
lists:append([N],lists:last([N])-1),
create_list(lists:last([N])-1);
create_list(N) ->
N.
This works when N is 1, but otherwise I get this error:
172> list:create_list([2]).
** exception error: an error occurred when evaluating an arithmetic expression
in function list:create_list/1 (list.erl, line 6)
Any help would be appreciated.
You should generally avoid using append or ++, which is the same thing, when building lists. They both add elements to the end of a list which entails making a copy of the list every time. Sometimes it is practical but it is always faster to work at the front of the list.
It is a bit unclear in which order you wanted the list so here are two alternatives:
create_up(N) when N>=1 -> create_up(1, N). %Create the list
create_up(N, N) -> [N];
create_up(I, N) ->
[I|create_up(I+1, N)].
create_down(N) when N>1 -> %Add guard test for safety
[N|create_down(N-1)];
create_down(1) -> [1].
Neither of these are tail-recursive. While tail-recursion is nice it doesn't always give as much as you would think, especially when you need to call a reverse to get the list in the right order. See Erlang myths for more information.
The error is lists:last([N])-1. Since N is an array as your input, lists:last([N]) will return N itself. Not a number you expect. And if you see the warning when compiling your code, there is another bug: lists:append will not append the element into N itself, but in the return value. In functional programming, the value of a variable cannot be changed.
Here's my implementation:
create_list(N) ->
create_list_iter(N, []).
create_list_iter(N, Acc) ->
case N > 0 of
true -> NewAcc = lists:append(Acc, [N]),
create_list_iter(N-1, NewAcc);
false -> Acc
end.
If I correctly understand your question, here is what you'll need
create_list(N) when N > 0 ->
create_list(N, []).
create_list(1, Acc) ->
lists:reverse([1 | Acc]);
create_list(N, Acc) ->
create_list(N - 1, [N | Acc]).
If you work with lists, I'd suggest you to use tail recursion and lists construction syntax.
Also, to simplify your code - try to use pattern matching in function declarations, instead of case expressions
P.S.
The other, perhaps, most simple solution is:
create_list(N) when N > 0 ->
lists:reverse(lists:seq(1,N)).

Overuse of guards in Erlang?

I have the following function that takes a number like 5 and creates a list of all the numbers from 1 to that number so create(5). returns [1,2,3,4,5].
I have over used guards I think and was wondering if there is a better way to write the following:
create(N) ->
create(1, N).
create(N,M) when N =:= M ->
[N];
create(N,M) when N < M ->
[N] ++ create(N + 1, M).
The guard for N < M can be useful. In general, you don't need a guard for equality; you can use pattern-matching.
create(N) -> create(1, N).
create(M, M) -> [M];
create(N, M) when N < M -> [N | create(N + 1, M)].
You also generally want to write functions so they are tail-recursive, in which the general idiom is to write to the head and then reverse at the end.
create(N) -> create(1, N, []).
create(M, M, Acc) -> lists:reverse([M | Acc]);
create(N, M, Acc) when N < M -> create(N + 1, M, [N | Acc]).
(Of course, with this specific example, you can alternatively build the results in the reverse order going down to 1 instead of up to M, which would make the lists:reverse call unnecessary.)
If create/2 (or create/3) is not exported and you put an appropriate guard on create/1, the extra N < M guard might be overkill. I generally only check on the exported functions and trust my own internal functions.
create(N,N) -> [N];
create(N,M) -> [N|create(N + 1, M)]. % Don't use ++ to prefix a single element.
This isn't quite the same (you could supply -5), but it behaves the same if you supply meaningful inputs. I wouldn't bother with the extra check anyway, since the process will crash very quickly either way.
BTW, you have a recursion depth problem with the code as-is. This will fix it:
create(N) ->
create(1, N, []).
create(N, N, Acc) -> [N|Acc];
create(N, M, Acc) -> create(N, M - 1, [M|Acc]).
I don't really think you have over used guards. There are two cases:
The first is the explicit equality test in the first clause of create/2
create(N, M) when N =:= M -> [M];
Some have suggested transforming this to use pattern matching like
create(N, N) -> [N];
In this case it makes no difference as the compiler internally transforms the pattern matching version to what you have written. You can safely pick which version you think feels best in each case.
In the second case you need some form of sanity check that the value of the argument in the range you expect it to be. Doing in every loop is unnecessary and I would move it to an equivalent test in create/1:
create(M) when M > 1 -> create(1, M).
If you want to use an accumulator I would personally use the count version as it saves reversing the list at the end. If the list is not long I think the difference is very small and you can pick the version which feels most clear to you. Anyway, it is very easy to change later if you find it to be critical.

Resources