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]

Advertisements

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}")
      

Leave a Comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: