full disclosure. interview/prescreen question failed solve during interview. decided implement in erlang own benefit.
here's problem statement:
you must find number of subsets of array largest number sum of remaining numbers. example, input of: 1, 2, 3, 4, 6
the subsets be
1 + 2 = 3
1 + 3 = 4
2 + 4 = 6
1 + 2 + 3 = 6
here's solution:
% credit: http://stackoverflow.com/questions/1459152/erlang-listsindex-of-function index_of(item, list) -> index_of(item, list, 1). index_of(_, [], _) -> not_found; index_of(item, [item|_], index) -> index; index_of(item, [_|tl], index) -> index_of(item, tl, index+1). % find sums findsums(l) -> permutations=generateallcombos(l), lists:filter(fun(ll) -> case index_of(lists:sum(ll), l) of not_found -> false; _ -> true end end, permutations). % generate combinations of size 2..legnth(l)-1 generateallcombos(l) -> newl=l--[lists:last(l)], sizes=lists:seq(2,length(newl)), lists:flatmap(fun(x) -> simplepermute(newl,x) end, sizes). % generate list of permutations of size r list l simplepermute(_,r) when r == 0 -> [[]]; simplepermute(l,r) -> [[x|t] || x <- l, t<-simplepermute(lists:nthtail(index_of(x,l),l),r-1)]. here's example run:
example:
18> maxsubsetsum_app:findsums([1,2,3,4,6]). [[1,2],[1,3],[2,4],[1,2,3]] questions
- dear erlangers (erlangists?) canonical erlang you?
- is there better way did?
- is there cleaner on solution (this quite brute force).
thank you!
it seems algorithm:
- generating combinations (2^n)
- summing each set of combinations (n)
- searching list each sum (n)
that looks it's n*2^n. think that's fast can go in terms of computation, since have try on order of combinations every number in list. maybe can correct me on that.
however, space efficiency seems 2^n, since stores combinations, unnecessary.
this came with, accumulates results:
- for each item, search rest of list combinations add it.
- in order find combinations, subtract first number of list target number, , search rest of list combinations add difference.
-module(subsets). -export([find_subsets/1]). find_subsets(numlist) -> reversesorted = lists:reverse(lists:sort(numlist)), find_each_subset(reversesorted, []). find_each_subset([], subsets) -> subsets; find_each_subset([first | reversesorted], subsets) -> [ { first, recurse_find_subsets(first, reversesorted, [])} | find_each_subset(reversesorted, subsets)]. recurse_find_subsets(_target, [], sets) -> sets; recurse_find_subsets(target, [target | _numbers], []) -> [[target]]; recurse_find_subsets(target, [first | numbers], sets) when target - first > 0 -> subsets = recurse_find_subsets(target - first, numbers, []), newsets = lists:map(fun(subset) -> [ first | subset] end, subsets), recurse_find_subsets(target, numbers, lists:append(newsets, sets)); recurse_find_subsets(target, [_first | numbers], sets) -> recurse_find_subsets(target, numbers, sets). output:
5> subsets:find_subsets([6,4,3,2,1]). [{6,[[3,2,1],[4,2]]},{4,[[3,1]]},{3,[[2,1]]},{2,[]},{1,[]}]
Comments
Post a Comment