1

Let's say I have a list of questions that stores an object that has a list of it's possible answers, and I need to generate all permutation pairs with no duplicates where one element of the pair is in the first list and the second one in the second list. In other words, let's say I have 2 questions, and each one has 2 answers, how many answer sets could I create with this? One last thing, the order is important. An answer from the first question could not be in the position from the 2nd question, if that makes sense.

I hope this is clear.

Thanks!

Edited for clarity

We have an Object called "Question__c". We have another object, "Answer__c". Answer__c has a lookup to Question__c.

In the Question__c object, we have a joiner object that can related a question to another question, so that the "child" question contributes to the answer on the "parent".

We also have one more object that we'll call ContributingQuestionCombos__c. Each record stores one possible combination.

Now, taking the Answers from the contributing questions, and the answers from the parent question, I am trying to make a CSV template that has all of the possible answer combinations for the options provided. There can be up to 4 "contributing" questions. Should the number of possible combinations be above 200, then I do not include the combinations in the CSV template. The columns in the CSV template are ControllingQuestionId__c, Answer1__c, Answer2__c, Answer3__c, Answer4__c.

Let's say we have 4 contributing questions, the answers from Question 1 can only ever be in the Answer1__c column, Question 2 can only be in Answer2__c, etc and so forth.

Given that logic, what I'm trying to do is prepopulate this CSV Template with the combinations for the user and provided there aren't too many.

So in all there would be 9 combinations total for 2 questions with 2 answers each as we are including blank answers as a potential combination.

Here's an example

Example Chart

I hope that clarifies things a bit!

Thanks for taking the time to help, I really appreciate it :)

5
  • 2
    Seems like this would be better posted to a mathematics stackexchange. This is much more of a combinatorics question and doesn't seem to have anything to do with Salesforce Feb 25, 2013 at 18:00
  • I'm sorry, Im actually trying to accomplish this purely with APEX in salesforce. Questions and Answers are custom objects and AnswerCombinations is another custom object that stores the various combos.. Feb 25, 2013 at 18:26
  • 1
    @jsfdev01 - computing permutations is not APEX specific and it sounds like you just need the algorithm. Can you elaborate on the Salesforce part of this, other than you're counting sObjects?
    – Mike Chale
    Feb 25, 2013 at 20:24
  • I suppose the issue I'm having is taking the algorithms and applying them in APEX, especially since my understanding of this topic is certainly lacking. Feb 25, 2013 at 21:02
  • 1
    This isn't really the correct place to put this. You'll probably have better luck on SO. However, I read through this twice and it's still unclear what you are trying to do. Why do you have 4 columns when there could be many permutations? What do you mean about counting distinct? How could a different permutation every be a duplicate? Feb 25, 2013 at 22:54

2 Answers 2

3

While I cannot answer your question specifically, this code may assist you in understanding what you're looking for in the end.

This is a block of code which I've genericised and simplified as best I can, it has been pretty helpful when I needed to generate massive amounts of test data with a basic method call. Usually the method call took some limiting parameter, like the number of permutations I required.

It can be run from Execute Anonymous like so: PermutationsTest.createPermutations(); It is easiest to see what is happening if you set the LoggingLevel in Exec Anon to Error so that you don't see the steps in and out of the methods.

The code as it is written will generate each of the 6480 permutations of the included data set.


Also, be very cognizant of the fact that code which calculates permutations written in this mathematically inefficient, iterating manner is a very greedy consumer of your precious script statements! That said, it does the job.


