Reputation: 403
I have a list of names, for example: "Alice", "Bob", "Steve", "Kate", "Jane", "John", "Vic", "Dan", "Robert" They call each other in a circle chain: "Alice" -> "Bob" -> "Steve" -> "Kate" -> "Jane" -> "John" -> "Vic" -> "Dan" -> "Robert" -> "Alice" I need an algorithm which will print several chains where in the result every person should have a call with all other persons without repeats. So if Vic called Dan and John called Vic yestarday all of them should have another persons in today call.
Upvotes: 0
Views: 52
Reputation: 11322
Your task can be achieved by the following MiniZinc model:
include "circuit.mzn";
int: n = 9; % number of participants
int: rounds = 4;
set of int: N = 1..n;
set of int: Rounds = 1..rounds;
% decision variables
array[N, Rounds] of var N: x;
predicate is_chain(array[N] of var N: c) =
circuit(c);
predicate is_talking_to(N: p1, N: p2, Rounds: r) =
(x[p1, r] == p2) \/
(x[p2, r] == p1);
constraint forall(r in Rounds) (circuit([x[p, r] | p in N]));
constraint forall(r1 in Rounds, r2 in r1+1..rounds, p1 in N, p2 in p1+1..n)
(is_talking_to(p1, p2, r1) -> not is_talking_to(p1, p2, r2));
function string: show_chain(array[N] of var N: c) =
join(" -> ", [ "\(c[p])" | p in N ]) ++ " -> \(c[1])\n";
output [ show_chain([fix(x[p, r]) | p in N]) | r in Rounds ];
Example output:
7 -> 5 -> 2 -> 9 -> 8 -> 4 -> 3 -> 6 -> 1 -> 7
4 -> 8 -> 9 -> 7 -> 1 -> 5 -> 2 -> 3 -> 6 -> 4
6 -> 9 -> 1 -> 3 -> 7 -> 2 -> 8 -> 4 -> 5 -> 6
2 -> 4 -> 6 -> 5 -> 3 -> 7 -> 9 -> 1 -> 8 -> 2
For more than four rounds, no solution was found.
The model interpretes to "have a call" as symmetric "speaking to eachother". It does not matter, who is initiating a call.
Upvotes: 1