-
Notifications
You must be signed in to change notification settings - Fork 3
/
SpecificPermutation.pq
81 lines (65 loc) · 2.51 KB
/
SpecificPermutation.pq
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/*
Copyright 2019 - 2020
Project : Power-Query @ => d:\Karthik K Selvan\Power Query\Library Functions\Power-Query
File : SpecificPermutation.pq @ => d:\Karthik K Selvan\Power Query\Library Functions\Power-Query\SpecificPermutation.pq
Created : Tuesday, 30th April 2019 5:32:41 pm
Author : KarthikK Selvan
Change History:
*/
(Source as list, SetNumber as number) as table =>
let
// number of combinations
NumberOfCombinations = Number.Combinations(List.Count(Source), SetNumber),
/* create SetNumber - 1 Lists, skipping one progressive items from Source
For a "A B C D E" list for which we want to generate combinations of 3, return 3 lists of:
A B C D E
B C D E
C D E
*/
PartitionList = List.Buffer(List.Accumulate(
{0..SetNumber - 1},
{},
(state, current) => state & {List.Skip(Source, current)}
)),
// item count of the last item of PartitionList
LastListLength = List.Count(List.Last(PartitionList)),
// generate list of 1's of length equal to setNumber
FirstListItems = List.Repeat({1}, SetNumber),
// set number items positions,
SetNumberItemsPosition = List.Buffer({0..SetNumber - 1}),
// for each item in Sequence list, take the correspondend item of Partition list
AssignItems = (Sequence as list) as list =>
List.Accumulate(
SetNumberItemsPosition,
{},
(state, current) => state & {PartitionList{current}{Sequence{current}-1}}
),
GenerateNewNumList = (PrevNumList as list) =>
List.Accumulate(
SetNumberItemsPosition,
{},
(state, current) =>
let
Res = if
current = SetNumber - 1
then
if PrevNumList{current} = LastListLength then state{current - 1} else PrevNumList{current} + 1
else
if
PrevNumList{current + 1} = LastListLength and PrevNumList{current} < LastListLength
then
PrevNumList{current} + 1
else
if PrevNumList{current} = LastListLength then state{current - 1} else PrevNumList{current}
in
state & {Res}
),
Result = List.Generate(
()=>[NumList = FirstListItems, Combin = AssignItems(NumList), counter = 1],
each [counter] <= NumberOfCombinations,
each [NumList = GenerateNewNumList([NumList]), Combin = AssignItems(NumList), counter = [counter] + 1],
each [Combin]
),
FinalTable = Table.FromRows(Result)
in
FinalTable