Enigmatic Code

Programming Enigma Puzzles

Enigma 1778: Around the houses

From New Scientist #2946, 7th December 2013 [link]

Fewer than 100 houses have been built on the edge of a circular green, equally-spaced around the whole perimeter and numbered 1, 2, … in order. I have counted the number of pairs of houses with their first and second digits exchanged that are either 90 degrees or 180 degrees apart around the circle. The numerical difference between the counts for 90 degrees and for 180 degrees apart is the same as the higher digit of the lowest-numbered house involved.

How many houses are there in all?



3 responses to “Enigma 1778: Around the houses

  1. Jim Randell 4 December 2013 at 8:14 pm

    There are multiple solutions if we allow leading zeros, so this Python code assumes they are not allowed (although you can set a flag in this code to allow them if you like). It runs in 37ms.

    from enigma import irange, printf
    # if we disallow leading zeros the lowest possible number is 12
    leading_zero = False
    start = (1 if leading_zero else 12)
    # check for houses a given angle apart with first and second digits exchanged
    def check(n, f):
      # angles we need
      (a, r) = divmod(n, f)
      if r > 0: return []
      angles = set((a, n - a))
      # find the pairs that satisfy the condition
      pairs = []
      for xy in irange(start, n):
        # separate the digits
        (x, y) = divmod(xy, 10)
        yx = 10 * y + x
        # is yx a valid number?
        if start <= xy < yx <= n:
          # is it the angle we want?
          if yx - xy in angles:
            pairs.append((xy, yx))
      return pairs
    # consider n houses
    for n in irange(start, 99):
      # look for pairs 180 degrees (1/2 circle) apart
      p180 = check(n, 2)
      # look for pairs 90 degrees (1/4 circle) apart
      p90 = check(n, 4)
      # the difference between the counts...
      d1 = abs(len(p180) - len(p90))
      # is the same as the higher digit of the lowest numbered house
      if not(p180) and not(p90): continue
      d2 = max(divmod(min(x[0] for x in p180[:1] + p90[:1]), 10))
      if d1 == d2:
        printf("n={n} [p180={p180} p90={p90} d1={d1} d2={d2}]")

    Solution: There are 72 houses in all.

  2. arthurvause 5 December 2013 at 10:37 am

    My variation:

    # N houses in a 90 degree segment, so 4N houses in total
    for N in xrange(3,25):
      pairs_180 = [(a, a+2*N) for a in xrange(10,2*N+1)
                      if set(str(a))==set(str(a+2*N))]
      pairs_90 = [(a, (a+N)%(4*N) ) for a in xrange(10,4*N+1)
                      if set(str(a))==set(str((a+N)%(4*N)))]
      diff = abs(len(pairs_180)-len(pairs_90))
      if diff > 0:
        houses = [x for (x,y) in pairs_180+pairs_90]
        houses += [y for (x,y) in pairs_180+pairs_90]
        if min(houses)%10 == diff:
          print 4*N, pairs_180, pairs_90

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: