1

I would like to write a program that can provide series of groups of 3 persons, so that no person is in the group with the same person twice. So we cannot have 123 and then 124 in two different series!

For example: 9 people. It can be formed four times (absolute max):
Series 1:
Group 1: 1 2 3
Group 2: 4 5 6
Group 3: 7 8 9

Series 2:
Group 1: 1 5 9
Group 2: 2 6 7
Group 3: 3 4 8

Series 3:
Group 1 3 5 7
Group 2: 1 6 8
Group 3: 2 4 9

Series 4:
Group 1: 3 6 9
Group 2: 2 5 8
Group 3: 1 4 7

But just with 12 people I find it hard to do it by hand. It is possible to form 4-5 series of 12 people (absolute max).

I've just no idea how to write this program. I cannot find a systematic way to do it besides just "trying" with pen and paper. I would like to do it with 30 people. With 30 people may form 13-14 series. (absolute max)

ekad
  • 14,436
  • 26
  • 44
  • 46
Emil
  • 19
  • 3
  • possible duplicate of [Creating combinations that have no more one intersecting element](http://stackoverflow.com/questions/2955318/creating-combinations-that-have-no-more-one-intersecting-element) – BlueRaja - Danny Pflughoeft Aug 26 '12 at 21:03
  • This problem is NP-Hard *(meaning you're not going to find an exact solution in any reasonable time for any decently-large number of people)*, but the above link gives [a complicated but near-optimal approximation algorithm](http://stackoverflow.com/a/2955527/238419). – BlueRaja - Danny Pflughoeft Aug 26 '12 at 21:04
  • Do you think it is possible to generate with 30 people? – Emil Aug 26 '12 at 22:15
  • Is it even possible to do it by hand? – Emil Aug 26 '12 at 22:24

1 Answers1

1

Ok, here is a backtracking solution using c++:

#include <stdio.h>

using namespace std;

int v[100], n;
int ma[100][100];

void init(int k)
{
    v[k] = 0;
}

bool solutionReached( int k ) 
{
    if (k == n + 1)
        return true;
    return false;
}

void printSolution( int k ) 
{
    for (int i = 1; i < k; i++)
    {
        printf("%i ", v[i]);
        if (i % 3 == 0)
        {
            printf("\n");
        }
    }

    for (i = 1; i < n; i++)
    {
        if (i % 3 == 1)
        {
            for (int j = i + 1; j < i + 3; j++)
            {
                ma[v[i]][v[j]] = 1;
                ma[v[j]][v[i]] = 1;
            }
        }

        for (int j = i + 1; j % 3 == 0; j++)
        {
            ma[v[i]][v[j]] = 1;
            ma[v[j]][v[i]] = 1;
        }
    }

    for (i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            //printf("%d ", ma[i][j]);
        }
        //printf("\n");
    }

    printf("\n");
}

bool hasSuccesor( int k ) 
{
    if(v[k] < n)
    {
        v[k]++;
        return true;
    }
    return false;
}

bool isValid( int k ) 
{
    for (int i = 1; i < k; i++)
    {
        if (v[i] == v[k])
        {
            return false;
        }

        /*if (ma[v[i]][v[k]] == 1)
        {
            return false;
        }*/
    }

    for (i = 1; i < k; i++)
    {
        if (i % 3 == 1)
        {
            for (int j = i + 1; j < i + 3; j++)
            {
                if (ma[v[i]][v[j]] == 1)
                {
                    return false;
                }
            }
        }

        for (int j = i + 1; j % 3 == 0; j++)
        {
            if (ma[v[i]][v[j]] == 1)
            {
                return false;
            }
        }
    }

    return true;
}

void bkt(int k)
{
    if(solutionReached(k))
        printSolution(k);
    else
    {
        init(k);
        while(hasSuccesor(k))
            if(isValid(k))
                bkt(k + 1);
    }
}

int main(int argc, char* argv[])
{
    n = 9;
    bkt(1);

    return 0;
}

If you want to experiment, change n = 9 to any number that divides by 3, like 12, 15, 21, but it will take a lot of time for even small numbers (>15) (it depends on computer).

Edit: I redo it so that "no person is in the group with the same person twice", but I only could find 3 groups instead of 4, for 9 people.

Ex: - for 9 program gives:

1 2 3 
4 5 6 
7 8 9 

1 4 7 
2 5 8 
3 6 9 

1 5 9 
2 6 7 
4 3 8 

For 12 program gives:

1 2 3 
4 5 6 
7 8 9 
10 11 12 

1 4 7 
2 5 10 
3 8 11 
6 9 12 

1 5 8 
2 4 12 
3 9 10 
7 6 11 

For 15:

1 2 3 
4 5 6 
7 8 9 
10 11 12 
13 14 15 

1 4 7 
2 5 8 
3 10 13 
6 11 14 
9 12 15 

1 5 9 
2 4 10 
3 6 15 
7 11 13 
8 12 14 

1 6 8 
2 7 14 
4 12 13 
5 10 15 
11 3 9 

For 18: (after a minut and a half - so there are more -)

1 2 3 
4 5 6 
7 8 9 
10 11 12 
13 14 15 

1 4 7 
2 5 8 
3 10 13 
6 11 14 
9 12 15 

1 5 9 
2 4 10 
3 6 15 
7 11 13 
8 12 14 

1 6 8 
2 7 14 
4 12 13 
5 10 15 
11 3 9 

1 2 3 
4 5 6 
7 8 9 
10 11 12 
13 14 15 
16 17 18 

1 4 7 
2 5 8 
3 6 9 
10 13 16 
11 14 17 
12 15 18 

1 5 9 
2 4 10 
3 7 11 
6 13 18 
8 15 17 
14 12 16 

1 6 8 
2 7 12 
3 4 13 
5 10 17 
9 14 18 
11 15 16 

1 10 14 
2 6 15 
3 5 12 
4 9 16 
7 13 17 
8 11 18 

If you want to save them to a file, include fstream and modify printSolution to:

        void printSolution( int k ) 
    {
        ofstream cout;
        cout.open("date.txt", ios::app);

        for (int i = 1; i < k; i++)
        {
            cout << v[i] << " ";
            if (i % 3 == 0)
            {
                cout << "\n";
            }
        }

        for (i = 1; i < n; i++)
        {
            if (i % 3 == 1)
            {
                for (int j = i + 1; j < i + 3; j++)
                {
                    ma[v[i]][v[j]] = 1;
                    ma[v[j]][v[i]] = 1;
                }
            }

            for (int j = i + 1; j % 3 == 0; j++)
            {
                ma[v[i]][v[j]] = 1;
                ma[v[j]][v[i]] = 1;
            }
        }
     }
Thanatos
  • 1,176
  • 8
  • 18
  • Looks nice! But
    1 2 3
    4 5 6
    7 8 9

    and

    1 2 3
    4 5 6
    7 9 8

    is the same thing!
    – Emil Aug 26 '12 at 20:19
  • But I think you have misunderstood the question. You cannot have 1 2 3 4 5 6 7 8 9 and then 1 2 3 4 5 7 6 8 9 ! No person may come in a group with the same person again! – Emil Aug 26 '12 at 20:22
  • Have you any idea how to program it? – Emil Aug 27 '12 at 09:25
  • Cool! Ive just startet the program with n=30. Do you think it will finish during the night? – Emil Aug 27 '12 at 20:27
  • Depends on your computer: on n = 15 it gave me the answer in 3 sec: that is 1 307 674 368 000 / 3 = 435 891 456 000 solutions checked in a sec. For n = 30 it should finish in 6 * 10^20 seconds = 10 ^ 17 hours = 10 ^ 15 days = 10 ^ 13 years.. so 10 000 000 000 years, so you can't find all the solutions, but what you can do is to get some solutions by saving them in a file instead of looking at them – Thanatos Aug 28 '12 at 07:43
  • Don't you think it possibly to find a systematic way to solve the problem with 30 people? There must be a way – Emil Sep 02 '12 at 21:27