blob: 343336277f8edcf469dba00a1944c9a34a4a16dd [file] [log] [blame]
% Licensed under the Apache License, Version 2.0 (the "License"); you may not
% use this file except in compliance with the License. You may obtain a copy of
% the License at
%
% http://www.apache.org/licenses/LICENSE-2.0
%
% Unless required by applicable law or agreed to in writing, software
% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
% License for the specific language governing permissions and limitations under
% the License.
-module(couch_tests_combinatorics).
-export([
powerset/1,
permutations/1,
product/1,
binary_combinations/1,
n_combinations/2
]).
%% @doc powerset(Items)
%% Generate powerset for a given list of Items
%% By Hynek - Pichi - Vychodil
%% For example:
%% 1> powerset([foo, bar, baz]).
%% [
%% [foo],
%% [foo,baz],
%% [foo,bar,baz],
%% [foo,bar],
%% [bar],
%% [bar,baz],
%% [baz],
%% []
%% ]
-spec powerset(Elements :: list()) -> [list()].
powerset([]) ->
[[]];
powerset([H | T]) ->
PT = powerset(T),
powerset(H, PT, PT).
powerset(_, [], Acc) ->
Acc;
powerset(X, [H | T], Acc) ->
powerset(X, T, [[X | H] | Acc]).
%% @doc permutations(Items)
%% Return all premutations of given list of Items.
%% from http://erlang.org/doc/programming_examples/list_comprehensions.html
%% For example:
%% 1> permutations([foo, bar, baz]).
%% [
%% [foo, bar, baz],
%% [foo, baz, bar],
%% [bar, foo, baz],
%% [bar, baz, foo],
%% [baz, foo, bar],
%% [baz, bar, foo]
%% ]
-spec permutations(Elements :: list()) -> [list()].
permutations([]) ->
[[]];
permutations(L) ->
[[H | T] || H <- L, T <- permutations(L -- [H])].
%% @doc product({Items1, Items2, ..., ItemsN})
%% Return cartesian product of multiple sets represented as list of lists
%% From: http://stackoverflow.com/a/23886680
%% For example:
%% 1> product([[foo, bar], [1,2,3]]).
%% [
%% [foo, 1],
%% [foo, 2],
%% [foo, 3],
%% [bar, 1],
%% [bar, 2],
%% [bar, 3]
%% ]
-spec product(Elements :: list()) -> [list()].
product([H]) ->
[[A] || A <- H];
product([H | T]) ->
[[A | B] || A <- H, B <- product(T)].
%% @doc binary_combinations(NBits).
%% Generate all combinations of true and false for specified number of bits.
%% For example:
%% 1> binary_combinations(3).
%% [
%% [ false , false , false ],
%% [ false , false , true ],
%% [ false , true , false ],
%% [ false , true , true ],
%% [ true , false , false ],
%% [ true , false , true ],
%% [ true , true , false ],
%% [ true , true , true ]
%% ]
%% 2> length(binary_combinations(3))
%% 8
-spec binary_combinations(NBits :: pos_integer()) -> [list(boolean())].
binary_combinations(NBits) ->
product(lists:duplicate(NBits, [true, false])).
%% @doc combinations(N, Items).
%% Generate all combinations by choosing N values from a given list of Items
%% in sorted order. Each combination is sorted and the entire table is sorted.
%% For example:
%% 1> couch_tests_combinatorics:n_combinations(2, [mon, tue, wed, thu, fri]).
%% [
%% [mon, tue],
%% [mon, wed],
%% [mon, thu],
%% [mon, fri],
%% [tue, wed],
%% [tue, thu],
%% [tue, fri],
%% [wed, thu],
%% [wed, fri],
%% [thu, fri]
%% ]
-spec n_combinations(Size :: pos_integer(), Elements :: list()) -> [list()].
n_combinations(0, _) ->
[[]];
n_combinations(_, []) ->
[];
n_combinations(N, [H | T]) ->
[[H | L] || L <- n_combinations(N - 1, T)] ++ n_combinations(N, T).