Permutations / Combinations using ABAP
I had written a code in Kiran Premlal to calculate all possible permutations.
started byThe code in this document has certain improvements like:
- Choose permutation or combination using radio-button
- Separation of data from logic
- Minimum and maximum set size can be specified
Why was data separated from logic?
Let us look at some example sets.
SET 1 | SET 2 | SET 3 | ||
54 | apple | 1 | ||
23 | orange | 2 | ||
101 | banana | 3 |
As we can see, sets can be of integers, strings, mixed data types and data can be unsorted.
However, for calculation of output, all we need is a set of indexes.
For index combination {2,3}, subset of SET 1 would be {23, 101}, whereas subset of SET 2 would be {orange, banana}
The code first calculates a list of index combinations, which can then be used to build data sets.
Example Explanation
We look at SET 2 and see how output is being calculated.
INDEX | DATA |
1 | apple |
2 | orange |
3 | banana |
Permutation of all pairs
We have 2 slots to fill, and first element can reserve a slot for starters.
Data sets are {apple, orange} and {apple, banana}.
Index set equivalents would be {1, 2} and {1, 3}.
Program would calculate index sets as:
1 | 2 |
1 | 3 |
2 | 1 |
2 | 3 |
3 | 1 |
3 | 2 |
When these indexes are replaced by their data equivalents, result would be:
apple | orange |
apple | banana |
orange | apple |
orange | banana |
banana | apple |
banana | orange |
Combinations of all singles and pairs
Keeping above SET 2 as input data, we see how output is calculated.
For calculating singles and pairs, we have minimum set size = 1 and maximum set size = 2.
We first find all sets of size 1, and of size 2.
Output in index as well data form would be:
1 | apple | |||
2 | orange | |||
3 | banana | |||
1 | 2 | apple | orange | |
1 | 3 | apple | banana | |
2 | 3 | orange | banana |
For same input data, 6 permutation of pairs was calculated, whereas only 3 combination of pairs.
Screenshots from program
The dataset in program is build using characters starting from ‘B’.
For dataset of size 3, program would build internal table of characters B, C and D.
INDEX | DATA |
1 | B |
2 | C |
3 | D |
We specify in program selection the size of dataset, max/min size of set, and option to find permutation or combination.
Program would store resulting sets in internal table GT_SETS, whose record is capable of storing table of integers.
Although this program prints the resulting sets, minor changes can be done to return the results to another routine.
Code Snippet
- TYPES: tty TYPE TABLE OF i.
- * store superset
- DATA gt_superset_index TYPE TABLE OF i.
- DATA gt_superset_data TYPE TABLE OF c.
- * temporarily store set
- DATA gt_set TYPE TABLE OF i.
- * gt_sets to store list of sets
- DATA gt_sets LIKE TABLE OF gt_set.
- DATA gv_setsize TYPE i.
- PARAMETERS: p_total TYPE i DEFAULT 5, “total number of elements in superset
- p_perm RADIOBUTTON GROUP r1, “permutation
- p_comb RADIOBUTTON GROUP r1, “combination
- p_max TYPE i DEFAULT 3, “maximum size of set
- p_min TYPE i DEFAULT 1. “minimum size of set
- CHECK p_total GT 0 AND
- p_max GT 0 AND
- p_min GT 0 AND
- p_total GE p_max AND
- p_max GE p_min.
- * populate superset index and data
- DO p_total TIMES.
- APPEND sy–index TO gt_superset_index.
- APPEND sy–abcde+sy–index(1) TO gt_superset_data.
- ENDDO.
- * populate gt_sets table with various combinations of indexes
- gv_setsize = p_min.
- WHILE gv_setsize LE p_max.
- PERFORM build_sets USING gt_superset_index
- gv_setsize.
- gv_setsize = gv_setsize + 1.
- ENDWHILE.
- * display sets by using data from gt_superset_data and index from gt_sets
- PERFORM display.
- *&———————————————————————*
- *& Form BUILD_SETS
- *&———————————————————————*
- FORM build_sets USING pt TYPE tty
- p_setsize TYPE i.
- DATA lv TYPE i.
- DATA lv_lines TYPE i.
- DATA lt TYPE tty.
- DATA lv_tabix TYPE i.
- LOOP AT pt INTO lv.
- lv_tabix = sy–tabix.
- * PUSH element to stack and pass remaining to recursive call
- APPEND lv TO gt_set.
- * save set if set size is achieved
- DESCRIBE TABLE gt_set LINES lv_lines.
- IF lv_lines EQ p_setsize.
- APPEND gt_set TO gt_sets.
- DELETE gt_set INDEX lv_lines.
- CONTINUE.
- ENDIF.
- * recursive call for subset
- lt = pt.
- CASE ‘X’.
- WHEN p_perm.
- “permutation – calculate for all elements excluding current
- DELETE lt INDEX lv_tabix.
- WHEN p_comb.
- “combination – calculate for all elements following current
- DELETE lt TO lv_tabix.
- ENDCASE.
- IF lt IS NOT INITIAL.
- PERFORM build_sets USING lt
- p_setsize.
- ENDIF.
- * POP the element from stack once all combinations are tried
- DESCRIBE TABLE gt_set LINES lv_lines.
- DELETE gt_set INDEX lv_lines.
- ENDLOOP.
- ENDFORM. ” BUILD_SETS
- *&———————————————————————*
- *& Form DISPLAY
- *&———————————————————————*
- FORM display .
- FIELD-SYMBOLS: <fs_set> TYPE ANY TABLE,
- <fs_index> TYPE i,
- <fs_data> TYPE c.
- LOOP AT gt_sets ASSIGNING <fs_set>.
- NEW-LINE.
- LOOP AT <fs_set> ASSIGNING <fs_index>.
- READ TABLE gt_superset_data INDEX <fs_index> ASSIGNING <fs_data>.
- IF sy–subrc EQ 0.
- WRITE <fs_data>.
- ENDIF.
- ENDLOOP.
- ENDLOOP.
- ENDFORM. ” DISPLAY
Good... Thanks for sharing...
nice article Manish.. In the initial code I modified a bit to include list of products and get the outputs in a N*1 table,,, simple and smooth logic, thanks for your time on this.. 🙂
ps : This is part of a big requirement where I need to query a table with these sets. I am really worried about the perfomance hits if the number of input is more than 5 !!
Hi Manish,
Great code.
Is there a way we can specify our own values for the data sets, and see the combination of the values, instead of the B,C,D...?