Updates from Jim Randell Toggle Comment Threads | Keyboard Shortcuts

  • Unknown's avatar

    Jim Randell 5:07 pm on 24 April 2020 Permalink | Reply
    Tags:   

    Teaser 3005: Tubular bales 

    From The Sunday Times, 26th April 2020 [link] [link]

    Ten equal-length, rigid tubes, each a different prime-valued external radius from 11 mm to 43 mm, were baled, broadside, by placing the 43 mm and 11 mm tube together and the third tube, not the largest remaining, touching both of these. Each subsequent tube touched the previous tube placed and the 43 mm tube. A sub-millimetre gap between the final tube placed and the 11 mm tube, made a near perfect fit.

    The radius sum of the first three tubes placed against the 43 mm tube was a multiple of one of the summed radii. Curiously, that statement remains true when each of “four”, “five”, “seven” and “eight” replaces “three”. For “two” and “six” tubes placed their radius sum was a multiple of an as yet unplaced tube’s radius.

    What radius tube, in mm, was placed last?

    [teaser3005]

     
    • Jim Randell's avatar

      Jim Randell 5:30 pm on 24 April 2020 Permalink | Reply

      This Python program runs in 78ms.

      Run: [ @replit ]

      from enigma import (primes, printf)
      
      # numbers available to to use
      rs = list(primes.between(11, 44))
      assert len(rs) == 10
      
      # check n is a multiple of some element of ms
      check = lambda n, ms: any(n % m == 0 for m in ms)
      
      # solve for the specified numbers
      # ns = unused numbers
      # ss = used numbers
      def solve(ns, ss):
        # are we done?
        if not ns:
          yield ss
        else:
          # what number placement is this?
          k = len(ss) + 1
          t = sum(ss)
          # choose the next number to use
          for (i, n) in enumerate(ns):
            # 2nd: not the largest available
            if k == 2 and n == ns[-1]: continue
            t_ = t + n
            # 3rd, 4th, 5th, 7th, 8th: multiple of a used number
            ss_ = ss + [n]
            if k in (3, 4, 5, 7, 8) and not check(t_, ss_): continue
            # 2nd, 6th: multiple of an unused number
            ns_ = ns[:i] + ns[i + 1:]
            if k in (2, 6) and not check(t_, ns_): continue
            # solve for the remaining numbers
            yield from solve(ns_, ss_)
      
      # collect possible final numbers
      fs = set()
      for ss in solve(rs[1:-1], rs[:1]):
        fs.add(ss[-1])
        printf("{ss}")
      
      # output solution
      printf("final number = {fs}")
      

      Solution: The 37 mm tube was placed last.

      The conditions placed on the ordering of the numbers means that although there are four possible orders that the tubes could be assembled in, the answer to the puzzle (the radius of the final tube) is the same in all cases.

      So it is not necessary to check that the placement results in a gap of less than 1 mm, but if you do, you find all 4 orderings result in a gap less than 1 mm (and one of them is an almost perfect fit).

      Here is a diagram of the packing (11, 23, 17, 41, 29, 31, 19, 13, 37) around the 43 tube. This has the largest gap of 0.66 mm.

      Here is a list of 4 packings, and the corresponding gaps:

      (11, 23, 17, 41, 29, 31, 13, 19, 37) → gap = 0.36 mm
      (11, 23, 17, 41, 29, 31, 19, 13, 37) → gap = 0.66 mm
      (11, 23, 17, 41, 31, 29, 13, 19, 37) → gap = 0.000055 mm
      (11, 23, 17, 41, 31, 29, 19, 13, 37) → gap = 0.41 mm

      The third one has a gap of just 55 nm, which is about half the diameter of a single coronavirus particle, and probably quite a lot smaller than the tolerance of the tubes.

      Perhaps the puzzle was intended to be set with the radii of the tubes measured in centimetres, then there would be only one arrangement that had a sub-millimetre gap.

      Like

  • Unknown's avatar

    Jim Randell 9:24 am on 23 April 2020 Permalink | Reply
    Tags:   

    Teaser 2591: Shilly Chalet 

    From The Sunday Times, 20th May 2012 [link] [link]

    George and Martha are running a holiday camp and their four daughters are staying there. To keep the peace they have been given chalets in different areas. Amelia’s chalet number is between 1 and 99, Bertha’s is between 100 and 199, Caroline’s between 200 and 299, and Dorothy’s between 300 and 399.

    George commented that the difference between any two of the four chalet numbers is either a square or a cube. Martha added that the same could be said for the sum of the chalet numbers of the three youngest daughters.

    Who is the eldest daughter and what is her chalet number?

    [teaser2591]

     
    • Jim Randell's avatar

      Jim Randell 9:25 am on 23 April 2020 Permalink | Reply

      Programatically it is straightforward to check all the possibilities.

      This Python program runs in 141ms.

      Run: [ @repl.it ]

      from enigma import (is_square, is_cube, irange, cached, printf)
      
      # check for a square or a cube
      check = cached(lambda n: is_square(n) or is_cube(n))
      
      # choose a value for A
      for A in irange(1, 99):
        # choose a value for B
        for B in irange(100, 199):
          if not check(B - A): continue
          # choose a value for C
          for C in irange(200, 299):
            if not (check(C - A) and check(C - B)): continue
            # choose a value for D
            for D in irange(300, 399):
              if not (check(D - A) and check(D - B) and check(D - C)): continue
              # check the total excluding the eldest
              T = A + B + C + D
              for (n, x) in zip("ABCD", (A, B, C, D)):
                if not check(T - x): continue
                # output solution
                printf("A={A} B={B} C={C} D={D}; eldest={n}")
      

      Solution: Amelia is the eldest daughter. Her chalet is number 93.

      The chalet numbers are:

      A=93, B=193, C=218, D=318

      And: B + C + D = 729 = 27^2 = 9^3.

      This sum is both a square and a cube.

      So, if you interpret “either … or …” to be an exclusive or (one or the other, but not both), then the puzzle has no solutions.

      Like

    • GeoffR's avatar

      GeoffR 10:45 am on 24 April 2020 Permalink | Reply

      
      % A Solution in MiniZinc
      include "globals.mzn";
       
      var 1..99:A;       % Amelia
      var 100..199:B;    % Bertha
      var 200..299:C;    % Caroline
      var 300..399:D;    % Dorothy
      
      set of int: sq = {n * n | n in 2..32};  
      set of int: cb = {n * n * n | n in 2..10};
      
      % difference between any chalet numbers is either a square or a cube
      constraint (B-A) in sq \/ (B-A) in cb;
      constraint (C-A) in sq \/ (C-A) in cb;
      constraint (C-B) in sq \/ (C-B) in cb;
      constraint (D-C) in sq \/ (D-C) in cb;
      constraint (D-B) in sq \/ (D-B) in cb;
      constraint (D-A) in sq \/ (D-A) in cb;
      
      % sum of three youngest daughters chalet numbers is a square or a cube
      constraint ((A+B+C) in sq \/ (A+B+C) in cb)
      \/  ((A+B+D) in sq \/ (A+B+D) in cb)
      \/  ((B+C+D) in sq \/ (B+C+D) in cb);
      
      solve satisfy;
      
      % A = 93;
      % B = 193;
      % C = 218;
      % D = 318;
      % % time elapsed: 0.06 s
      % ----------
      % ==========
      % sum of three youngest daughters chalets is a square or a cube
      % A + B + C = 93 + 193 + 218 = 504 - not a square or a cube
      % A + B + D = 93 + 193 + 318 = 604 - not a square or a cube
      % B + C + D = 193 + 218 + 318 = 729 - is both a square and a cube
      
      % Therefore, Ameila is the eldest daughter with chalet number 93
      
      
      

      Like

    • GeoffR's avatar

      GeoffR 11:46 am on 24 April 2020 Permalink | Reply

      sq = [x * x for x in range(2,32)]
      cb = [x * x * x for x in range(2,10)]
      
      # form a set of square and cube numbers
      sc = set(sq) | set(cb)
      
      for a in range(1,100):
        for b in range(100,200):
          if (b-a) in sc:
            for c in range(200,300):
              if (c-a) in sc and (c-b) in sc:
                for d in range(300,400):
                  if (d-c) in sc and (d-b) in sc and (d-a) in sc:
                    if (a+b+d) in sc:
                      print('Eldest daughter Caroline has chalet', c)
                    if (b+c+d) in sc:
                      print('Eldest daughter Ameila has chalet', a)
                    if (a+c+d) in sc:
                        print('Eldest daughter Bertha has chalet', b)
                    if (a+b+c) in sc:
                        print('Eldest daughter Dorothy has chalet', d)
      
      # Eldest daughter Ameila has chalet 93
      
      
      

      Like

  • Unknown's avatar

    Jim Randell 8:21 am on 21 April 2020 Permalink | Reply
    Tags: by: Brian Young   

    Brain-Teaser 518: [Prophecies] 

    From The Sunday Times, 16th May 1971 [link]

    An interesting fragment tells us what took place at the meeting of the Five Prophets:

    “If Hosea hath prophesied truth, Micah and Obadiah will die in the same city; if Micah hath prophesied truth, Joel and Obadiah will die in the same city. It is the saying of Joel that three of the five prophets shall die in Babylon; and Nahum declareth to Hosea that the two of them shall die in different cities.”

    It is well known that those who prophesy correctly die in Jerusalem, whereas those who make false prophecies die in Babylon.

    So how many of these five will die in Jerusalem?

    This puzzle was originally published with no title.

    [teaser518]

     
    • Jim Randell's avatar

      Jim Randell 8:22 am on 21 April 2020 Permalink | Reply

      There are only 2^5 (= 32) possibilities, so we can examine them all.

      This Python program runs in 79ms.

      from enigma import subsets, printf
      
      # check statement made by X
      check = lambda X, s: (X == "J") == bool(s)
      
      # consider where each will die
      for (H, J, M, N, O) in subsets("BJ", size=5, select="M"):
      
        # how many die in J?
        n = (H, J, M, N, O).count('J')
      
        # "H: M and O will die in the same city"
        if not check(H, M == O): continue
      
        # "M: J and O will die in the same city"
        if not check(M, J == O): continue
      
        # "J: [exactly] three of the five prophets shall die in B"
        if not check(J, n == 2): continue
      
        # "N: N and H shall die in different cities"
        if not check(N, N != H): continue
      
        # output solution
        printf("n={n} [H={H} J={J} M={M} N={N} O={O}]")
      

      Solution: One of them will die in Jerusalem.

      There are two solutions:

      H: false, B
      J: false, B
      M: false, B
      N: false, B
      O: [true], J

      H: false, B
      J: false, B
      M: true, J
      N: false, B
      O: [false], B

      We are not given a prophesy by O, to verify whether it is true or not, but we can infer where he must die in order for the prophecies we are given to be consistent, and from that whether he makes prophecies that are true or false.

      In the first case he must die in Jerusalem, so must make true prophecies. And in the second case he must die in Babylon, and so must make false prophecies.

      Like

      • John Crabtree's avatar

        John Crabtree 8:18 pm on 22 April 2020 Permalink | Reply

        Let the prophesies be #1, #2, #3 and #4 by H, M, J and N respectively.
        From #4, H dies in Babylon.
        Then from #1, one, and only one, of M and O die in Babylon.
        Then from #2, J dies in Babylon.
        Then from #3, four prophets, including N, die in Babylon.
        And so one prophet (Micah or Obadiah) dies in Jerusalem.

        Liked by 1 person

  • Unknown's avatar

    Jim Randell 4:27 pm on 17 April 2020 Permalink | Reply
    Tags:   

    Teaser 3004: Going up 

    From The Sunday Times, 19th April 2020 [link] [link]

    In our football league, the teams all play each other once, with three points for a win and one for a draw. At the end of the season, the two teams with most points are promoted, goal difference being used to separate teams with the same number of points.

    Last season’s climax was exciting. With just two games left for each team, there were several teams tied at the top of the league with the same number of points. One of them, but only one, could be certain of promotion if they won their two games. If there had been any more teams on the same number of points, then none could have guaranteed promotion with two wins.

    How many teams were tied at the top of the league, and how many of the remaining matches involved any of those teams?

    [teaser3004]

     
    • Jim Randell's avatar

      Jim Randell 9:33 am on 18 April 2020 Permalink | Reply

      I supposed there were several teams, A, B, C, …, tied at the top. And we are looking for situations where team A is looking at a guaranteed promotion, if they win both their games.

      Obviously any of the other teams tied at the top of the table would also be in with a chance of promotion if they win both their games (as they will have the same maximum number of points as A).

      But if one of the teams were to win a match by an enormous number of goals, it would give them an unassailable goal difference. So A can only be guaranteed a win if there are fewer than three teams tied at the top after the games are played (so the goal difference rule doesn’t come into it).

      So we need to look at numbers of teams, such that there is an arrangement of remaining matches, where A (and only A) is guaranteed a promotion if they win both their matches, but if there were one more team then there would be no such arrangement of matches.

      This Python program is a bit slow (it takes 8.9s), but it does find what seems to be a reasonable answer. I may see if I can come up with a more efficient program later.

      from enigma import (cproduct, multiset, irange, join, printf)
      
      # generate matches for teams <ts> tied at the top
      # ts = teams tied at the top
      # ss = number of matches to be played by teams in <ts>
      # team Z is used to denote any other team not in <ts>
      def matches(ts, ss, ms=[]):
        # are we done?
        if not ss:
          yield ms
        else:
          # choose a team
          ks = sorted(ss.keys())
          t = ks.pop(0)
          # choose an opponent
          ks.append('Z')
          for x in ks:
            m = (t, x)
            if x == 'Z' or not (ms and m < ms[-1]):
              yield from matches(ts, ss.difference(m), ms + [m])
      
      # find teams that can be guaranteed promotion
      # ts = teams tied at the top
      # ms = remaining matches
      def solve(ts, ms):
        # find wins where 2 wins guarantees A a place in the top 2
        (inc, exc) = (set(), set())
        # choose winning teams for each match
        for wins in cproduct(ms):
          # collect teams with 2 wins
          m = multiset.from_seq(wins)
          ws = list(t for (t, n) in m.items() if n == 2 and t != 'Z')
          if len(ws) < 3:
            # a guaranteed win
            inc.update(ws)
          else:
            # not a guaranteed win
            exc.update(ws)
            if exc.issuperset(ts): return set()
        # return those teams that are guaranteed a win in all situations
        return inc.difference(exc)
      
      # format a sequence of matches
      fmt = lambda ms: join((x + "v" + y for (x, y) in ms), sep=", ", enc="()")
      
      # consider teams labelled A, B, C, ... (Z is used to denote "other" teams)
      # record teams where there is a set of matches that guarantees only team A a promotion
      r = dict()
      for n in irange(2, 25):
        teams = "ABCDEFGHIJKLMNOPQRSTUVWXY"[:n]
        ss = multiset.from_seq(teams * 2)
        for ms in matches(teams, ss):
          # does this set of matches guarantee a promotion for only A?
          ws = solve(teams, ms)
          if len(ws) == 1 and 'A' in ws:
            printf("n={n}: {ms} -> {ws}", ms=fmt(ms), ws=join(sorted(ws)))
            r[n] = ms
            break # we only need one set of matches
        if n not in r:
          printf("n={n}: <none>")
          # are we done?
          k = n - 1
          if k in r:
            ms = r[k]
            printf("{k} -> {ms}; {m} matches", m=len(ms), ms=fmt(ms))
            break
      

      Solution: There are 6 teams tied at the top. 7 of the remaining matches involve at least one of those teams.


      For six teams at the top:

      If A plays B and C and wins both matches, then neither B nor C can achieve the maximum number of points, so they are out of contention.

      And there are three more teams at the top, D, E, F, and they all play each other, then only one of them can achieve 2 wins, to tie with A at the top of the table.

      So A is guaranteed to finish in the top 2 if they win both their games, and get promotion.

      Introducing a seventh team, G, would mean that a third team could get two wins, so A‘s promotion would not be guaranteed.

      Like

  • Unknown's avatar

    Jim Randell 12:02 pm on 16 April 2020 Permalink | Reply
    Tags:   

    Brainteaser 1808: Next choice 

    From The Sunday Times, 11th May 1997 [link]

    Much nonsense is written about the lottery. It is true that there are about 14 million different choices of six numbers from 1 to 49, but often surprise is expressed when the winning six include at least two consecutive numbers. In common with a lot of people, when I choose my numbers I make sure that they are well spread out, thus fitting in with the usual conception that it is unlikely that consecutive numbers will be drawn.

    This set me thinking about what proportion of the 14 million possible choices of 6 numbers actually contained no two consecutive numbers. The answer is surprising and neat. So, in percentages, to the nearest whole number, what proportion of the choices include no consecutive numbers?

    This puzzle is included in the book Brainteasers (2002). The puzzle text above is taken from the book.

    [teaser1808]

     
    • Jim Randell's avatar

      Jim Randell 12:02 pm on 16 April 2020 Permalink | Reply

      We have already tackled a very similar puzzle with Enigma 1029 (also set by Victor Bryant under the pseudonym Susan Denham).

      The number of ways to choose 6 numbers from 49 is:

      C(49, 6) = 49! / (6! (49 − 6)!) = 13,983,816

      The number of ways to choose 6 non-consecutive numbers from 49 is:

      C(49 − 5, 6) = 44! / (6! (44 − 6)!) = 7,059,052

      This is approximately 50.48% of the total number of choices. So there are slightly more non-consecutive choices than consecutive choices.

      Solution: Approximately 50% of choices are non-consecutive.

      Like

  • Unknown's avatar

    Jim Randell 8:49 am on 14 April 2020 Permalink | Reply
    Tags:   

    Teaser 2650: Squares of oblongs 

    From The Sunday Times, 7th July 2013 [link] [link]

    I gave to each of Ruby and Annie a set of “Oblongs”. Each set consisted of nine pieces of card of sizes 1×2, 2×3, 3×4, 4×5, 5×6, 6×7, 7×8, 8×9 and 9×10. The idea was to use some or all of the cards to make various shapes in jigsaw fashion. I asked them to make a square using some of their own pieces. Ruby made the smallest square possible with her set and Annie made the largest square possible with hers. Then I collected up all the unused pieces of card.

    What (in increasing order) were the sizes of these unused pieces?

    [teaser2650]

     
    • Jim Randell's avatar

      Jim Randell 8:49 am on 14 April 2020 Permalink | Reply

      See also: Enigma 10, Enigma 1491, Enigma 1251.

      I packaged up the rectangle packer I wrote for Enigma 1491 into a separate module: rectpack.py.

      This Python program looks for subsets of the tiles that have an area that can be made into a square, and then tries to pack them into the square. It runs in 110ms.

      Run: [ @replit ]

      from rectpack import pack
      from enigma import (irange, subsets, is_square, Accumulator, diff, printf)
      
      # available tiles
      tiles = list((i, i + 1) for i in irange(1, 9))
      
      # find the smallest and largest squares
      rs = [ Accumulator(fn=min), Accumulator(fn=max) ]
      
      # choose subsets of the tiles
      for ts in subsets(tiles, min_size=2):
        # is the area a square number
        t = sum(a * b for (a, b) in ts)
        x = is_square(t)
        if x is None: continue
      
        # attempt to fit the rectangles into the square
        for ps in pack(x, x, ts):
          printf("{t} = {x}^2 -> {ts}")
          printf("-> {ps}")
          for r in rs: r.accumulate_data(x, ts)
          break  # only need one packing
      
      # output solution
      printf("min = {rs[0].value}^2, {rs[0].data}")
      printf("max = {rs[1].value}^2, {rs[1].data}")
      
      # unused tiles
      us = diff(tiles, rs[0].data) + diff(tiles, rs[1].data)
      printf("unused = {us}", us=sorted(us))
      

      Solution: The unused pieces are: 1×2, 2×3, 8×9.

      The smallest square that can be made is a 16×16 square using all the pieces except 1×2 and 8× 9.

      The largest square that can be made is a 18×18 square using all the pieces except 2×3.

      These are in fact the only two sets of pieces that can be assembled into squares.

      Like

  • Unknown's avatar

    Jim Randell 11:43 am on 12 April 2020 Permalink | Reply
    Tags:   

    Brain-Teaser 517: [Rugby table] 

    From The Sunday Times, 9th May 1971 [link]

    The final table of the inter-zone Rugby championships of Pongoland reads:

    Each tribe used only one goal-kicker; C’s kicked most points and A’s least. C had only one penalty scored against them.

    The only types of score were:

    try converted to goal (5 points)
    try unconverted (3 points)
    penalty goal (3 points)

    How were the two sides’ scores made up in the match Aboma vs. Bwaga?

    This puzzle was originally published with no title.

    [teaser517]

     
    • Jim Randell's avatar

      Jim Randell 11:44 am on 12 April 2020 Permalink | Reply

      It seems that the points scored by the kicker are: 2 points for a conversion; 0 points for a try; 3 points for a penalty goal.

      I wrote a MiniZinc model to solve the problem:

      %#! minizinc -a
      
      % xYZ = number of score type x (= c (5), t (3), p (3)) by Y against Z
      
      var 0..2: cAB;
      var 0..4: tAB;
      var 0..4: pAB;
      var 0..2: cBA;
      var 0..4: tBA;
      var 0..4: pBA;
      
      var 0..3: cAC;
      var 0..5: tAC;
      var 0..5: pAC;
      var 0..1: cCA;
      var 0..3: tCA;
      var 0..3: pCA;
      
      var 0..2: cBC;
      var 0..4: tBC;
      var 0..4: pBC;
      var 0..1: cCB;
      var 0..3: tCB;
      var 0..3: pCB;
      
      % total points
      function var int: points(var int: c, var int: t, var int: p) = 5 * c + 3 * t + 3 * p;
      
      % kicked points
      function var int: kicks(var int: c, var int: t, var int: p) = 2 * c + 3 * p;
      
      % point values in the table
      constraint points(cAB, tAB, pAB) + points(cAC, tAC, pAC) = 18;
      constraint points(cBA, tBA, pBA) + points(cCA, tCA, pCA) = 12;
      
      constraint points(cBA, tBA, pBA) + points(cBC, tBC, pBC) = 14;
      constraint points(cAB, tAB, pAB) + points(cCB, tCB, pCB) = 13;
      
      constraint points(cCA, tCA, pCA) + points(cCB, tCB, pCB) = 9;
      constraint points(cAC, tAC, pAC) + points(cBC, tBC, pBC) = 16;
      
      % A won both their games, C lost both their games
      constraint points(cAB, tAB, pAB) > points(cBA, tBA, pBA); % A beat B
      constraint points(cAC, tAC, pAC) > points(cCA, tCA, pCA); % A beat C
      constraint points(cBC, tBC, pBC) > points(cCB, tCB, pCB); % B beat C
      
      % kicked points: C > B > A
      constraint kicks(cAB, tAB, pAB) + kicks(cAC, tAC, pAC) < kicks(cBA, tBA, pBA) + kicks(cBC, tBC, pBC);
      constraint kicks(cBA, tBA, pBA) + kicks(cBC, tBC, pBC) < kicks(cCA, tCA, pCA) + kicks(cCB, tCB, pCB);
      
      % C had 1 penalty scored against them
      constraint pAC + pBC = 1;
      
      solve satisfy;
      

      Solution: Aboma scored 2 conversions (for 10 points). Bwaga scored 1 try and 1 penalty (for 6 points)

      The results are:

      A vs. B: 10 pts (2c) vs. 6 pts (t + p)
      A vs. C: 8 pts (c + t) vs. 6 pts (2p)
      B vs. C: 8 pts (c + p) vs. 3 pts (p)

      A’s kicker made 6 points.
      B’s kicker made 8 points.
      C’s kicker made 9 points.

      Like

  • Unknown's avatar

    Jim Randell 5:27 pm on 9 April 2020 Permalink | Reply
    Tags:   

    Teaser 3003: All that glitters 

    From The Sunday Times, 12th April 2020 [link] [link]

    My aunt has a collection of sovereigns, and she set me a challenge:

    “You can have the coins if you can work out the dates, which (in increasing order) are equally spaced and all in the 20th century. The number of coins is an odd prime. The highest common factor of each pair of dates is an odd prime. The sum of the number of factors of each of the dates (including 1 and the date itself) is an odd prime.”

    I worked out the dates, though the gift was much less valuable than I’d hoped.

    What were the dates?

    [teaser3003]

     
    • Jim Randell's avatar

      Jim Randell 5:46 pm on 9 April 2020 Permalink | Reply

      I assumed the dates we are looking for are the years in the 20th century for each coin.

      This Python program runs in 93ms.

      Run: [ @repl.it ]

      from enigma import (primes, subsets, irange, inf, gcd, tau, printf)
      
      primes.extend(100)  # primes up to 100
      
      # check a number is an odd prime
      check = lambda n: n > 2 and n in primes
      
      # choose years for the first 2 coins
      for (a, b) in subsets(irange(1901, 1999), size=2):
        if not check(gcd(a, b)): continue
      
        # consider a sequence with n terms
        d = b - a
        for n in primes.irange(3, inf):
          z = a + (n - 1) * d
          if z > 2000: break
          s = list(irange(a, z, step=d))
      
          # gcd of each pair is an odd prime
          if not all(check(gcd(x, y)) for (x, y) in subsets(s, size=2)): break
      
          # sum of the number of divisors of each year is an odd prime
          if not check(sum(tau(x) for x in s)): continue
      
          # output solution
          printf("a={a} b={b}, d={d} -> n={n}: {s}")
      

      Solution: The dates of the coins were: 1903, 1936, 1969.


      Manually (as suggested by Robert):

      Most number have divisors that come in pairs, so have an even number of divisors. The exception is the square numbers, which have an odd number of divisors (see: Puzzle #08).

      So, in order for the sum of the divisors of the dates to be odd, the list of dates must include an odd number of square numbers. And in the range 1901 – 2000 there is only one square number, 1936. So that must be one of the dates.

      1936 factorises as: (2^4)(11^2), so the other dates must have a GCD with 1936 of 11.

      For numbers less than 1936, we get: 1925, 1903. For numbers greater than 1936 we get: 1947, 1969, 1991.

      Looking for arithmetic sequences containing 1936, with a number of elements that is an odd prime we get:

      d=11: (1925, 1936, 1947); divisor sum = 35
      d=33: (1903, 1936, 1969); divisor sum = 23

      Only the second of these has a divisor sum that is prime, and gcd(1903, 1969) = 11 so this satisfies all the required conditions and gives the answer.

      Like

    • Robert Brown's avatar

      Robert Brown 9:08 pm on 9 April 2020 Permalink | Reply

      The only numbers with odd numbers of factors are perfect squares. There is only one of these in the 20th century, and that date has only has one factor >1 that’s an odd prime. Quite easy to find the answer by inspection.

      Like

  • Unknown's avatar

    Jim Randell 12:29 pm on 9 April 2020 Permalink | Reply
    Tags:   

    Teaser 2862: Algebria’s standard 

    From The Sunday Times, 30th July 2017 [link] [link]

    The Algebrian rectangular flag is highly symbolic. Each of its sides is an even number of inches long and a diagonal divides it into two triangles, one blue and one green, representing its two founding tribes. The length of the diagonal (in inches) is the number of states in Algebria, and the area of the flag (in square inches) is the twentieth century year in which the country obtained independence.

    How many states are there in Algebria, and in which year did the country obtain independence?

    [teaser2862]

     
    • Jim Randell's avatar

      Jim Randell 12:30 pm on 9 April 2020 Permalink | Reply

      If the dimensions of the flag are X and Y (and the diagonal is Z), then the area XY is between 1901 and 2000.

      X and Y are even (say X = 2x, Y = 2y), which limits xy to be between 476 and 500.

      Originally I looked at the possible areas to find viable x, y, z values, but the following Python program uses the [[ pythagorean_triples() ]] generator from the enigma.py library to find x, y, z values that can be scaled up to give an appropriate flag. It runs in 76ms.

      Run: [ @replit ]

      from enigma import (pythagorean_triples, irange, inf, printf)
      
      # consider primitive pythagorean triples
      for (x, y, z) in pythagorean_triples(501, primitive=1):
        # and scale up to an appropriate size
        for k in irange(2, inf, step=2):
          (X, Y, Z) = (k * x, k * y, k * z)
          A = X * Y
          if A < 1901: continue
          if A > 2000: break
          printf("X={X} Y={Y} Z={Z} A={A} [x={x} y={y} z={z} k={k}]")
      

      Solution: There are 68 states in Algebria. It gained independence in 1920.

      Like

  • Unknown's avatar

    Jim Randell 3:34 pm on 7 April 2020 Permalink | Reply
    Tags: by: WT Blunt   

    Brainteaser 1805: Find the deuce 

    From The Sunday Times, 20th April 1997 [link]

    Adam, Bill, Charlie and Dave play a game using the ace (counting as 1) and 2 to 10 of spades. These cards are shuffled and placed face down on the table. Each player in turn draws one card and declares whether it is odd or even. Each then in turn draws a further card and must declare a number being either the sum or the product of the two cards held. The winner is the first to deduce which cards remain on the table. They are all perfect logicians, draw every possible inference, and rely on the fact that the others do too.

    In a recent game the calls went as follows:

    Adam: “odd”
    Bill: “odd”
    Charlie: “odd”
    Dave: “odd”
    Adam: “6”
    Bill: “12”
    Charlie: “15”

    But as Dave reached for his second card, a player claimed the game.

    Who was the winner and where was the 2?

    This puzzle is included in the book Brainteasers (2002). The puzzle text above is taken from the book.

    [teaser1805]

     
    • Jim Randell's avatar

      Jim Randell 3:34 pm on 7 April 2020 Permalink | Reply

      They could just have easily played the game with 10 cards numbered 1 to 10.

      There are 5 odd cards (1, 3, 5, 7, 9) and only four players, so no one can win from the first round.

      This Python program collects the possible sequences of cards, and then works out it any of the players can determine the cards in the sequence given that they know their own cards. (If you can determine the cards in the sequence, you know which cards remain on the table). And then repeats this until the set of possible sequences remains unchanged (so all deductions have been made). It then moves on to the next play described in the text, with no-one winning until after C has drawn his second card. D is about to draw his second card when someone else claims victory.

      This Python program runs in 88ms.

      Run: [ @repl.it ]

      from enigma import irange, subsets, filter_unique, ordered, intersect, printf
      
      # cards
      cards = set(irange(1, 10))
      
      # collect hand for player k from a sequence of cards
      def hand(s, k, n=4):
        return ordered(*(s[i] for i in irange(k, len(s) - 1, step=n)))
      
      # find wins from sequences ss
      def win(ss):
        r = dict()
        us = list()
        # can player k win?
        for (i, k) in enumerate("ABCD"):
          (rk, uk) = filter_unique(ss, (lambda s: hand(s, i)), (lambda s: ordered(*s)))
          if rk: r[k] = rk
          us.append(uk)
        # return wins (dict), and sequences that do not give a win (set)
        return (r, intersect(us))
      
      # analyse sequences ss
      def analyse(ss):
        n = len(ss)
        while True:
          (r, ss) = win(ss)
          yield (r, ss)
          m = len(ss)
          if m == n: break
          n = m
      
      # play a card for player k, who delares d
      def play(ss, k, d):
        for s in ss:
          for x in cards.difference(s):
            if x + s[k] == d or x * s[k] == d:
              yield s + (x,)
      
      # the first four plays are all odd cards
      ss = list(subsets((1, 3, 5, 7, 9), size=4, select="P"))
      
      # no-one wins
      for (r, ss) in analyse(ss): pass
      
      # A (player 0) declares 6
      ss = list(play(ss, 0, 6))
      
      # no-one wins
      for (r, ss) in analyse(ss): pass
      
      # B (player 1) declares 12
      ss = list(play(ss, 1, 12))
      
      # no-one wins
      for (r, ss) in analyse(ss): pass
      
      # C (player 2) declares 15
      ss = list(play(ss, 2, 15))
      
      # someone (other than D) wins
      for (r, ss) in analyse(ss):
        if r and 'D' not in r:
          for k in sorted(r.keys()):
            for v in r[k]:
              printf("{k} wins: {v}")
          break
      

      Solution: Charlie won. The 2 remained on the table.

      I agree with the published answer, but not with the full solution given at the back of the book.

      My solution is that C claims victory and the final situation when C wins is:

      A: 1 then 6
      B: 3 then 4
      C: 5 then 10 (or: 7 then 8)
      D: 9
      table: 2, 7, 8 (or: 2, 5, 10)

      It makes sense that C is the one who can claim victory as he could be holding (5, 10) or (7, 8), and only C knows for sure.


      The solution given in the book [ link ] says that the final situation when C wins is:

      A: 1 then 5 (or: 5 then 1)
      B: 3 then 4
      C: 9 then 6
      D: 7
      table: 2, 8 [and, presumably, 10]

      However the first four cards are odd, and if A drew the last remaining odd card, then he would know that the cards that remained on the table at this point were the 5 even cards and would claim victory.

      So this cannot be the situation (and given that A did not claim victory as soon as he drew his second card everyone would know that A cannot have 1 and 5 (so must have 3 and 2, or 1 and 6)).

      Like

      • John Crabtree's avatar

        John Crabtree 6:16 am on 10 April 2020 Permalink | Reply

        D does not win. Summarizing the successive elimination:
        After A’s 2nd call, if A = 1 + 5, A wins. Everybody knows this. This eliminates (a) and (b).
        After B’s 2nd call, if B = 3 + 9, B wins. Everybody knows this. This eliminates (c) and (d).
        After C’s 2nd call, if D = 1, 5 or 7, D wins. This eliminates (e), (g) and (i).
        This leaves two cases, (f) and (h) as noted by Jim.
        And so C wins and the 2 is on the table.

        It is ironic that the published solution was correct, but for the wrong reasons.

        Like

  • Unknown's avatar

    Jim Randell 4:52 pm on 3 April 2020 Permalink | Reply
    Tags:   

    Teaser 3002: Short-cut 

    From The Sunday Times, 5th April 2020 [link] [link]

    To demonstrate a bit of geometry and trigonometry to my grandson, I took a rectangular piece of paper whose shorter sides were 24 cm in length. With one straight fold I brought one corner of the rectangle to the midpoint of the opposite longer side. Then I cut the paper along the fold, creating a triangle and another piece. I then demonstrated to my grandson that this other piece had double the area of the triangle.

    How long was the cut?

    [teaser3002]

     
    • Jim Randell's avatar

      Jim Randell 5:40 pm on 3 April 2020 Permalink | Reply

      If we assume the fold goes from one of the corners of the rectangle, then we get a nice answer. (See: Enigma 1402). I don’t think other constructions are possible. [This assumption is justified below].

      Brainteaser 1798 is a puzzle with a similar theme.

      The triangles X, Y, Z are all right-angled. We need to find the value of h, the hypotenuse of triangle X.

      The area of triangle X must be the same as the sum of the areas of triangles Y and Z, so:

      (24 − a)b = 12b + ab/2
      12b = 3ab/2
      a = 8

      From triangle Z:

      b² = 16² − 8² = 192

      (So the long side of the rectangle is 2b = 16√3, approximately 27.71 cm).

      And from triangle X:

      h² = 16² + 2²×192 = 1024
      h = 32

      Solution: The length of the cut is 32 cm.

      And we can then demonstrate that X = Y + Z by constructing X from Y and Z:

      X, Y, Z are all (30°, 60°, 90°) triangles. The same shape as one of the standard set squares.

      Like

      • Jim Randell's avatar

        Jim Randell 3:39 pm on 5 April 2020 Permalink | Reply

        Adding a 24-by-2x strip on the left-hand side of the diagram (to account for the fold not going from a corner), and adjusting the bases of triangles Y and Z to (b − x) and (b + x) leads to the following 2 equations:

        [X = Y + Z + 48x] ⇒ 3b(8 − a) = (72 + a)x
        [Y and Z are similar] ⇒ (24 − a)x = 3b(8 − a)

        These can only be satisfied (for positive a, b) if x = 0 and a = 8 (i.e. a is 1/3 the height of the rectangle), as above.

        So the fold must go from one of the corners, and the assumption above is justified.

        Like

    • Benet Allen's avatar

      Benet Allen 7:49 pm on 5 April 2020 Permalink | Reply

      There’s only one shape where you can fold a corner to the midpoint of the opposite side and be left with a triangle. That’s a 2×1 rectangle. And surely, the remaining piece will have three times the area of the triangle? Am befuddled.

      Like

      • Jim Randell's avatar

        Jim Randell 9:23 pm on 5 April 2020 Permalink | Reply

        My diagram above [ link ] is actually to scale. If you print it out and cut out the rectangle you will find that you can fold the white X onto the grey X, and then fold Y and Z on top (or behind) to make another copy of X, neatly demonstrating that X = Y + Z as required.

        Like

  • Unknown's avatar

    Jim Randell 12:12 pm on 2 April 2020 Permalink | Reply
    Tags:   

    Brain-Teaser 516: [Cabinet reshuffle] 

    From The Sunday Times, 2nd May 1971 [link]

    In Northminster the Premier is planning a reshuffle of five positions in his Cabinet. They are (in decreasing order of rank):

    Deputy Premier,
    Chancellor of the Purse-strings,
    Minister of Mails,
    Secretary of Science,
    Head Whip.

    At the moment these jobs are held (not respectively) by:

    Attler,
    Balfy,
    Chamberton,
    Disreel,
    Edane.

    Soon these five jobs are to be re-allocated among these five people and each person will get a different job from the one he holds at the moment.

    In the reshuffle the Premier is going to promote Chamberton to Minister of the Mails, or above. Edane is also to be promoted. Attler has made it clear that if he is going to be junior to Chamberton, then the only Deputy Premier he would work under would be Disreel.

    Balfy is going to be demoted, but one consolation is that after the reshuffle he will be senior to someone to whom at the moment he is junior. Finally, Disreel will become Deputy Premier only if Balfy becomes Minister of Mails.

    The Premier tries to avoid a party split by arranging his reshuffle to satisfy all the above demands. Also he arranges it with the least number of demotions possible in the circumstances.

    Who is the present Secretary of Science? And, who is to become Secretary of Science?

    This puzzle was originally published with no title.

    [teaser516]

     
    • Jim Randell's avatar

      Jim Randell 12:12 pm on 2 April 2020 Permalink | Reply

      In order to get a unique solution I had to add a couple of extra “implied” conditions (the kind that got me into trouble in Enigma 99).

      So: “… is going to promote Chamberton to Minister of the Mails, or above”, implies that C’s current position is below MoM.

      and: “Disreel will become Deputy Premier only if …”, implies that D is not currently Deputy Premier. (Also the fact that A would serve under D as Deputy Premier implies that D does not currently hold this position).

      and (maybe): “… Attler has made it clear that if he is going to be junior to Chamberton …”, implies that A is not currently junior to C (although this extra condition is not required to get a unique solution).

      With these conditions made explicit we find there is a single answer to the puzzle.

      This Python program runs in 86ms.

      Run: [ @repl.it ]

      from enigma import (defaultdict, irange, subsets, printf)
      
      # "p -> q" = "if p then q", "q if p", "p only if q"
      implies = lambda p, q: not(p) or q
      
      # record (by number of demotions) who occupies position 4
      r = defaultdict(set)
      
      # consider "before" positions
      for before in subsets(irange(1, 5), size=5, select="P"):
        (bA, bB, bC, bD, bE) = before
      
        # [implied] D is not currently 1
        if bD == 1: continue
      
        # [implied] A is not currently junior to C
        if (bC < bA): continue
      
        # [implied] C is currently below 3
        if not (bC > 3): continue
      
        # consider "after positions"
        for after in subsets(irange(1, 5), size=5, select="P"):
          (aA, aB, aC, aD, aE) = after
      
          # nobody keeps the same post
          if any(bX == aX for (bX, aX) in zip(before, after)): continue
      
          # if A is junior to C, then D must be 1
          if not implies(aA > aC, aD == 1): continue
      
          # D becomes 1 only if B becomes 3
          if not implies(aD == 1, aB == 3): continue
      
          # C is to be promoted to 3 or above
          if not (aC < 4 and aC < bC): continue
      
          # E is to be promoted
          if not (aE < bE): continue
      
          # B is to be demoted ...
          if not (aB > bB): continue
      
          # ... but will become senior to someone who was his junior
          if not any(aB < aX and bB > bX for (bX, aX) in zip(before, after)): continue
      
          # count the number of demotions
          d = sum(aX > bX for (bX, aX) in zip(before, after))
      
          printf("[d={d}, A: {bA}->{aA}; B: {bB}->{aB}; C: {bC}->{aC}; D: {bD}->{aD}; E: {bE}->{aE}]")
          b = dict(zip(before, "ABCDE"))
          a = dict(zip(after, "ABCDE"))
          r[d].add((b[4], a[4]))
      
      # look for the fewest number of demotions
      k = min(r.keys())
      for (b4, a4) in r[k]:
        printf("{k} demotions: SoS = {b4}->{a4}")
      

      Solution: Chamberton is the current Secretary of Science. Edane will be the new Secretary of Science.

      There is only one scenario that has only 2 demotions:

      A: demoted from Deputy Premier to Head Whip
      B: demoted from Chancellor to Minister of Mails
      C: promoted from Secretary of Science to Chancellor
      D: promoted from Minster of Mails to Deputy Premier
      E: promoted from Head Whip to Secretary of Science

      We are told B is to be demoted, and someone else who was above B must also be demoted under B, so we cannot do better than 2 demotions.

      There are 2 further scenarios that satisfy the conditions that have 3 demotions.

      Like

    • John Crabtree's avatar

      John Crabtree 10:06 pm on 3 April 2020 Permalink | Reply

      Let the five positions in order of rank be P1, P2, P3, P4 and P5.

      C and E will be promoted, D can be promoted, and B has somebody senior to him, and so A is currently in P1.
      B can be demoted to P3, and so is currently in P2.
      A will move to P4 or P5 (lower than B), and so will be junior to C (P3 or above), and so D moves to P1, and so B moves to P3, and so C moves to P2.
      To minimise the number of demotions A moves to P5, and E moves from P5 to P4.
      The current positions are not in order, and so currently C is in P4, and D is in P3.

      Chamberton is the current Secretary of Science.
      Edane will become the Secretary of Science.

      Like

  • Unknown's avatar

    Jim Randell 10:30 am on 31 March 2020 Permalink | Reply
    Tags:   

    Teaser 2877: Four steadings and a numeral 

    From The Sunday Times, 12th November 2017 [link] [link]

    Farmers Al, Bo, Cy and Di have different double-digit numbers of sheep kept in their respective steadings. Al has the fewest and his number of sheep is a certain fraction of Bo’s number of sheep. Also, Bo’s number of sheep is that same fraction of Cy’s number, and Cy’s number is that same fraction of Di’s.

    If I told you the total of Bo’s number of sheep added to Cy’s, then you would be unable to work out all their numbers of sheep. Similarly, if instead I told you just Bo’s number of sheep, then you would be unable to work out all the other numbers.

    What (in the order Al, Bo, Cy, Di) are their numbers of sheep?

    [teaser2877]

     
    • Jim Randell's avatar

      Jim Randell 10:31 am on 31 March 2020 Permalink | Reply

      This Python program looks for possible geometric sequences for A, B, C, D (the numbers of sheep). And then uses the [[ filter_unique() ]] function from the enigma.py library to find sets where (B + C) does not identify a single sequence, and where B does not identify a single sequence. The solution is in the intersection of these two sets.

      This Python program runs in 62ms.

      Run: [ @repl.it ]

      from enigma import (subsets, irange, div, fraction, filter_unique, unpack, intersect, printf)
      
      # collect results as (A, B, C, D)
      rs = list()
      
      # start with values for A and B
      for (A, B) in subsets(irange(10, 97), size=2):
        # f = B / A
        # C = f * B = B^2 / A
        C = div(B * B, A)
        if C is None or C > 98: continue
        # D = f * C = BC / A
        D = div(B * C, A)
        if D is None or D > 99: continue
      
        printf("[A={A} B={B} C={C} D={D}, f={f[0]}/{f[1]}]", f=fraction(B, A))
        rs.append((A, B, C, D))
      
      # B + C does not uniquely identify the solution
      (_, s1) = filter_unique(rs, unpack(lambda A, B, C, D: B + C))
      printf("[s1 = {s1}]")
      
      # B does not uniquely identify the solution
      (_, s2) = filter_unique(rs, unpack(lambda A, B, C, D: B))
      printf("[s2 = {s2}]")
      
      # so the solution is in both sets
      for (A, B, C, D) in intersect((s1, s2)):
        printf("A={A} B={B} C={C} D={D}")
      

      Solution: The numbers of sheep are: Al=16, Bo=24, Cy=36, Di=54.

      Each term in the 3/2 times the previous term.

      There are 6 possible geometric sequences:

      [1] A=10, B=20, C=40, D=80; f=2
      [2] A=11, B=22, C=44, D=88; f=2
      [3] A=12, B=24, C=48, D=96; f=2
      [4] A=16, B=24, C=36, D=54; f=3/2
      [5] A=24, B=36, C=54, D=81; f=3/2
      [6] A=27, B=36, C=48, D=64; f=4/3

      [1], [4] have the same value for B + C (= 60).

      [3], [4] have the same value for B (=24), and [5], [6] have the same value for B (= 36).

      The solution occurs in both sets, so is sequence [4].

      Like

    • GeoffR's avatar

      GeoffR 5:06 pm on 1 April 2020 Permalink | Reply

      The following programme gives the same six sequences for A,B,C and D.

      for a in range(10,99):
        for b in range(a+1,99):
          for c in range(b+1,99):
            for d in range(c+1,99):
              # Ratios given are a/b = c/d and b/c = c/d
              if a*c == b*b and b*d == c*c:
                print(f"A={a}, B={b}, C={c}, D={d}")
       
      # A=10, B=20, C=40, D=80
      # A=11, B=22, C=44, D=88
      # A=12, B=24, C=48, D=96
      # A=16, B=24, C=36, D=54  << Answer - see Jim's logic above
      # A=24, B=36, C=54, D=81
      # A=27, B=36, C=48, D=64
      
      
      
      

      Like

  • Unknown's avatar

    Jim Randell 4:46 pm on 27 March 2020 Permalink | Reply
    Tags:   

    Teaser 3001: Tetragonal toy tiles 

    From The Sunday Times, 29th March 2020 [link] [link]

    (see: [ @wikipedia ])

    Thirteen toy tiles comprised a square, rectangles, rhombuses (diamonds on a playing card are rhombuses) and kites (as shown in the diagram). All of each different type were identical. A rhombus’s longer diagonal was a whole number of inches (equalling any diagonal of any other type). Its shorter diagonal was half this. Also, one side of a rectangle was slightly over one inch.A pattern I made, using every tile laid flat, had all the symmetries of a square. After laying the first tile, each subsequent tile touched at least one other previously placed tile. Ultimately, any contact points were only where a vertex of a tile touched a vertex of just one other tile; only rhombuses touched every other tile type.What, in inches, was a square’s diagonal?

    [teaser3001]

     
    • Jim Randell's avatar

      Jim Randell 6:29 pm on 27 March 2020 Permalink | Reply

      I came up with a pattern for 13 tiles that has the same symmetries as a square (I’ll make a diagram of it later), and that gave me a way to calculate the sides of the rectangle, in terms of the larger diagonal of the rhombus, x.

      Once these are calculated the value of x can be determined manually, or here is a quick program to do it:

      Run: [ @replit ]

      from enigma import (sqrt, irange, inf, printf)
      
      # multipliers for the sides of the rectangle
      (ra, rb) = (sqrt(1, 8), sqrt(7, 8))
      
      # consider the diagonal of the square piece
      for x in irange(1, inf):
        # calculate the sides of the rectangle
        (a, b) = (ra * x, rb * x)
        if 1.0 < a < 1.1 or 1.0 < b < 1.1:
          printf("x={x} [a={a:.3f} b={b:.3f}]")
        elif a > 1.1:
          break
      

      Solution: The length of the square’s diagonal is 3 inches.


      I arranged 13 shapes (1 square, 4 rectangles, 4 rhombuses, 4 kites) into the following pattern:

      All the diagonals of all the shapes are equal (= x), except for the shorter diagonal of the rhombus (= x/2).

      In this arrangement the short side of the rectangle is the hypotenuse of a right-angled triangle where the other two sides have length x/4, so it has a length of x√(1/8), and so the longer side has a length of x√(7/8).

      Setting x = 3 gives dimensions of 1.061 × 2.806 inches. The smaller side being close to 1 + 1/16 inches. Which is “slightly over 1 inch” as required.

      The exact shape of the kite doesn’t matter (as long as both diagonals are x), it doesn’t affect the calculation for the rectangle. (In particular the kites could all be rotated through 180° to give a second arrangement).

      Placing the rhombuses the other way leaves a gap that cannot be filled by the required rectangle, and we don’t have enough shapes to fill the gap with multiple shapes.

      Like

    • Robert Brown's avatar

      Robert Brown 8:06 am on 28 March 2020 Permalink | Reply

      I did a scale drawing. My kite has the same aspect ratio as the one in the original text, which makes the large angle equal to that of the rhombus. I don’t think your program would have found my answer, which has the rectangle 1.03 inches high.

      Like

      • Jim Randell's avatar

        Jim Randell 8:13 am on 28 March 2020 Permalink | Reply

        @Robert: My arrangement looks like this [ link ], so the exact shape of the kite doesn’t affect the calculations. But I didn’t look too hard for alternative patterns (although you would hope the setter would have made sure there was a unique answer to the puzzle).

        Like

    • Robert Brown's avatar

      Robert Brown 11:54 am on 28 March 2020 Permalink | Reply

      Interesting. Each rhombus has a thin & thick ‘corner’. My layout has the thin corners connected to the square, then the kites & rhombuses are all angled to fit round the square. I tried (but failed) to get the rectangles in the corner, to give it ‘all the symmetries of a square’ ! My rectangle is long & thin, with diagonal =9 inches. I see Brian has 3 inches, I wonder what his layout looks like . . .

      Like

      • Jim Randell's avatar

        Jim Randell 12:36 pm on 28 March 2020 Permalink | Reply

        I tried my pattern with the rhombuses turned through 90°, but I found the gap between the remaining vertices was too large to fit any of the other shapes into.

        Looking at Brian’s attachment to the Google Sites page it looks like he has found the same layout I did (although I don’t think his kites are the right shape, but that doesn’t change the answer).

        Like

        • Brian Gladman's avatar

          Brian Gladman 1:15 pm on 28 March 2020 Permalink | Reply

          That is because the teaser doesn’t explicitly constrain the non-rhombus shapes to have equal diagonals (of course, all except the kite do). The longest rhombus diagonal can be any diagonal of any other shape and I chose to match the longest diagonals of the rhombus and the kite.

          Like

          • Jim Randell's avatar

            Jim Randell 1:20 pm on 28 March 2020 Permalink | Reply

            @Brian: It does say that the longer diagonal of the rhombus should “equal any diagonal of any other type”, so I think the vertices of the kite must touch the sides of an x by x bounding box.

            Like

            • Brian Gladman's avatar

              Brian Gladman 2:36 pm on 28 March 2020 Permalink | Reply

              Yes, you interpret it to mean “equal to the diagonals of the other types” (surely a simpler expression of this interpretation), whereas I interpret it to mean a choice between “any of the diagonals of any other type”. Fortunately this clear ambiguity (!) doesn’t have an impact on the answer.

              Like

    • Robert Brown's avatar

      Robert Brown 12:33 pm on 28 March 2020 Permalink | Reply

      So my alternative pattern lacks one of the required symmetries (it has clockwise & counter clockwise versions). We’ve had problems with words before . . . I guess Brian’s layout is similar to yours.

      Like

  • Unknown's avatar

    Jim Randell 9:49 am on 24 March 2020 Permalink | Reply
    Tags:   

    Teaser 2500: [Rogue ball detection] 

    From The Sunday Times, 22nd August 2010 [link] [link]

    A well-known puzzle asks:

    “If among 12 snooker balls one is a different weight, how can the rogue ball be identified – together with deciding whether it is heavier or lighter – in three weighings on a balance?”

    Recently I faced a very similar problem of finding a rogue ball among a consignment of 39 identical-looking balls – and deciding if it was heavier or lighter. I had at my disposal a two-pan balance.

    How many weighings did I need?

    This puzzle was originally published with no title.

    [teaser2500]

     
    • Jim Randell's avatar

      Jim Randell 9:50 am on 24 March 2020 Permalink | Reply

      We dealt with a similar puzzle in Enigma 1589 (also set by Peter Harrison). For that puzzle I wrote a program that searches for a minimal decision tree.

      For an analytical solution the paper Weighing Coins: Divide and Conquer to Detect a Counterfeit by Mario Martelli and Gerald Gannon [ link ] provides an elegant analysis to determine the maximum number of coins that can be distinguished using a certain number of weighings for four related problems.

      And this gives us the solution to this puzzle:

      Solution: 4 weighings can be used to find the rogue object in a set of 39.

      Like

    • Jim Randell's avatar

      Jim Randell 9:44 pm on 24 March 2020 Permalink | Reply

      For Enigma 1589 I wrote the following code to generate the decision trees for the four types of problem described in the linked paper.

      It can be used to generate decision trees for either puzzle.

      Run: [ @codepad ] [ @repl.it ]

      from enigma import (irange, arg, printf)
      
      # weigh 3^n coins in n weighings, suspect coin is lighter
      def solve_lighter(n, coins, p=''):
        assert len(coins) == 3**n
        # 3 coins
        if n == 1:
          # weigh two of the coins
          printf("{p}{coins[0]} < {coins[1]} -> {coins[0]}L")
          printf("{p}{coins[0]} = {coins[1]} -> {coins[2]}L")
          printf("{p}{coins[0]} > {coins[1]} -> {coins[1]}L")
        else:
          # divide the coins into 3 piles
          k = len(coins) // 3
          (c1, c2, c3) = (coins[:k], coins[k:2 * k], coins[2 * k:])
          printf("{p}{c1} < {c2}")
          solve_lighter(n - 1, c1, p + '  ')
          printf("{p}{c1} = {c2}")
          solve_lighter(n - 1, c3, p + '  ')
          printf("{p}{c1} > {c2}")
          solve_lighter(n - 1, c2, p + '  ')
      
      
      # weigh 3^n coins in n weighings
      # suspect coin is in reds if heavier, in blacks if lighter
      def solve_red_black(n, reds, blacks, red='H', black='L', p=''):
        assert len(reds) + len(blacks) == 3**n and len(reds) == len(blacks) + 1
        # 2 red, 1 black
        if n == 1:
          # weigh the two reds
          printf("{p}{reds[0]} < {reds[1]} -> {x[0]}{x[1]}", x=((reds[1], 'H') if red == 'H' else (reds[0], 'L')))
          printf("{p}{reds[0]} = {reds[1]} -> {blacks[0]}{black}")
          printf("{p}{reds[0]} > {reds[1]} -> {x[0]}{x[1]}", x=((reds[0], 'H') if red == 'H' else (reds[1], 'L')))
        else:
          # weigh (3^(n-1) + 1)/2 reds against (3^(n-1) - 1)/2 of the blacks
          k = (3**(n - 1) + 1) // 2
          (r1, r2, r3) = (reds[:k], reds[k:2 * k], reds[2 * k:])
          (b1, b2, b3) = (blacks[:k - 1], blacks[k - 1:2 * k - 2], blacks[2 * k - 2:])
          (left, right) = (r1 + b1, r2 + b2)
          printf("{p}{left} < {right}")
          solve_red_black(n - 1, r2, b1, red, black, p + '  ')
          printf("{p}{left} = {right}")
          solve_red_black(n - 1, b3, r3, black, red, p + '  ')
          printf("{p}{left} > {right}")
          solve_red_black(n - 1, r1, b2, red, black, p + '  ')
      
      
      # weigh (3^n - 1) / 2 suspect coins in n weighings
      # given a known good coin
      def solve_test_coin(n, good, coins, p=''):
        assert len(coins) == ((3**n) - 1) // 2
        if n == 1:
          # weigh the coin against the good coin
          printf("{p}{good} < {coins[0]} -> {coins[0]}H")
          printf("{p}{good} = {coins[0]} -> #")
          printf("{p}{good} > {coins[0]} -> {coins[0]}L")
        else:
          k = (3**(n - 1) + 1) // 2
          (c1, c2, c3) = (coins[:k], coins[k:2 * k - 1], coins[2 * k - 1:])
          (left, right) = (c1, [good] + c2)
          printf("{p}{left} < {right}")
          solve_red_black(n - 1, c1, c2, 'L', 'H', p + '  ')
          printf("{p}{left} = {right}")
          solve_test_coin(n - 1, good, c3, p + '  ')
          printf("{p}{left} > {right}")
          solve_red_black(n - 1, c1, c2, 'H', 'L', p + '  ')
      
      
      # weigh (3^n - 3) / 2 suspect coins in n weighings
      def solve_general(n, coins, p=''):
        assert len(coins) == ((3**n) - 3) // 2
        # divide the coins into 3 piles
        k = len(coins) // 3
        (c1, c2, c3) = (coins[:k], coins[k:2 * k], coins[2 * k:])
        printf("{p}{c1} < {c2}")
        solve_red_black(n - 1, c1 + c3[:1], c2, 'L', 'H', p + '  ')  
        printf("{p}{c1} = {c2}")
        solve_test_coin(n - 1, c1[0], c3, p + '  ')
        printf("{p}{c1} > {c2}")
        solve_red_black(n - 1, c1 + c3[:1], c2, 'H', 'L', p + '  ')
        
      
      # number of weighings and problem type
      n = arg(3, 0, int, prompt="number of weighings")
      p = arg(2, 1, int, prompt="problem number")
      printf("[n={n}; p={p} (of 1-4)]")
      
      if p == 1:
        # solve the general case
        k = (3**n - 3) // 2
        if k > 0:
          printf("---\n{n} weighings finds the suspect coin from {k} coins\n---")
          solve_general(n, list(irange(1, k)))
      
      elif p == 2:
        # solve with a known good coin
        k = (3**n - 1) // 2
        printf("---\n{n} weighings finds the suspect coin from {k} coins, with an extra known good coin (0)\n---")
        solve_test_coin(n, 0, list(irange(1, k)))
      
      elif p == 3:
        # solve red/black
        k = 3**n
        j = (k + 1) // 2
        printf("---\n{n} weighings finds the suspect coin from {k} coins, where {j} of the coins are red and {j1} of the coins are black\nif the suspect coin is red it is heavier, if it is black it is lighter\n---", j1=j - 1)
        solve_red_black(n, list(irange(1, j)), list(irange(j + 1, k)))
      
      elif p == 4:
        # solve lighter
        k = 3**n
        printf("---\n{n} weighings finds the suspect lighter coin from {k} coins\n---")
        solve_lighter(n, list(irange(1, k)))
      

      Like

  • Unknown's avatar

    Jim Randell 4:25 pm on 20 March 2020 Permalink | Reply
    Tags:   

    Teaser 3000: The three thousandth 

    From The Sunday Times, 22nd March 2020 [link] [link]

    In this addition digits have been consistently replaced by letters, different letters representing different digits. But instead of an addition in base 10 in which the letters represent the digits 0 to 9 this is an addition in base 11, using X for the extra digit, in which the letters represent the digits 1 to X, with 0 unused.

    Please submit the number (still in base 11) represented by TEASER.

    Congratulations to The Sunday Times for publishing 3000 Teaser puzzles.

    [teaser3000]

     
    • Jim Randell's avatar

      Jim Randell 4:30 pm on 20 March 2020 Permalink | Reply

      We can use the [[ SubstitutedSum() ]] solver from the enigma.py library to solve this puzzle.

      The following run file executes in 126ms.

      Run: [ @replit ]

      #! python3 -m enigma -r
      
      SubstitutedSum
      
      --base="11"
      --digits="1-10"
      
      "THREE + THOUS + ANDTH = TEASER"
      

      Solution: TEASER = 12X523.

      There are two ways to assign values to the letters, as D and O are interchangeable:

      17322 + 17495 + X6817 = 12X523 / A=10 D=8 E=2 H=7 N=6 O=4 R=3 S=5 T=1 U=9
      17322 + 17895 + X6417 = 12X523 / A=10 D=4 E=2 H=7 N=6 O=8 R=3 S=5 T=1 U=9

      Like

      • Jim Randell's avatar

        Jim Randell 12:08 pm on 1 July 2023 Permalink | Reply

        Here is a faster solution using the [[ SubstitutedExpression.split_sum ]] solver from the enigma.py library.

        The internal runtime of this run file is 495µs.

        Run: [ @replit ]

        #! python3 -m enigma -rr
        
        SubstitutedExpression.split_sum
        
        --base="11"
        
        "{THREE} + {THOUS} + {ANDTH} = {TEASER}"
        
        --invalid="0,ADEHNORSTU"  # no 0 digits
        --code="base_digits('0123456789X')"  # use X for digit 10
        --answer="int2base({TEASER}, 11)"  # output solution in base 11
        

        Like

    • GeoffR's avatar

      GeoffR 1:48 pm on 21 March 2020 Permalink | Reply

      The teaser uses the 10 different letters ([T,H,R,E,O,U,S,A,N,D] in this teaser), which can convieniently represent the digits (1..10), as zero is not required,

      The programme produces a single solution with the third digit as 10 (or X), alltough there are two sets of digits, with values of O and D interchangeable.

      The programme uses the standard method of adding digits in columns, with carry digits to adjacent columns for column digit sums exceeding 11.

      % A Solution in MiniZinc
      include "globals.mzn";
      
      %    T H R E E
      %    T H O U S
      %    A N D T H
      %  -----------
      %  T E A S E R
      %  -----------
      
      % Using digits 1..10 in base 11
      var 1..10:T; var 1..10:H; var 1..10:R; var 1..10:E;
      var 1..10:O; var 1..10:U; var 1..10:S; var 1..10:A;
      var 1..10:N; var 1..10:D;
      
      constraint all_different ([T,H,R,E,O,U,S,A,N,D]);
      
      var 0..2: carry1; var 0..2: carry2; var 0..2: carry3;
      var 0..2: carry4; var 0..2: carry5;
      
      % Adding up digits in columns, starting from right side
      constraint (E + S + H) mod 11 == R 
      /\ carry1 == (E + S + H) div 11;
      
      constraint (E + U + T + carry1) mod 11 == E 
      /\ carry2 == (E + U + T + carry1) div 11;
      
      constraint (R + O + D + carry2) mod 11 == S 
      /\ carry3 == (R + O + D + carry2) div 11;
      
      constraint (H + H + N + carry3) mod 11 == A 
      /\ carry4 = (H + H + N + carry3) div 11;
      
      constraint (T + T + A + carry4) mod 11 == E 
      /\ carry5 == (T + T + A + carry4) div 11;
      
      constraint T == carry5;
      
      solve satisfy;
      
      output ["TEASER = " ++ show(T) ++ " " ++ show(E) ++ " " ++ show(A)
      ++ " " ++ show(S) ++ " " ++ show(E) ++ " " ++ show(R)  
      ++"\n" ++ "10 digits are [T,H,R,E,O,U,S,A,N,D] = " ++ show([T,H,R,E,O,U,S,A,N,D]) ];
      
      
      

      Like

  • Unknown's avatar

    Jim Randell 8:17 am on 17 March 2020 Permalink | Reply
    Tags: ,   

    Brainteaser 1798: Trisection 

    From The Sunday Times, 2nd March 1997 [link]

    We have taken a piece of paper in the shape of an equilateral triangle and folded it so that one of the corners lies at some point on the opposite side:

    In the figure triangle A has an area of 36 cm²  and triangle B has an area of 16 cm².

    What is the area of the unfolded piece of paper?

    This puzzle is included in the book Brainteasers (2002). The puzzle text above is taken from the book.

    [teaser1798]

     
    • Jim Randell's avatar

      Jim Randell 8:17 am on 17 March 2020 Permalink | Reply

      (See also: Enigma 1402).

      We note that triangles A and B are similar (they both have angles of (60°, θ, 120° − θ)).

      And their areas are in the ratio 36:16 = 6²:4², so their sides are in the ratio 6:4 = 3:2.

      We can label the sides of A as (3x, 3y, 3z) and of B as (2x, 2y, 2z).

      Looking at the base of the original triangle we see it has a length of: (2x + 3y)

      And so the the missing lengths on the other sides are: (3y − x) and (2x + y)

      But these are also the lengths of the remaining sides of triangles A and B, hence:

      (3y − x) / (2x + y) = 3 / 2
      6y − 2x = 6x + 3y
      3y = 8x

      So triangle A has sides of 3x and 8x, separated by an angle of 60°, and it has an area of 36, so:

      36 = (1/2)(3x)(8x)sin(60°)
      36 = 6x²√3
      x²√3 = 6

      And the base of the original triangle is 8x + 2x = 10x, so the total area is:

      T = (√3/4)(10x)²
      T = 25x²√3
      T = 25×6 = 150

      Hence:

      Solution: The area of the original triangle is 150 cm².

      Like

  • Unknown's avatar

    Jim Randell 4:56 pm on 13 March 2020 Permalink | Reply
    Tags:   

    Teaser 2999: Triangular card tower 

    From The Sunday Times, 15th March 2020 [link] [link]

    Robbie leans two very thin playing cards together, then another two together, placing an identical card across the top forming a platform, and proceeding sideways and upwards to build a roughly triangular tower.

    For the bottom layers, he uses a whole number of 53-card packs of large cards (integer length above 70mm), the number of packs equalling the number of bottom layers. He then uses small cards (75% size) to complete the tower, which is 1428mm high. The distance between the bases of two leaning cards is always 0.56 of the length of each card.

    Robbie would like to extend the tower sideways and upwards to the next possible integer height (measured in mm), still using large cards only for the bottom layers.

    How many extra cards would be needed in total?

    [teaser2999]

     
    • Jim Randell's avatar

      Jim Randell 5:49 pm on 13 March 2020 Permalink | Reply

      I assumed a classic “house of cards” construction, where the bottom layer has n triangular supports, each constructed from 2 cards, and (n − 1) horizontal cards bridging between the supports. Each higher layer has one fewer supports than the layer below it, until we reach the top, which is composed of a single triangular support. (See my comment below for a justification of this assumption).

      For the bottom layer, if there are n supports, that uses 2n cards, and then (n − 1) horizontal cards to make the platform for the next layer. In total it requires (3n − 1) cards.

      So the total number of cards required in a tower with n layers is:

      T(n) = n (3n + 1) / 2

      The supports are isosceles triangles. If the length of card is x, and the base of the support is 0.56x across, then the height of the support is 0.96x.

      The cards are described as “very thin”, which I am assuming means they have zero thickness (even when multiple cards are measured).

      This makes the height of a tower with n layers, of which the top m layers are constructed with cards that are 75% smaller as:

      H(n, m) = 0.96x ((n − m) + 0.75m)
      H(n, m) = 0.24x (4n − m)

      And in the first tower this total height is 1428 mm. Giving:

      (4n − m) x = 5950

      So the height of the larger cards is a divisor of 5950, and we are told it is greater than 70.

      This Python program runs in 76ms.

      Run: [ @repl.it ]

      from enigma import (divisors_pairs, irange, inf, div, printf)
      
      # consider the length of the larger cards
      for (x, d) in divisors_pairs(5950, every=1):
        if not (x > 70): continue
      
        # consider the number of top rows m
        # and the total number of rows n
        for m in irange(1, inf):
          (n, r) = divmod(d + m, 4)
          if not (n > m): break
          if r != 0: continue
      
          # the total number of cards required (for the n rows)
          t = n * (3 * n + 1) // 2
          # the number of smaller cards required (for the top m rows)
          s = m * (3 * m + 1) // 2
          # and so the number of larger cards required (for the bottom n-m rows)
          b = t - s
          # the number of 53 card packs used is equal to the number of bottom rows
          if 53 * (n - m) != b: continue
      
          printf("x={x} -> m={m} n={n}; t={t} s={s} b={b}")
      
          # start adding k extra rows, counting the additional cards
          a = 0
          for k in irange(1, inf):
            # add 3 cards for each bottom row
            a += 3 * (n - m)
            # and 3 cards for each top row, plus 2 for the new top
            a += 3 * (m + k) - 1
            # calculate the new height
            h = div(6 * x * (4 * n + 3 * k - m), 25)
            # is it an integer?
            if h is not None:
              printf("-> additional cards = {a} [k={k} h={h}]")
              break
      

      Solution: 355 extra cards are required.

      The larger cards are 85 mm long (so the smaller cards are 63.75 mm long).

      The original tower consisted of 21 layers. The top 14 layers being built using the smaller cards.

      This requires 672 cards in total. 301 smaller cards are required, and 371 larger cards (= 7× 53).

      Adding 5 extra layers to the tower requires 105 larger cards (1 short of 2 extra packs), and 250 smaller cards. Making the total number of extra cards required 355.

      The height of the new tower is 1734 mm.


      Analytically:

      If n is the total number of layers in the tower (= the number of supports in the base layer), and m is the number of layers of smaller cards (so: m < n), then the requirement that the number of packs of larger cards used is the same as the number larger layers is:

      53(n − m) = T(n) − T(m)
      ⇒ 106(n − m) = 3(n² − m²) + (n − m)
      ⇒ 106 = 3(n + m) + 1
      ⇒ n + m = 35

      This gives us a limited number of (n, m) pairs.

      Then considering values for x:

      x = 5950 / (4n − m)
      ⇒ x = 5950 / (5n − 35)
      ⇒ x = 1190 / (n − 7)

      And given that x > 70, this narrows (n, m, x) down to a single value, which defines the initial tower.

      We then want to know how many lots of 0.72x we need to get an integer number of millimetres height increase.

      And this gives us the number of extra oblique columns we need to add to the initial tower, and from this we can calculate the number of extra cards required.

      All this can easily be tackled manually, or here is a quick program which looks at the possibilities:

      from enigma import (divisors_pairs, irange, div, printf)
      
      # consider possible card sizes
      for (n, x) in divisors_pairs(1190):
        if not (x > 70): break
        # calculate n and m
        n += 7
        m = 35 - n
        if not (n > m): continue
      
        # how many extra obliques to add?
        for k in irange(1, 25):
          h = div(18 * x * k, 25) 
          if h is None: continue
          # calculate the additional number of cards
          a = k * (3 * k + 6 * n + 1) // 2
          printf("x={x} n={n} m={m} -> k={k} h={h} a={a}")
          break
      

      Like

    • Jim Randell's avatar

      Jim Randell 4:45 pm on 15 March 2020 Permalink | Reply

      Here is a diagram of the solution found by my program, which assumes that each layer has one fewer supports than the layer below it.

      However, if the spacing of the supports is constant, then the result is only “very roughly triangular”:

      I also looked for a solution where a more “roughly triangular” shape is maintained, but this means that number of supports on the bottom layer of the smaller cards does not necessarily have one fewer supports than the layer of larger cards it is resting on (it will probably have more supports).

      And I did find a solution:

      However it does require the wording “layers” and “packs” in the puzzle text to include the possibility of a single layer and a single pack.

      I think that my original solution is probably the one the setter is looking for.


      In the original solution we can narrow the gaps between the supports in the lower part of the tower, and widen them in the upper part of the tower, to get a “roughly pentagonal” shape that is perhaps closer to the “rough triangle” that the setter is looking for. (Although applying it to the second solution would make it look even more triangular).

      Here is the first solution rendered with altered spacing (but still constant within the sections):

      And by varying the spacing within the sections it should be possible to reduce the kink in the oblique sides of the triangle, and possibly even eliminate it completely.

      In fact the idea of varying the spacing opens up the possibility of many more possible towers where the number of supports in bottom layer of smaller cards is not one less than the number of supports in the top layer of the larger cards. (Or even violating this rule within a section). So I think it makes sense to restrict the towers considered to those where the number of supports decreases by one from the layer below.

      Like

  • Unknown's avatar

    Jim Randell 9:17 am on 12 March 2020 Permalink | Reply
    Tags:   

    Brain-Teaser 515: [Herb gardens] 

    From The Sunday Times, 25th April 1971 [link]

    Five little girls wanted herb gardens. Mother gave them five kinds and said:

    “There are three clumps of each sort. Now each take three clumps, but so that you have three different kinds in your garden, and so that not one of you has the same three as anyone else.”

    Anne now has two the same as Eve, whose third is common to Beth and Carol. Carol has two the same as Beth, but not the parsley, which Beth has. Dot has mint, and shares two others with Anne. Eve didn’t really like any of Dot’s choice, but they have to share the one Beth and Carol don’t have. Dot doesn’t have rue, and only one person has rue with mint, and one with parsley and thyme.

    Who had sage and who had thyme?

    This puzzle was originally published with no title.

    [teaser515]

     
    • Jim Randell's avatar

      Jim Randell 9:18 am on 12 March 2020 Permalink | Reply

      Programatically, we can try all possible assignments of selections of herbs to the girls.

      This Python program runs in 94ms.

      Run: [ @repl.it ]

      from enigma import subsets, join, printf
      
      # possible choices
      ss = list(map(set, subsets("MPRST", size=3, select="C")))
      
      # choose different sets for each of the girls
      for (A, B, C, D, E) in subsets(ss, size=5, select="P"):
      
        # A does not have M
        # B has P
        # C does not have P
        # D has M, does not have R
        if 'M' in A or 'P' not in B or 'P' in C or 'M' not in D or 'R' in D: continue
      
        # A has 2 the same as E
        AnE = A.intersection(E)
        if len(AnE) != 2: continue
      
        # and E's other one is common to B and C
        # B and C share 2
        BnC = B.intersection(C)
        if len(BnC) != 2: continue
        EdA = E.difference(A)
        if not EdA.issubset(BnC): continue
      
        # A and D share 2
        AnD = A.intersection(D)
        if len(AnD) != 2: continue
      
        # D and E share 1, and neither B nor C have it
        DnE = D.intersection(E)
        if len(DnE) != 1 or DnE.issubset(B.union(C)): continue
        
        # only one has M+R, only one has P+T
        count = lambda s: sum(x.issuperset(s) for x in (A, B, C, D, E))
        if not(count('MR') == 1 and count('PT') == 1): continue
      
        # output solutions
        collect = lambda k: join(x for (x, s) in zip("ABCDE", (A, B, C, D, E)) if k in s)
        (A, B, C, D, E) = (join(sorted(x)) for x in (A, B, C, D, E))
        printf("A={A} B={B} C={C} D={D} E={E} -> S={S} T={T}", S=collect('S'), T=collect('T'))
      

      Solution: Anne, Dot, Eve have sage. Beth, Carol, Eve have thyme.

      There are two possible sets of herbs (B has a choice of two different selections):

      A: PRS
      B: MPT / PRT
      C: MRT
      D: MPS
      E: RST

      Like

  • Unknown's avatar

    Jim Randell 8:13 am on 10 March 2020 Permalink | Reply
    Tags:   

    Brainteaser 1791: Untied problem 

    From The Sunday Times, 12th January 1997 [link]

    Here is an exact long division sum. In some places digits have been consistently replaced by letters, with different letters used for different digits. In all other places the digits have been replaced by asterisks.

    Untie this and find UNTIED.

    This puzzle is included in the book Brainteasers (2002). The puzzle text above is taken from the book and differs slightly from the original puzzle.

    [teaser1791]

     
    • Jim Randell's avatar

      Jim Randell 8:13 am on 10 March 2020 Permalink | Reply

      We can use the [[ SubstitutedDivision() ]] solver from the enigma.py library to solve this puzzle.

      The following run file executes in 147ms.

      Run: [ @repl.it ]

      #!/usr/bin/env python -m enigma -r
      
      SubstitutedDivision
      
      "UNTIED / JIM = ADAM"
      
      "UNT - ??? = ??"
      "??? - ??? = ??"
      "??? - ??D = ??"
      "??? - ??? = 0"
      
      --answer="UNTIED"
      

      Solution: UNTIED = 986304.

      The correct division sum is: 986304 ÷ 132 = 7472.

      Like

    • GeoffR's avatar

      GeoffR 6:32 pm on 10 March 2020 Permalink | Reply

      
      from itertools import permutations
      
      for P in permutations('1234567890', 9):
          j, i, m, u, n, t, e, d, a = P
      
          # leading digits must not be zero
          if j == '0' or a =='0'or u == '0': continue
          jim = int(j + i + m)
          untied = int(u + n + t + i + e + d)
          adam = int(a + d + a + m)
          if jim * adam == untied:
              
              # check the lone 'D' position is correct
              if (int(a) * jim) % 10 == int(d):
                print (f"Sum is {untied} / {jim} = {adam}")
                
      # Sum is 986304 / 132 = 7472
      
      # There are only two solutions to the main division sum:
      # 986304 / 132 = 7472
      # and 785601 / 369 = 2129
      
      # Checking the lone 'D' digit position is enough to eliminate the
      # second solution ie 785601 / 369 =  2129. The last line of the
      # second solution also has 4 digits, instead of 3 digits.
      # It ran in 112 msec.
      
      
      

      Like

c
Compose new post
j
Next post/Next comment
k
Previous post/Previous comment
r
Reply
e
Edit
o
Show/Hide comments
t
Go to top
l
Go to login
h
Show/Hide help
shift + esc
Cancel
Design a site like this with WordPress.com
Get started