# Enigmatic Code

Programming Enigma Puzzles

## Enigma 1542: Recycling points

From New Scientist #2705, 25th April 2009 [link]

The recycling plant accepts glass, metal and plastic items. For every four items of the same type that I feed it I receive 1 green point, so I will receive 10 points whether I feed it 40, 41, 42 or 43 plastic items.

I fed it a 2-digit number of glass items, a larger 2-digit number of metal items and an even larger 2-digit number of plastic items. I received a 1-digit number of points for each type of item. The digits 1 to 9 each appeared only once among those 2-digit and 1-digit numbers.

If I told you the total number of items that I fed it you would be able to deduce with certainty how many of them were glass, how many were metal and how many were plastic.

How many were metal?

[enigma1542]

### 2 responses to “Enigma 1542: Recycling points”

1. Jim Randell 9 April 2012 at 9:45 pm

Here’s my original Perl code. It runs in 29ms.

```my (\$G, \$M, \$P);
my (\$g, \$m, \$p);
my (\$x, \$t);

my %d = ();
for \$G (10..37) {
\$g = int(\$G / 4);
for \$M (\$G+1..38) {
\$m = int(\$M / 4);
for \$P (\$M+1..39) {
\$p = int(\$P / 4);

\$x = join '', sort map { split '' } \$G, \$g, \$M, \$m, \$P, \$p;
next unless \$x eq '123456789';

\$t = \$G + \$M + \$P;

push @{\$d{\$t}}, "G=\$G/\$g, M=\$M/\$m, P=\$P/\$p";
}
}
}

while ((\$t, \$x) = each %d) {
next if @{\$x} > 1;
print "\$t [\$x->[0]]\n";
}
```

Solution: There were 27 metal items.

• Jim Randell 9 April 2012 at 9:49 pm

Here’s a Python version. It builds up the pandigital requirement as it goes along and rejects candidates that won’t work. It runs in 41ms.

```from itertools import count
from collections import defaultdict
from enigma import concat, printf

d = defaultdict(list)
# we can start at 12 as 10 contains 0 and 11 has repeated digits
for G in count(12):
g = G // 4
if g > 9: break
s1 = set(concat(G, g))
if len(s1) != 3 or '0' in s1: continue
for M in count(10 * (1 + (G // 10)) + 1):
m = M // 4
if m > 9: break
s2 = s1.union(concat(M, m))
if len(s2) != 6 or '0' in s2: continue
for P in count(10 * (1 + (M // 10)) + 1):
p = P // 4
if p > 9: break
s3 = s2.union(concat(P, p))
if len(s3) != 9 or '0' in s3: continue

d[G + M + P].append((G, g, M, m, P, p))

for (T, v) in d.items():
if len(v) > 1: continue
(G, g, M, m, P, p) = v[0]
printf("T={T} G={G}/{g} M={M}/{m} P={P}/{p}")
```