public with sharing class PermutationsTest {

    public class Permutation {

        public string field1 { get; set; }
        public string field2 { get; set; }
        public string field3 { get; set; }
        public string field4 { get; set; }
        public string field5 { get; set; }

    }

    public static List<Permutation> createPermutations() {

        List<Permutation> mutantList = new List<Permutation>();

        // all of the values for each permutation field
        List<String> field1Values = 'blank,Mercury,Venus,Earth,Mars,Jupiter'.split(',');
        List<String> field2Values = 'blank,Lamborghini,Ferrari,Porsche,Audi,BMW'.split(',');
        List<String> field3Values = 'blank,Steak,Salad,Antipasto,Tapas,Pizza'.split(',');
        List<String> field4Values = 'blank,Apple,Orange,Grape,Watermelon'.split(',');
        List<String> field5Values = 'blank,Beer,Wine,Vodka,Water,Soda'.split(',');

        // calculate the permutations
        Integer aSize, bSize, cSize, dSize, eSize = 0;
        aSize = field1Values.size();
        bSize = field2Values.size();
        cSize = field3Values.size();
        dSize = field4Values.size();
        eSize = field5Values.size();

        // number of records which need to be created is the number of permutations possible
        Integer totalPermutations = aSize * bSize * cSize * dSize * eSize;
        system.debug(LoggingLevel.ERROR, '\n\n\tTotal Permutations To Create: ' + totalPermutations + '\n');

        // make sure we didn't multiply anything by zero
        system.assertNotEquals(0, totalPermutations);

        // create one instance in the list for every permutation of data
        for (Integer a = 0; a < aSize; a++) {
            for (Integer b = 0; b < bSize; b++) {
                for (Integer c = 0; c < cSize; c++) {
                    for (Integer d = 0; d < dSize; d++) {
                        for (Integer e = 0; e < eSize; e++) {

                            // create the permutation instance
                            Permutation perm = new Permutation();

                            // set the data points
                            perm.field1 = field1Values[a];
                            perm.field2 = field2Values[b];
                            perm.field3 = field3Values[c];
                            perm.field4 = field4Values[d];
                            perm.field5 = field5Values[e];

                            // output to the debug log, at the lowest level so that you can filter to ERROR
                            // and see just these debug statements
                            system.debug(LoggingLevel.ERROR, perm);

                            // add to the list of permutations being returned to the caller
                            mutantList.add(perm);
                        }
                    }
                }
            }
        }


        return mutantList;
    }
}

Hope this adds to your understanding or provides more info to help the question!

Wikipedia - Permutation in combinatorics

2
  • Thank you, I was able to take this and make it do what I needed, it was definitely the push in the right direction ( or massive shove, if you will ) that I needed. I'm also going to read the supplied article. Feb 26, 2013 at 0:01
  • @jsfdev01 could you to add another answer to your own question with the fruits of your labor? I'm curious to see how the solution to the question is reflected in your code.
    – Mark Pond
    Feb 26, 2013 at 0:13
2

As requested by Mark Pond, here is the modified code I came up with that correctly calculated the permutations of the lists provided. For the most part, his code worked perfectly, I just had to add some simple conditionals to determine if the user provided less than 4 questions. It's not perfect, by any stretch, and I have a colleague peer reviewing it, but it works!

public static List<Permutation> createPermutations(list<list<String>> questions) {

    List<Permutation> mutantList = new List<Permutation>();


    // add default values to the permutation field.    
    List<String> field1Values = 'blank'.split(',');
    List<String> field2Values = 'blank'.split(',');
    List<String> field3Values = 'blank'.split(',');
    List<String> field4Values = 'blank'.split(',');

    if(questions.size() > 0)
        field1Values.addAll(questions.get(0));
    if(questions.size() > 1)
        field2Values.addAll(questions.get(1));
    if(questions.size() > 2)
        field3Values.addAll(questions.get(2));
    if(questions.size() > 3)
        field4Values.addAll(questions.get(3)); 

    // calculate the permutations
    Integer aSize, bSize, cSize, dSize = 0;
    aSize = field1Values.size();
    bSize = field2Values.size();
    cSize = field3Values.size();
    dSize = field4Values.size();

    // number of records which need to be created is the number of permutations possible
    Integer totalPermutations = aSize * bSize * cSize * dSize;

    // make sure we didn't multiply anything by zero
    system.assertNotEquals(0, totalPermutations);

    // create one instance in the list for every permutation of data
    for (Integer a = 0; a < aSize; a++) {
        for (Integer b = 0; b < bSize; b++) {
            if(questions.size() > 2){
                for (Integer c = 0; c < cSize; c++) {
                    if(questions.size() > 3){
                        for (Integer d = 0; d < dSize; d++) {
                                // create the permutation instance
                                Permutation perm = new Permutation();
                                // set the data points
                                perm.field1 = field1Values[a];
                                perm.field2 = field2Values[b];
                                perm.field3 = field3Values[c];
                                perm.field4 = field4Values[d];

                                // add to the list of permutations being returned to the caller
                                mutantList.add(perm);
                        }
                    }else{
                        Permutation perm = new Permutation();

                        perm.field1 = field1Values[a];
                        perm.field2 = field2Values[b];
                        perm.field3 = field3Values[c];      

                        mutantList.add(perm);

                    }
                }                    
            }else{
                Permutation perm = new Permutation();

                perm.field1 = field1Values[a];
                perm.field2 = field2Values[b];

                mutantList.add(perm);
            }

        }                
    }


    return mutantList;
}

This then gets parsed into a string and exported to a CSV as a template!

Thanks!

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .