Sorry that this is a mess, but it takes a lot of time to make code pretty. Anyway, SatisfiabilityCount
/SatisfiabilityInstances
are the core of it all. This approach could be generalised to more complicated questions than round tables etc., but of course would need a different visualisation with those questions.
With[{couples = 4, (* Just for clarity: *) genders = 2},
With[{seats = couples genders},
And @@ Flatten@Join[
(* Fix position of one person. *)
{s[1, 1, 1]},
(* Exactly one person per seat. *)
Table[
BooleanCountingFunction[{1}, couples genders] @@
Flatten@Table[s[i, j, k], {j, couples}, {k, genders}], {i,
seats}],
(* Exactly one instance of each person. *)
Table[
BooleanCountingFunction[{1}, seats] @@
Table[s[i, j, k], {i, seats}], {j, couples}, {k, genders}],
(* At most one person from a couple per adjacent seats. *)
Table[
BooleanCountingFunction[1, 2 genders] @@
Flatten@Table[s[i, j, k], {i, {##}}, {k, genders}], {j, couples}] & @@@
EdgeList@CycleGraph[seats]]
// SatisfiabilityCount]]
1488
With[{couples = 4, (* Just for clarity: *) genders = 2},
With[{seats = couples genders},
With[{sols = And @@ Flatten@Join[
(* Fix position of one person. *)
{s[1, 1, 1]},
(* Exactly one person per seat. *)
Table[
BooleanCountingFunction[{1}, couples genders] @@
Flatten@Table[s[i, j, k],
{j, couples}, {k, genders}], {i, seats}],
(* Exactly one instance of each person. *)
Table[
BooleanCountingFunction[{1}, seats] @@ Table[s[i, j, k],
{i, seats}], {j, couples}, {k, genders}],
(* At most one person from a couple per adjacent seats. *)
Table[
BooleanCountingFunction[1, 2 genders] @@
Flatten@Table[s[i, j, k],
{i, {##}}, {k, genders}], {j, couples}] & @@@
EdgeList@CycleGraph[seats]] //
(* Pick variables (s[seat, couple, gender]) which are true. *)
With[{vars =
Flatten@Table[
s[i, j, k], {i, seats}, {j, couples}, {k, genders}]},
Pick[vars, #] & /@ SatisfiabilityInstances[#, vars, All] &]},
(* Draw a sample of graphs of seatings with couples. *)
With[{samples = UpTo[20], perrow = UpTo[4]},
(Graphics[
{Circle[],
Table[
With[{pp = {Sin[#], Cos[#]} & /@ (# 2 \[Pi]/seats)},
{Black, Line@pp,
LightRed, Disk[First@pp, 1/5],
LightBlue, Disk[Last@pp, 1/5],
Black, Text[i, #] & /@ pp}] &@
SortBy[Last][Cases[#, s[s_, i, g_] :> {s, g}]][[All, 1]], {i, couples}]}] & /@
RandomSample[sols, samples]) //
GraphicsGrid@Partition[#, perrow] &]]]]

By adding the following constraint to the problem we can find out that there are only 12 solutions where genders alternate around the table (odd seats must have a female, even seats a male):
(* Genders must alternate. *)
Table[Or @@ Table[s[i, j, Mod[i, 2, 1]], {j, couples}], {i, seats}],

DeleteCases
, you can instead insert a|
between patterns, like an "or" (the underlying name for this isAlternative
), e.g.({h[a_], __, w[b_]} | {w[a_], __, h[b_]}) /; a == b
. $\endgroup$/; a == b
in this case simply by using the same named pattern:{h[a_], __, w[a_]} | {w[a_], __, h[a_]}
$\endgroup$p = Join[{-1}, #] & /@ Permutations[{1, -2, 2, -3, 3, -4, 4}]; s = Select[p, Min[Abs[Abs[#] - Abs[RotateLeft[#]]]] != 0 &] // Length
. $\endgroup$