# Enigmatic Code

Programming Enigma Puzzles

## Enigma 273: Moral choices

From New Scientist #1420, 6th September 1984 [link]

The campaign to Brace Up Moral Standards is run by a six-person committee, who elect a president from among themselves. Each person casts three votes. On the last occasion each voted for three persons and each person totalled a different number of votes.

Lord Luvaduck Love finished higher than Miss Marriage, who voted for herself. Tansy Tickell, the romantic novelist, fared better than the Reverend Cuthbert Custard, who did not vote for himself. Peregrine Prunes voted for Miss Marriage. Sylvia Slap, the agony aunt, voted for herself. Love did not vote for Tickell. No one votes for Love and Marriage; no one for Slap and Tickell; and no one for Prunes and Custard.

[enigma273]

### 3 responses to “Enigma 273: Moral choices”

1. Jim Randell 15 April 2015 at 8:49 am

This Python program examines all possible combinations of votes. It runs in 1.3s.

```from itertools import product
from collections import Counter
from enigma import irange, concat, printf

# no-one votes for (L and M) or (S and T) or (P and C),
# so every one votes for (L or M) and (S or T) and (P and C)

(L, M, S, T, P, C) = names = 'LMSTPC'

# accumulate results
r = Counter()

for votes in product(product(L + M, S + T, P + C), repeat=6):

# M voted for herself
if M not in votes[M]: continue

# C did not vote for himself

# P voted for M
if M not in votes[P]: continue

# S voted for herself
if S not in votes[S]: continue

# L did not vote for T

# determine the totals
totals = dict((x, sum(1 for v in votes.values() if x in v)) for x in names)

# L got more votes than M
if not(totals[L] > totals[M]): continue

# T got more votes than C
if not(totals[T] > totals[C]): continue

# totals are distinct
if not(len(set(totals.values())) == 6): continue

# record the results
r[tuple(totals[x] for x in names)] += 1

printf("[votes: {votes}, totals: {totals}]", votes=' '.join(x + '=' + votes[x] for x in names), totals=' '.join(x + '=' + str(totals[x]) for x in names))

# output the results
for (k, v) in r.most_common():
printf("{k} [{v} solutions]", k=' '.join(x + '=' + str(y) for (x, y) in zip(names, k)))
```

There are 4 possible voting patterns: L voted for L+S+P; M voted for M+P; S voted for L+S+P; T voted for L+P; P voted for M+P; C voted for L+P. Then from the remaining votes cast by M, T, P and C, one of them voted for T and the rest of them voted for S.

• Jim Randell 15 April 2015 at 9:04 am

Here’s the problem expressed as a set of constraints in a MiniZinc model. It runs finds the four solutions in 77ms using [[ `mzn-gecode -a enigma273.mzn` ]].

```include "globals.mzn";

% identify the candidates
set of int: Candidates = 1..6;

int: L = 1;
int: M = 2;
int: S = 3;
int: T = 4;
int: P = 5;
int: C = 6;

array[Candidates] of string: name = [ "L", "M", "S", "T", "P", "C" ];

array[Candidates, Candidates] of var bool: votes;

% each person casts three votes
constraint forall (i in Candidates) (sum (j in Candidates) (votes[i, j]) == 3);

% totals
array[Candidates] of var 0..6: total;
constraint forall (i in Candidates) (total[i] == sum (j in Candidates) (votes[j, i]));

% the totals are all different
constraint alldifferent(total);

% L got more votes than M
constraint total[L] > total[M];

% M voted for herself

% T got more votes than C
constraint total[T] > total[C];

% C did not vote for himself

% P voted for M

% S voted for herself

% L did not vote for T

% no-one votes for L and M

% no-one votes for S and T

% no-one votes for P and C

% solve the problem
solve satisfy;

% output the solution
output [
"L: " ++ show([votes[L, i] | i in Candidates]) ++ "\n" ++
"M: " ++ show([votes[M, i] | i in Candidates]) ++ "\n" ++
"S: " ++ show([votes[S, i] | i in Candidates]) ++ "\n" ++
"T: " ++ show([votes[T, i] | i in Candidates]) ++ "\n" ++
"P: " ++ show([votes[P, i] | i in Candidates]) ++ "\n" ++
"C: " ++ show([votes[C, i] | i in Candidates]) ++ "\n" ++
"total: " ++ show(total)
];
```
2. arthurvause 18 April 2015 at 10:37 pm

From the puzzle constraints, it is easy to deduce that
totals for the candidates have to be 0,1,2,4,5,6
6>L>M>1
5>T>C
S>0,
L+M = S+T = P+C = 6

So, some code:

```from itertools import product, permutations

for p in permutations( ( (0,6),(1,5),(2,4) ) ):
for L,S,P in product(*p):
M,T,C = 6-L,6-S,6-P
if 6>L>M>1 and 5>T>C and S>0 :
print L, M, S, T, P, C
```

This site uses Akismet to reduce spam. Learn how your comment data is processed.