Updates from Jim Randell Toggle Comment Threads | Keyboard Shortcuts

  • Unknown's avatar

    Jim Randell 9:11 am on 1 October 2019 Permalink | Reply
    Tags:   

    Brain-Teaser 503: [Exam marks] 

    From The Sunday Times, 31st January 1971 [link]

    When the headmaster came to look up Charley’s marks in the previous term’s exam in Physics and Chemistry, sat by the Science pupils of the 6th (Al, Bill, Charley, Dan, Ed, Frank and George) he found that ink had been spilt on the results sheet and only the following was legible:

    He remembered that the pupils finished in alphabetical order in total marks; that there were no ties in either subject, or overall; and that no pupil occupied the same place in each subject.

    All that he could remember about Charley’s results was that he was placed higher in Chemistry than in Physics.

    What were Charley’s marks in each subject?

    This puzzle was originally published with no title.

    [teaser503]

     
    • Jim Randell's avatar

      Jim Randell 9:13 am on 1 October 2019 Permalink | Reply

      I assumed the exams are marked out of 100, and only whole numbers of marks are awarded.

      I made a MiniZinc model for the puzzle. It finds a single solution in 121ms.

      %#! minizinc --solver chuffed --all
      
      include "globals.mzn";
      
      % label the boys
      set of int: Boys = 1..7;
      int: A = 1;
      int: B = 2;
      int: C = 3;
      int: D = 4;
      int: E = 5;
      int: F = 6;
      int: G = 7;
      
      % places for each boy in each subject
      array [Boys] of var 1..7: pPh;
      array [Boys] of var 1..7: pCh;
      
      constraint all_different(pPh);
      constraint all_different(pCh);
      
      % marks for each boy in each subject
      array [Boys] of var 0..100: mPh;
      array [Boys] of var 0..100: mCh;
      
      constraint forall (x, y in Boys where x != y) ((pPh[x] < pPh[y]) -> (mPh[x] > mPh[y]));
      constraint forall (x, y in Boys where x != y) ((pCh[x] < pCh[y]) -> (mCh[x] > mCh[y]));
      
      % given values
      constraint pPh[A] = 5;
      constraint pCh[B] = 2;
      constraint pPh[E] = 3;
      constraint pCh[G] = 5;
      constraint mPh[D] = 70;
      constraint mCh[F] = 67;
      constraint mPh[G] = 71;
      
      % total marks is 1023
      constraint sum (x in Boys) (mCh[x] + mPh[x]) = 1023;
      
      % "the pupils finished in alphabetical order by total marks"
      constraint decreasing (x in Boys) (mPh[x] + mCh[x]);
      
      % "there were no ties in either subject, or overall"
      constraint all_different(mPh);
      constraint all_different(mCh);
      constraint all_different (x in Boys) (mPh[x] + mCh[x]);
      
      % "no pupil occupied the same place in both subjects"
      constraint forall (x in Boys) (pPh[x] != pCh[x]);
      
      % "C placed higher in Chemistry than Physics"
      constraint pCh[C] < pPh[C];
      
      solve satisfy;
      

      Solution: Charley got 73% in Physics and 75% in Chemistry.

      Here is the complete table:

      Like

  • Unknown's avatar

    Jim Randell 11:58 am on 30 September 2019 Permalink | Reply
    Tags:   

    Teaser 2842: The best policy 

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

    George and Martha’s home insurance policy number is a six-figure number consisting of six different digits. George commented that the number was divisible by each of its digits and also by the sum of its digits. Martha then added that, if you deleted the left-hand digit, then you were left with a five-figure number divisible by the sum of its five digits. If you then deleted that number’s left-hand digit, then you were left with a four-figure number divisible by the sum of its four digits, and so on all the way down.

    What is their policy number?

    [teaser2842]

     
    • Jim Randell's avatar

      Jim Randell 11:59 am on 30 September 2019 Permalink | Reply

      Using copy and paste we can easily make the expressions to feed to the [[ SubstitutedExpression() ]] solver from the enigma.py library.

      The following run file executes in 70ms. (Internal run time of the generated program is 132us).

      Run: [ @replit ]

      #! python -m enigma -rr
      
      # suppose the number is: ABCDEF
      
      SubstitutedExpression
      
      --digits="1-9"
      --answer="ABCDEF"
      
      "ABCDEF % A = 0"
      "ABCDEF % B = 0"
      "ABCDEF % C = 0"
      "ABCDEF % D = 0"
      "ABCDEF % E = 0"
      "ABCDEF % F = 0"
      "ABCDEF % (A + B + C + D + E + F) = 0"
      "BCDEF % (B + C + D + E + F) = 0"
      "CDEF % (C + D + E + F) = 0"
      "DEF % (D + E + F) = 0"
      "EF % (E + F) = 0"
      
      --template="ABCDEF"
      

      Solution: The policy number is 384912.


      I also coded up a custom program for this particular problem.

      It runs in 34ms (with an internal run time of 152µs). So the program produced by the [[ SubstitutedExpression ]] solver executes faster than my custom program:

      # permissible digits (0 is disallowed as n % 0 is undefined)
      digits = range(1, 10)
      
      # find <k> digit numbers such that each suffix is divisible by the sum
      # of the digits in that suffix and the number is divisible by each of
      # it's digits individually.
      def solve(k, n=0, s=0, ds=[]):
        # are we done?
        if k == 0:
          # check for divisibility by all the digits individually
          if all(n % d == 0 for d in ds):
            print(n)
        else:
          # add a new digit to the front
          for d in digits:
            if d not in ds:
              ds1 = [d] + ds
              n1 = n + d * 10**len(ds)
              s1 = s + d
              if n1 % s1 == 0:
                # and solve for the remaining digits
                solve(k - 1, n1, s1, ds1)
      
      # we need 6 digit numbers
      solve(6)
      

      We can however use this program to investigate numbers of different lengths, and we find that 6 is the maximum possible length.

      Like

  • Unknown's avatar

    Jim Randell 5:04 pm on 29 September 2019 Permalink | Reply
    Tags:   

    Brainteaser 1721: Prime leaps 

    From The Sunday Times, 10th September 1995 [link]

    The history-cum-maths teacher asked the class to name some years which the knew from history lessons. Johnny named 1066, the Battle of Hastings, and 1939, the outbreak of the Second World War. The teacher then asked him to calculate the difference between the two and Johnny got the correct answer of 873.

    The teacher then asked Johnny if this difference was prime and Johnny answered correctly that it was not because, for example, it was divisible by three.

    The teacher then asked the class to find the longest list of years they could from 0, 1, 2, …, 1999, 2000 so that for any two numbers in the list their difference was not prime.

    Which numbers are in the longest such list?

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

    [teaser1721]

     
    • Jim Randell's avatar

      Jim Randell 5:05 pm on 29 September 2019 Permalink | Reply

      First, lets treat the list as a sequence of consecutive integers starting at 0. (We’re only interested in differences, so it doesn’t really matter where we start).

      If we consider the set of numbers (0, 4, 8, 12, 16, …) (i.e. the multiples of 4) then we see the difference between any two numbers is also a multiple of 4, and hence not prime. This allows us to select ⌈n / 4⌉ numbers from a sequence of n numbers.

      And this is the best we can manage. Every segment of size 4 has 1 number (and if there is a shorter segment left over from chopping the sequence into fours, then that also has one number).

      To do better we would have to have a segment of size 4 with (at least) two numbers in it.

      We can’t have … 0 _ 2 _ … or … 0 _ _ 3 … as these have a difference of 2 and 3 respectively, so the only possible segment is … 0 1 _ _ ….

      But any numbers that differ by 1 have to be followed by (or preceded by) 7 gaps:

      So the best we could manage is 2 numbers out of every 9, which is worse than 1 out of every 4.

      So presented with a sequence of 2001 numbers the best we can manage is ⌈2001 / 4⌉ = 501 numbers: (0, 4, 8, 12, 16, …, 1992, 1996, 2000).

      Solution: The longest list contains all exact multiples of 4.

      Considered as years (ignoring the fact that there was no year 0), most of the numbers represent leap years, hence the title of the puzzle.

      Like

    • Lise Andreasen's avatar

      Lise Andreasen 12:18 pm on 5 August 2024 Permalink | Reply

      Elegant.

      Like

  • Unknown's avatar

    Jim Randell 6:14 pm on 27 September 2019 Permalink | Reply
    Tags:   

    Teaser 2975: Hollow cube land 

    From The Sunday Times, 29th September 2019 [link] [link]

    I have a large box of toy building bricks. The bricks are all cubes (the same size), and can be pushed together then dismantled.

    I decided to build the largest cube possible by leaving out all the interior bricks. When my hollow cube was finished I had two bricks left over. I put all the bricks back in the box and gave it to my two children. Each in turn was able to use every brick in the box to construct two hollow cubes, again with all interior bricks removed. Their cubes were all different sizes.

    This would not have been possible had the box contained any fewer bricks.

    How many bricks were in the box?

    [teaser2975]

     
    • Jim Randell's avatar

      Jim Randell 6:57 pm on 27 September 2019 Permalink | Reply

      For n ≥ 2 we can calculate the “hollow cube” number as:

      h(n) = n³ − (n − 2)³ = 6(n − 1)² + 2

      We can then check for values where it is possible to make h(n) + 2 from the sum of two smaller h() numbers, in (at least) two different ways.

      This Python 3 program runs in 81ms.

      Run: [ @replit ]

      from enigma import (irange, inf, subsets, printf)
      
      # "hollow cube" numbers (n >= 2)
      h = lambda n: 6 * (n - 1)**2 + 2
      
      # solve the puzzle using formula for h(n)
      def solve():
        d = dict()
        for n in irange(3, inf):
          # calculate h(n)
          x = h(n)
          printf("[h({n}) = {x}]")
          # can x + 2 be made from the sum of 2 smaller h numbers?
          ss = list(s for s in subsets(d.keys(), size=2) if sum(d[k] for k in s) == x + 2)
          # in 2 different ways?
          if len(ss) > 1:
            printf("t={t} [n={n} x={x}, ss={ss}]", t=x + 2)
            return
          # add the number to the list
          d[n] = x
      
      solve()
      

      Solution: There were 3754 bricks in the box.

      The setter was able to build a hollow cube measuring 26 units along each side, using up 3752 of the bricks (leaving 2 unused).

      One child produced cubes measuring 8 and 25 units along each side, using up 296 + 3458 = 3754 bricks.

      The other child produced cubes measuring 16 and 21 units along each side, using up 1352 + 2402 = 3754 bricks.


      Analytically:

      We are looking for numbers p, q such that:

      6(n − 1)² + 4 = 6(p − 1)² + 2 + 6(q − 1)² + 2
      (n − 1)² = (p − 1)² + (q − 1)²

      So we can look for Pythagorean triples that share a hypotenuse. The smallest is:

      25² = 7² + 24² = 15² + 20²

      from which we see the setter’s cube measured 26 units, and the children’s were (8, 25) units and (16, 21) units.

      For more than 2 children the smallest solution is with 25354 bricks. The setter built a cube measuring 66 units, and there can be up to 4 children with cubes measuring (17, 64), (26, 61), (34, 57), (40, 53) units. Corresponding to:

      65² = 16² + 63² = 25² + 60² = 33² + 56² = 39² + 52²

      Like

  • Unknown's avatar

    Jim Randell 10:54 am on 27 September 2019 Permalink | Reply
    Tags: ,   

    Brain-Teaser 502: [Duplicated leaves] 

    From The Sunday Times, 17th January 1971 [link]

    A publisher friend of mine told me the following improbable story. He dreamt that on his shelves he had a collection of twelve books of the same edition of the same title. The curious thing about these books was this:

    The book, as published, ran to 300 pages, but eleven of the books on his shelves had each been bound with duplicate leaves inserted. The number of leaves thus duplicated was different in each volume, all except two being even numbers. They went in ascending order from the book on the left (Volume I), the highest being twenty extra leaves in Volume XI.

    The end book on the right (Volume XII) had 200 pages missing. By a strange coincidence, the duplicated sections from the other volumes exactly filled these gaps. In the reconstituted Volume XII the middle pages (143 to 158) came from the middle volume of the faulty books, while half the duplicated pages came before these and an equal number in the latter half of the volume.

    How many pages were duplicated in Volume IV?

    This puzzle was originally published with no title.

    [teaser502]

     
    • Jim Randell's avatar

      Jim Randell 10:55 am on 27 September 2019 Permalink | Reply

      Assuming that 1 “leaf” consists of 2 “pages” (the “front” (odd numbered) page and “back” (even numbered) page).

      We know vol XII has 200 missing pages (= 100 missing leaves), and each is accounted for (exactly) by the duplicate leaves in vols I – XI.

      Of the 100 duplicate leaves vol XI has 20 of them, so the remaining volumes have 80 duplicate leaves between them.

      This Python program examines this scenario. It runs in 104ms.

      from enigma import (irange, printf)
      
      # decompose total t into k different ascending numbers, min value m
      def decompose(t, k, m=1, s=[]):
        if k == 1:
          if not (t < m):
            yield s + [t]
        else:
          for x in irange(m, t - (k - 1) * m):
            yield from decompose(t - x, k - 1, x + 1, s + [x])
      
      # there are 80 extra leaves amongst vols I - X
      for vs in decompose(80, 10, 1):
        # vol VI has (at least) 8 extra leaves
        if vs[5] < 8: continue
        # and vol XI has exactly 20 extra leaves
        if vs[-1] > 19: continue
        vs.append(20)
      
        # exactly 2 are odd
        if not (sum(x % 2 == 1 for x in vs) == 2): continue
      
        # output the number of duplicate leaves for each volume
        printf("{vs}")
      

      This seems to give 4 possibilities for the numbers of duplicate leaves:

      [1, 2, 3, 4, 6, 8, 10, 12, 16, 18, 20]
      [1, 2, 4, 5, 6, 8, 10, 12, 14, 18, 20]
      [1, 2, 4, 6, 7, 8, 10, 12, 14, 16, 20]
      [2, 3, 4, 5, 6, 8, 10, 12, 14, 16, 20]

      If we’d been asked for the number of duplicate leaves (or pages) in vols VII or VIII there would be a unique solution (10 leaves for vol VII; 12 leaves for vol VIII), but not for vol IV (we have options for 4, 5, 6 duplicate leaves).

      So we need to try an untangle the condition:

      “In the reconstituted Volume XII the middle pages (143 to 158) came from the middle volume of the faulty books, while half the duplicated pages came before these and an equal number in the latter half of the volume.”

      So vol VI must have (at least) 8 duplicate leaves. Which it does in each of our possibilities, so that doesn’t help us.

      The rest of it either doesn’t make sense, or doesn’t seem to be useful.

      “half the duplicate pages” is 50 leaves, so 50 of the duplicate leaves end up making up some of pages 1-142 of vol XII.

      It then goes on to say “and an equal number” (presumably another 50 leaves) “in the latter half of the volume” (presumably pages 151-300), which seems to account for 104 of the 100 missing leaves. So that can’t be right.

      Perhaps it meant “…half the remaining duplicated pages…”, but that just tells us that 46 of the duplicate leaves are used for pages 1-142, and the other 46 are used for pages 159-300, which as we have 92 duplicate leaves to distribute doesn’t seem to help either.

      Another possibility is to ignore the final condition, and take a strict reading of “eleven of the books on his shelves had each been bound with duplicate leaves inserted”, to mean that each book has at least 2 duplicate leaves. This removes the first 3 of the possibilities, leaving:

      I→2, II→3, III→4, IV→5, V→6, VI→8, VII→10, VIII→12, IX→14, X→16, XI→20

      As the only remaining solution, so vol IV has 5 duplicate leaves, and hence 10 duplicate pages. (Which is the published solution).

      We can modify line 13 of the program to [[ decompose(80, 10, 2) ]] to get this single solution.

      Like

  • Unknown's avatar

    Jim Randell 8:46 am on 24 September 2019 Permalink | Reply
    Tags:   

    Teaser 2848: Coffee breaks 

    From The Sunday Times, 23rd April 2017 [link] [link]

    The roads on our estate form a grid consisting of three roads running west-to-east with a number of other roads running south-to-north from the bottom road across the middle road to the top road. I live at the south-west corner of the grid and I work at the north-east corner. Each day I walk to work by one of the various shortest possible routes along the roads: there is a two-figure number of such routes. One quarter of my possible routes pass Caffee Claudius, and one quarter of my routes pass Spenda Coffee (which are on different roads).

    How many of my routes pass both the coffee shops?

    [teaser2848]

     
    • Jim Randell's avatar

      Jim Randell 8:47 am on 24 September 2019 Permalink | Reply

      I considered coffee shops that are located somewhere on the roads between the intersection points of the grid. (If we consider coffee shops at the intersections there are no solutions where the two shops are not on the same road).

      This Python 3 program constructively generates the possible paths in a grid, and then looks for segments of the paths that appear in exactly one quarter of a possible paths. We then select two of these segments for the positions of the coffee shops and count how many paths include both the segments. It runs in 76ms.

      Run: [ @repl.it ]

      from enigma import (irange, inf, div, multiset, tuples, subsets, contains, seq_all_same, printf)
      
      # generate paths from (0, 0) to (x, y)
      def paths(x, y, s=[]):
        if x == y == 0:
          yield [(0, 0)] + s
        else:
          if x > 0: yield from paths(x - 1, y, [(x, y)] + s)
          if y > 0: yield from paths(x, y - 1, [(x, y)] + s)
      
      y = 2
      for x in irange(1, inf):
      
        # the total number of different routes
        ps = list(paths(x, y))
        t = len(ps) # t = C(x + y, y)
        if t < 10: continue
        if t > 99: break
      
        q = div(t, 4)
        if q is None: continue
      
        printf("[x={x} y={y}] t={t}, q={q}")
      
        # count the number of paths that use each of the line segments on the grid
        segs = multiset.from_seq(*(tuples(p, 2) for p in ps))
      
        # find segments that appear q times
        qs = list(k for (k, v) in segs.items() if v == q)
        printf("-> qs={qs}")
      
        # choose two of them
        for (q1, q2) in subsets(qs, size=2):
          # that don't lie on the same road
          if any(seq_all_same(x) for x in zip(*(q1 + q2))): continue
          # and count the paths that include both segments
          n = sum((contains(p, q1) != -1 and contains(p, q2) != -1) for p in ps)
          printf("-> n={n} [q1={q1} q2={q2}] (*** SOLUTION ***)")
      

      Solution: Only one route passes both coffee shops.

      There are 7 N-S roads.

      (The coffee shops are indicated by stars. The single route is shown in red).

      The number of routes on an x by y grid is given by: C(x + y, x), or C(x + y, y).

      In this case y = 2, so x must be in the the range 3 … 12 in order for the number of routes to be a 2-digit number.

      For the number of routes to be exactly divisible by 4 we must have x = 6 or 7.

      If x = 7 the number of routes is 36, and there are no segments that are used in exactly 36/4 = 9 shortest routes.

      If x = 6 the number of routes is 28, and only the two vertical segments shown in red on the diagram have 28/4 = 7 shortest routes using them. So these give the locations of the coffee shops, and there is only one shortest route that uses both of them together.

      If we require the coffee shops to be at intersections, then we find the only possible positions are shops at (0, 1) and (6, 1), but these both lie on the y = 1 road, so does not provide a viable solution. Although potentially it does allow a solution where one of the coffee shops is at one of these intersections, and the other one is on a segment between intersections, but it doesn’t change the answer to the puzzle.

      The restriction on there being a 2-digit number of shortest paths limits the range of x to a small number of values, but even without this restriction I didn’t find any further candidate solutions (with segments lying on one quarter of the total number of paths) for x up to 5000.

      However there are further candidate locations if the coffee shops are allowed on the intersections. For example with x = 47 we could have shops at (6, 1), (41, 1), and with x = 286 we could have shops at (41, 1), (245, 1), and with x = 1679 we could have shops at (245, 1), (1434, 1). However when choosing 2 shops these all fall foul of the condition that that the shops be on different roads, so don’t provide viable solutions.

      Like

      • Jim Randell's avatar

        Jim Randell 4:49 pm on 24 September 2019 Permalink | Reply

        Here is a modified version of the program that allows the coffee shops to be on the segments between intersections or at the intersections themselves. Instead of constructing the paths it uses the formula C(x + y, x) to count the number of paths. The answer to the puzzle is the same, however.

        Run: [ @repl.it ]

        from enigma import (cproduct, multiply, C, irange, inf, div, subsets, seq_all_same, printf)
        
        # count the number of paths along a sequence of segments
        paths = lambda *ps: multiply(C(x + y, x) for (x, y) in ps)
        
        # grid segment between two points
        def seg(p, q):
          ((px, py), (qx, qy)) = (p, q)
          return (qx - px, qy - py)
        
        y = 2
        for x in irange(1, inf):
        
          # the total number of different routes
          t = paths((x, y))
          if t < 10: continue
          if t > 99: break
        
          q = div(t, 4)
          if q is None: continue
        
          printf("[x={x} y={y}] t={t}, q={q}")
        
          # count the number of paths that use each of the line segments and nodes on the grid
          qs = list()
          for (i, j) in cproduct([irange(0, x), irange(0, 2)]):
            # line segment N
            if j < 2 and paths((i, j), seg((i, j + 1), (x, y))) == q:
              qs.append(((i, j), (i, j + 1)))
            # line segment E
            if i < x and paths((i, j), seg((i + 1, j), (x, y))) == q:
              qs.append(((i, j), (i + 1, j)))
            # node
            if paths((i, j), seg((i, j), (x, y))) == q:
              qs.append(((i, j),))
        
          printf("-> qs={qs}")
        
          # choose two of them
          for (q1, q2) in subsets(qs, size=2):
            # that don't lie on the same road
            if any(seq_all_same(x) for x in zip(*(q1 + q2))): continue
            # and count the paths that include both segments
            n = paths(q1[0], seg(q1[-1], q2[0]), seg(q2[-1], (x, y)))
            printf("-> n={n} [q1={q1} q2={q2}] (*** SOLUTION ***)")
        

        One shop is on the line (0, 0) – (0, 1) and the other is on the line (6, 1) – (6, 2), all locations are acceptable apart from (0, 1) together with (6, 1), as then the shops are both on the y = 1 road.

        Like

  • Unknown's avatar

    Jim Randell 12:05 am on 21 September 2019 Permalink | Reply
    Tags:   

    Teaser 2974: Flockbuster 

    From The Sunday Times, 22nd September 2019 [link] [link]

    Wu, Xi, Yo and Ze had different two-figure numbers of sheep and kept them in a walled field divided by fences into a fold each. Maths whizz, Wu, with the largest flock, noticed that together her flock and Ze’s equalled Xi’s and Yo’s combined; and that, as a fraction, the ratio of Yo’s flock to Xi’s had consecutive upper and lower numbers (e.g. 3/4), whereas her flock to Xi’s ratio had those numbers swapped over (e.g. 4/3).

    Overnight, storm-damaged fences led to the same number of sheep in each fold. Wu’s old maths teacher, told just this number and the above relationships, couldn’t be certain how many sheep Wu owned (which would have been true, also, if he’d been told either fraction instead).

    How many sheep did Wu own?

    [teaser2974]

     
    • Jim Randell's avatar

      Jim Randell 12:07 am on 21 September 2019 Permalink | Reply

      This Python program considers possible values for X and Y, from which the values of W and Z (and k) can be derived. It runs in 88ms.

      Run: [ @replit ]

      from enigma import (irange, subsets, div, filter_unique, unpack, intersect, printf)
      
      # collect possible solutions
      rs = list()
      
      # choose X and Y (Y < X)
      for (Y, X) in subsets(irange(10, 99), size=2):
      
        # Y / X can be expressed as k / (k + 1)
        k = div(Y, X - Y) 
        if k is None: continue
      
        # X / W can be expressed as (k + 1) / k
        W = div((k + 1) * X, k)
        if W is None or not (X < W < 100): continue
      
        # W + Z = X + Y
        Z = X + Y - W
        if (not 9 < Z < W) or Z == Y or Z == X: continue
      
        # total number of sheep must be divisible by 4
        t = W + X + Y + Z
        if t % 4 != 0: continue
      
        rs.append((W, X, Y, Z, k, t))
        printf("[Y={Y} X={X}, k={k}, W={W} Z={Z}, t={t}]")
      
      # the total is ambiguous
      (_, rs1) = filter_unique(rs, unpack(lambda W, X, Y, Z, k, t: t))
      
      # the fraction is also ambiguous
      (_, rs2) = filter_unique(rs, unpack(lambda W, X, Y, Z, k, t: k))
      
      # but together these tell us W
      rs = intersect((rs1, rs2))
      ws = set(W for (W, X, Y, Z, k, t) in rs)
      printf("W = {ws} [{rs}]")
      

      Solution: Wu owns 99 sheep.

      There are 12 possible values for W, X, Y, Z that fit the description. Here they are are by the total number of sheep, and the value of k, the numerator of the fraction:

      [ 1] t=72 k=4, W=25 Z=11, X=20 Y=16
      [ 2] t=84 k=3, W=32 Z=10, X=24 Y=18
      [ 3] t=144 k=4, W=50 Z=22, X=40 Y=32
      [ 4] t=156 k=6, W=49 Z=29, X=42 Y=36
      [ 5] t=168 k=3, W=64 Z=20, X=48 Y=36
      [ 6] t=200 k=2, W=90 Z=10, X=60 Y=40
      [ 7] t=216 k=4, W=75 Z=33, X=60 Y=48
      [ 8] t=220 k=5, W=72 Z=38, X=60 Y=50
      [ 9] t=220 k=2, W=99 Z=11, X=66 Y=44
      [10] t=252 k=3, W=96 Z=30, X=72 Y=54
      [11] t=272 k=8, W=81 Z=55, X=72 Y=64
      [12] t=312 k=6, W=98 Z=58, X=84 Y=72

      We see that the total number of sheep is only ambiguous when t = 220 (cases 8, 9). So the teacher can narrow down the situation to one of those two cases (all other values of t uniquely identify a single case).

      And the value of k is ambiguous when:

      k = 2 (cases 6, 9)
      k = 3 (cases 2, 5, 10)
      k = 4 (case 1, 3, 7)
      k = 6 (cases 4, 12)

      And case 9 is the only one common to both scenarios so this is the required solution: W=99 Z=11, X=66 Y=44.

      So W + Z = X + Y = 110 and Y/X = X/W = 2/3.

      Like

      • Jim Randell's avatar

        Jim Randell 3:06 pm on 22 September 2019 Permalink | Reply

        Here’s a slightly shorter program that considers values for X, and derives possible values for W, Y, Z, k, t from that.

        Since we know:

        k / (k + 1) = Y / X = X / W

        We also know that:

        X² = Y.W

        So Y and W are divisor pairs of X², and Y < X < W.

        We can then also calculate Z and k and check they satisfy the remaining conditions.

        Run: [ @replit ]

        from enigma import (irange, divisors_pairs, div, filter_unique, unpack, intersect, printf)
        
        # collect possible solutions
        rs = list()
        
        # consider 2-digit values for X
        for X in irange(10, 99):
        
          # compute W, Y, Z, k, t
          for (Y, W) in divisors_pairs(X, 2):
            if not (9 < Y < X < W < 100): continue
            Z = X + Y - W
            if not (9 < Z): continue
            k = div(Y, X - Y)
            if k is None: continue
            t = X + Y + W + Z
            if t % 4 != 0: continue
        
            rs.append((W, X, Y, Z, k, t))
            printf("[X={X}, Y={Y} W={W} Z={Z}, k={k} t={t}]")
        
        # the total is ambiguous
        (_, rs1) = filter_unique(rs, unpack(lambda W, X, Y, Z, k, t: t))
        
        # the fraction is also ambiguous
        (_, rs2) = filter_unique(rs, unpack(lambda W, X, Y, Z, k, t: k))
        
        # but together these tell us W
        rs = intersect((rs1, rs2))
        ws = set(W for (W, X, Y, Z, k, t) in rs)
        printf("W = {ws} [{rs}]")
        

        Like

  • Unknown's avatar

    Jim Randell 11:46 am on 20 September 2019 Permalink | Reply
    Tags:   

    Teaser 2871: Five-card trick 

    From The Sunday Times, 1st October 2017 [link] [link]

    I have five cards with a different digit from 1 to 5 on each. I shuffled them and placed them face-down in a row to form a concealed five-figure number. Then I invited each of my six nephews to choose a number less than fifty and they happened to choose six consecutive numbers. Then I explained that there would be a prize for anyone whose number was a divisor of the concealed number. No-one was certain to win but they were all in with a chance until I revealed the final digit of the number, which ruled out two of them from winning. Then I revealed the first digit and that ruled two more out. Then I revealed the whole number and just one nephew won a prize.

    What was the concealed number?

    [teaser2871]

     
    • Jim Randell's avatar

      Jim Randell 11:48 am on 20 September 2019 Permalink | Reply

      This is a similar puzzle to Teaser 2891 (also set by Stephen Hogg), but I think this one is easier to solve.

      This Python program runs in 52ms.

      Run: [ @repl.it ]

      from enigma import (defaultdict, irange, subsets, nconcat, flattened, tuples, printf)
       
      # possible divisors
      divisors = list(irange(1, 49))
       
      # possible numbers made by the cards
      # record numbers by the divisors from 1 to 49, final digit, first digit
      r = defaultdict(lambda: defaultdict(lambda: defaultdict(set)))
      t = 0
      for s in subsets(irange(1, 5), size=len, select="P"):
        n = nconcat(s)
        t += 1
        for d in divisors:
          if n % d == 0:
            r[d][s[-1]][s[0]].add(n)
       
      # how to flatten r (a nested structure of dicts and sets)
      def flatten_test(x):
        if isinstance(x, dict): return x.values()
        if isinstance(x, set): return sorted(x)
       
      # extract the leaf values from the structure
      def values(x):
        return list(flattened(x, fn=flatten_test))
       
      # eliminate divisors that contain all t values ("no-one was certain to win")
      # or have no values ("they all have a chance")
      ds = list(d for d in divisors if 0 < len(values(r[d])) < t)
       
      # choose the 6 numbers for the nephews
      for ns in tuples(ds, 6):
        # the numbers must be consecutive
        if ns[-1] != ns[0] + 5: continue
       
        # revealing the final digit eliminates two of them
        for d5 in irange(1, 5):
          e1 = set(n for n in ns if not values(r[n][d5]))
          if len(e1) != 2: continue
       
          # the first digit eliminates two more of them
          for d1 in irange(1, 5):
            if d1 == d5: continue
            e2 = set(n for n in ns if n not in e1 and not values(r[n][d5][d1]))
            if len(e2) != 2: continue
       
            # the whole number works for just one of the remaining nephews
            rs = set(ns).difference(e1, e2)
            for x in set().union(*(values(r[n][d5][d1]) for n in rs)):
              # find the winners
              ws = set(n for n in rs if x in values(r[n][d5][d1]))
              if len(ws) == 1:
                printf("cards = {x} [ns={ns}, e1={e1}, e2={e2}, ws={ws}]")
      

      Solution: The concealed number is 15324.

      “no-one was certain to win”, eliminates divisors 1 and 3.

      “but they all have a chance”, eliminates: 9, 10, 11, 18, 20, 22, 27, 30, 33, 36, 40, 41, 44, 45.

      Which means the only set of six consecutive possible divisors remaining is: 12, 13, 14, 15, 16, 17.

      Revealing the final digit eliminates 2 of the nephews, so the final digit must be 2 or 4 (if it were 1, 3, 5 at least the three nephews who had chosen even divisors would be eliminated), but if it were 2 only 15 would be eliminated. So the final digit is 4, and the nephews who chose 15 and 16 are eliminated.

      Then the first digit is revealed, and this eliminates another two nephews. So the first digit is 1, which eliminates 13 and 17 as possible divisors (2 eliminates 12, 13, 14; 3 eliminates 13, 14, 17; 5 eliminates 17).

      So the number is 1???4. Only 15324 has one winner – the nephew who chose 12. The other possibility is 13524, which has 12 and 14 as winners.

      Like

  • Unknown's avatar

    Jim Randell 9:52 am on 19 September 2019 Permalink | Reply
    Tags:   

    Brain-Teaser 501: [Missing weight] 

    From The Sunday Times, 10th January 1971 [link]

    The grain retailer had with his scales a set comprising the smallest number of weights which, use in any way required, enabled him to weigh loads of every exact number of kilos from 1 to 40 kilos.

    One day he mislaid one of his weights and, remembering that the rival shop next door had had an identical set which was no longer in use, he asked to borrow it.

    That set too, however, proved to have one of its weights missing, and so it turned out that, even with all the surviving weights in both sets at his disposal, he could weigh only 25 different loads within the required range of 1-40 kilos.

    What was the retailers missing weight?

    This puzzle was originally published with no title.

    [teaser501]

     
    • Jim Randell's avatar

      Jim Randell 9:53 am on 19 September 2019 Permalink | Reply

      In Brainteaser 1575 we determined that a set of weights consisting of the first four powers of three (1, 3, 9, 27) will allow us to weigh all integer amounts between 1 and 40.

      The borrowed set must be missing the same weight as the original set (otherwise he could just replace the missing weight and weigh 1 … 40 kg again). So there are only 4 options to try.

      This Python program runs in 95ms.

      from enigma import (irange, subsets, printf)
      
      # set of weights for weighing 1 ... 40 kg
      weights = (1, 3, 9, 27)
      
      # find values that cannot be weighed with the set of weights
      def values(weights):
        # desired values
        ws = set(irange(1, 40))
        # choose a subset of the weights
        for s in subsets(weights):
          # choose a pan for each weight
          for p in subsets((+1, -1), size=len(s), select="M"):
            w = sum(x * y for (x, y) in zip(s, p))
            ws.discard(w)
        return ws 
      
      # choose 3 of the 4 weights
      for ws in subsets(weights, size=3):
        # determine the number of missing values using 2 sets of weights
        vs = values(ws * 2)
        # if there 15 missing values...
        if len(vs) == 15:
          # output solution
          printf("{ws} -> {vs}")
      

      Solution: The missing weight is 9 kg.

      Both sets are missing the 9 kg weight, and there are 15 values that cannot be weighed (9 – 18 kg, 36 – 40 kg).

      If both the 1 kg weights are missing there are 27 values that cannot be weighed (1, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22, 23, 25, 26, 28, 29, 31, 32, 34, 35, 37, 38, 40).

      If both the 3 kg weights are missing there are 18 values that cannot be weighed (3 – 6, 12 – 15, 21 – 24, 30 – 33, 39 – 40)

      If both the 27 kg weights are missing there are 14 values that cannot be weighed (27 – 40).

      Like

  • Unknown's avatar

    Jim Randell 12:19 pm on 18 September 2019 Permalink | Reply
    Tags:   

    Teaser 2891: Nine cut diamonds 

    From The Sunday Times, 18th February 2018 [link] [link]

    An app “shuffles” and “deals” the “ace” (= 1) to “nine” of diamonds in a line, face down. Three numbers under 30 are chosen at random and each will win if it is a factor of the hidden nine-digit value. Keying # reveals the rightmost face-down card. At such a “reveal” the app displays “won”, “lost” or “in-play” for each number. The rightmost face-down cards are revealed singly until all are known.

    For one deal my three numbers didn’t include a prime number and after two “reveals” were all “in-play”. After the third “reveal”, two were “won” and one “lost”.

    At the third “reveal” what three-digit number was displayed?

    [teaser2891]

     
    • Jim Randell's avatar

      Jim Randell 12:22 pm on 18 September 2019 Permalink | Reply

      I found the wording a bit cumbersome. Perhaps something like this would have been better:

      I dealt 9 green cards with the digits 1-9 on them face down to create a hidden 9 digit “pandigital” number. And then dealt three blue cards face up from a set consisting of numbers from 1 to 30. None of the blue cards showed a prime number.

      I then started turning over the green cards from the right hand end of the “pandigital” number. After revealing the final two digits I couldn’t be sure whether any of the numbers on the blue cards divided the whole pandigital number or not, but when I revealed the third digit I knew for sure that 2 of them must divide it and the other one must not.

      What were the final three digits of the pandigital number?


      We can eliminate some of the non-primes below 30 as possible divisors because we know the divisibility is not decided until at least digits of the number are revealed (although doing so does not make a huge difference to the run time).

      For instance we can immediately discard the following divisors:

      1 – all numbers are divisible by 1
      9 – any pandigital composed of the digits 1-9 is divisible by 9
      10 – no pandigital is divisible by 10
      20 – as no pandigital is divisible by 10

      We can also discard the following divisors as the divisibility remains undecided when the final digit of the number is known:

      6 – all pandigitals are divisible by 3, and the final digit will tell us if it is divisibly by 2
      15 – all pandigitals are divisible by 3, the final digit will tell us if it is divisible by 5
      18 – all pandigitals are divisible by 9, the final digit will tell us if it is divisible by 2

      And when the final 2 digits are revealed:

      4 – the final 2 digits tell us if it is divisible by 4
      12 – as all pandigitals are divisible by 3
      25 – the final 2 digits tell us if it is divisible by 25

      This Python program considers the three revealed digits and looks for possible divisors that would behave in the manner described. It runs in 904ms.

      Run: [ @repl.it ]

      from enigma import (defaultdict, irange, is_prime, subsets, nconcat, printf)
      
      # possible digits
      digits = set(irange(1, 9))
      
      # non-primes 1-29
      numbers = set(x for x in irange(1, 29) if not is_prime(x))
      
      # we can eliminate some numbers based on the fact that divisibility
      # of the pandigital is not known until 3 digits have been revealed
      # (although it doesn't make that much difference to the runtime)
      numbers.difference_update([1, 9, 10, 20], [4, 6, 12, 15, 18, 25])
      
      # n in div[x] = "there is a pandigital ending with x divisible by n"
      # n in non[x] = "there is a pandigital ending with x that is not divisible by n"
      (div, non) = (defaultdict(set), defaultdict(set))
      # consider all pandigitals
      for s in subsets(digits, size=len, select="P"):
        x = nconcat(s)
        # find the final 1-, 2-, 3- digits
        ms = tuple(x % m for m in (10, 100, 1000))
        # consider each of the candidate numbers
        for n in numbers:
          # record the number against the suffixes
          # according to whether it divides the pandigital or not
          d = (div if x % n == 0 else non)
          for m in ms: d[m].add(n)
      
      # when 1 digit is revealed
      for d1 in digits:
        n1 = d1
        # we need 3 numbers that have witnesses in both div and in non
        s1 = div[n1].intersection(non[n1])
        if len(s1) < 3: continue
      
        # when 2 digits are revealed
        for d2 in digits:
          if d2 == d1: continue
          n2 = 10 * d2 + n1
          # we need 3 numbers that have witnesses in both div and in non
          s2 = s1.intersection(div[n2], non[n2])
          if len(s2) < 3: continue
      
          # when 3 digits are revealed
          for d3 in digits:
            if d3 == d1 or d3 == d2: continue
            n3 = 100 * d3 + n2
            # find numbers that definitely divide the hidden number (we need at least 2)
            ds = s2.intersection(div[n3].difference(non[n3]))
            if len(ds) < 2: continue
            # find numbers that definitely don't divide the hidden number (we need at least 1)
            ns = s2.intersection(non[n3].difference(div[n3]))
            if len(ns) < 1: continue
        
            printf("{n3} -> div = {ds}, non = {ns}")
      

      Solution: The final three digits of the selected number are …528.

      There are 166 sets of divisors that would give “in-play” (x3) when the 1st digit is revealed. This is reduced to 84 when the 2nd digit is revealed, and only one of these gives (“win”, “win”, “lose”) when the 3rd digit is revealed.

      For the first digit there are 165 sets that can go with the even digits (2, 4, 6, 8) and 1 set that goes with the digit 5, although this set doesn’t survive to the 2nd digit reveal. There are 60 sets that are fixed by the reveal of the third digit, but all except the solution give (“lose”, “lose”, “lose”).

      There are only two potential divisors that end up with “win” – these are 8 and 24. And only one divisor that ends up with “lose” – 22. So these are our three chosen divisors.

      There are 720 candidate pandigitals ending …528. The smallest being 134679528, and the largest 976431528.

      Like

    • Steve Taylor's avatar

      Steve Taylor 11:11 pm on 7 January 2023 Permalink | Reply

      Hello Jim,

      My name is Steve, and this is just a hello message.

      I came across your site during lockdown and think it’s tremendous!

      I look forward to discussing Teaser 2891…

      Regards

      Steve

      Like

      • Jim Randell's avatar

        Jim Randell 3:11 pm on 9 January 2023 Permalink | Reply

        @Steve: Welcome to the site. I’m glad you find it useful. Feel free to post any further comments on the puzzles.

        Like

  • Unknown's avatar

    Jim Randell 7:49 am on 17 September 2019 Permalink | Reply
    Tags: ,   

    Teaser 1973: Straw store 

    From The Sunday Times, 9th July 2000 [link]

    Farmer Fermat has more straw than he can safely stack on his usual rectangular storage area. So he extends the shorter sides of the area to equal the longer sides, thereby forming a square. Alongside he adds another square area, whose side is equal to the shorter side of the original rectangle. The total area of the two squares together is 243 square feet larger than the original rectangle.

    He can now stack straw on each square, up to a height equal to the length of the side of each square, effectively forming two cubes, and the total volume in cubic feet is a perfect cube.

    What was the perimeter of the original rectangle?

    [teaser1973]

     
    • Jim Randell's avatar

      Jim Randell 7:50 am on 17 September 2019 Permalink | Reply

      As presented this puzzle has multiple solutions. However if the perimeter of the original rectangle is required to be a whole number of feet, then only one of the solutions remains.

      This Python program finds all the solutions to the puzzle numerically using the [[ find_zero() ]] function from the enigma.py library. It runs in 63ms.

      Run: [ @replit ]

      from enigma import (irange, cb, cbrt, sq, find_zero, catch, printf)
      
      # consider values for t, where T = t^3 is the total volume
      for t in irange(1, 100):
        T = cb(t)
      
        # calculate y (for x in [0, t])
        def Y(x):
          return cbrt(T - cb(x))
      
        # how close is x^2 + y^2 - xy to 243?
        def f(x):
          y = Y(x)
          return abs((sq(x) + sq(y) - x * y) - 243)
      
        # find a zero for f
        r = catch(find_zero, f, 0, cbrt(0.5 * T))
        if r is None: continue
        x = r.v
        y = Y(x)
        p = 2 * (x + y)
      
        # output solution
        printf("t={t}: x={x:.3f}, y={y:.3f}, p={p:.3f}")
      

      Solution: The (integer) perimeter of the original rectangle was 48 feet.

      Allowing non-integer solutions for the perimeter we get four solutions:

      t=16: x=0.857, y=15.999, p=33.712
      t=17: x=3.258, y=16.960, p=40.436
      t=18: x=6.255, y=17.745, p=48.000
      t=19: x=10.291, y=17.935, p=56.453

      Graphically we get a solution when the ellipse x² + y² − xy = 243 intersects the curve x³ + y³ = t³ for integer values of t.

      For positive x and y we get solutions for t = 16, 17, 18, 19, as shown in the graph below:

      The original rectangle has sides of length x and y, so the perimeter of the original rectangle is 2(x + y). Only t=18 gives an integer value for the perimeter (although the values for x and y are not integers). In this case the exact values are: x, y = 12 ± √33.

      Like

      • Jim Randell's avatar

        Jim Randell 8:39 am on 19 September 2019 Permalink | Reply

        Here is an analytical solution.

        Given the equations:

        x³ + y³ = t³
        x² + y² − xy = 243

        If we consider the product (x + y)(x² + y² − xy) we have:

        (x + y)(x² + y² − xy) = x³ + y³ = t³
        (x + y) = t³ / 243

        We also have:

        (x + y)² = (x² + y²) + 2xy
        (x + y)² = (243 + xy) + 2xy
        (x + y)² = 243 + 3xy
        xy = (x + y)² / 3 − 81

        So for a given value of t we can determine values for x + y and xy, say:

        x + y = a
        xy = b

        These have positive real solutions for x and y when a² ≥ 4b and b ≥ 0

        a² ≥ 4b
        (x + y)² ≥ 4xy
        (x + y)² ≥ (4/3)(x + y)² − 324
        (x + y)² ≤ 973
        (x + y) ≤ √973
        t³ ≤ 243 × √973
        t ≤ 19.643…

        b ≥ 0
        (x + y)² / 3 − 81 ≥ 0
        (x + y)² ≥ 243
        (x + y) ≥ √243
        t³ ≥ 243 × √243
        t ≥ 15.588…

        So t is in the range 16 to 19. And the required perimeter is given by p = 2(x + y) = 2t³ / 243.

        We can consider the 4 candidate values manually and look for an integer solution, or use a short program:

        Run: [ @replit ]

        from enigma import (irange, cb, div, printf)
        
        for t in irange(16, 19):
          p = div(2 * cb(t), 243)
          if p is None: continue
          printf("t={t}: p={p}")
        

        Like

  • Unknown's avatar

    Jim Randell 9:58 pm on 16 September 2019 Permalink | Reply
    Tags:   

    Brain-Teaser 500: [Succession] 

    From The Sunday Times, 3rd January 1971 [link]

    Joybells rang, fireworks went bang, and merry Bahreinis sang, celebrating not only their 500th Founding Festival, but also the coronation of the new monarch of Bahrein Teza.

    “But”, said our special correspondent, intercepting the Lord High Solutioner as he was hurrying through the Palace gates, “I understand there has been a disturbance concerning rival claimants to the throne?”

    “Yes, yes. A bit of bother. Long story”, replied the LHS. “Afraid I can’t stop now though. Banquet just starting. See you later. Wait! Here’s a copy of the royal genealogical tree. Tells you everything. Succession laws same as your own. Right?”, and he disappeared into the Palace.

    Well, here’s a relevant extract:

    CALCULUS – Son-in-law of NUMERA
    DATA III – Daughter of LOGICUS XI
    DATA – Mother of RIDELLA IV
    DECIMUS – Husband of PUZELA
    LOGICUS X – Father of NUMERA
    LOGICUS XI – Father of RIDELLA IV
    LOGICUS – Son of LOGICUS XI
    MATHUS – Brother-in-law of PUZLUS V
    NUMERA – Aunt of PUZLUS VI
    PUZELA – Cousin of LOGICUS XI
    PUZELA – Daughter-in-law of PUZELA
    PUZLUS V – Father of RIDELLA
    PUZLUS VI – Elder son of PUZLUS V
    RIDELLA IV – Niece of PUZLUS VI
    RIDELLA – Mother of SOLVUS II
    RIDELLA – Wife of LOGICUS XI
    SOLVUS II – Cousin of RIDELLA IV

    So who is crowned and who is the claimant?

    The following was published alongside this puzzle:

    Brain-teased 500 times

    “Tantalising but irresistible” sums up the reaction of thousands of readers to The Sunday Times Brain-teaser, which this week reaches its 500th example since numbering began on February 26, 1961.

    Competitors, from emeritus professors of mathematics to 11-year-olds, with a growing proportion of women, submit their solutions from every county and from 56 oversea States, some never having missed a week. It is calculated that between 40,000/50,000 readers send a solution every year.

    Set by Sunday Times readers, the problems are selected from about 200 a year, vetted for uniqueness of solutions by independent experts (with an occasional oversight) and are published in varying degrees of difficulty; entries then range weekly from around 4,000 to a handful from the master-minds.

    Anthony French

    This puzzle was originally published with no title.

    [teaser500]

     
    • Jim Randell's avatar

      Jim Randell 9:59 pm on 16 September 2019 Permalink | Reply

      For me this puzzle isn’t well enough defined.

      For instance:

      PUZELA − Daughter-in-law of PUZELA

      Does this mean that PUZELA married her own son? Or is there not a one-to-one correspondence between names and people?

      Maybe each line of the genealogy refers to a different person? If so, there are two PUZELAs and RIDELLAs and we don’t know which is referred to when the names are used again.

      And even if you come up with an answer there seems to be no way to check if it is right.

      However, as I have transcribed the puzzle (and at least glanced at it) I am posting it for completeness, and in case someone else is interested in it.


      The published solution is:

      Crowned = DECIMUS. Claimant = LOGICUS.

      A splendid baffling problem of succession. Did no one spot the Stuart parallel? A mixed bag. 18% right.

      So it doesn’t look like it was that well received at the time.

      Like

    • Lise Andreasen's avatar

      Lise Andreasen 6:26 am on 28 July 2024 Permalink | Reply

      Yeah. Can’t quite make sense of it.

      Like

  • Unknown's avatar

    Jim Randell 8:37 am on 15 September 2019 Permalink | Reply
    Tags:   

    Brainteaser 1712: Squambling 

    From The Sunday Times, 9th July 1995 [link]

    In “squambling” a number, the first (leftmost) digit is squared, the next is cubed, the next raised to the fourth power, and so on. The total of these answers provides a new number, ready for the squambling to begin again.

    For example:

    18 → 1² + 8³ = 513 → 5² + 1³ + 3⁴ = 107
    107 → 2402 → 100 → 1 → 1 → …

    If you take my age and squamble it you get a three-figure number. If you then squamble that answer you get my age next year.

    How old am I?

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

    [teaser1712]

     
    • Jim Randell's avatar

      Jim Randell 8:38 am on 15 September 2019 Permalink | Reply

      This Python program runs in 86ms.

      Run: [ @replit ]

      from enigma import (nsplit, irange, inf, printf)
      
      squamble = lambda n: sum(d ** n for (n, d) in enumerate(nsplit(n), start=2))
      
      assert squamble(18) == 513
      
      for n in irange(1, inf):
        sn = squamble(n)
        if not (99 < sn < 1000): continue
        s2n = squamble(sn)
        if not (s2n == n + 1): continue
        # output solution
        printf("{n} -> {sn} -> {s2n}")
        break
      

      Solution: You are 46.

      We have:

      46 → 232 → 47 → … → 43

      After 91 applications of the function we eventually reach a value of 43, which is stable (i.e. squamble(43) = 43).

      The next smallest value at which this occurs is 753:

      753 → 255 → 754

      Like

  • Unknown's avatar

    Jim Randell 3:58 pm on 13 September 2019 Permalink | Reply
    Tags:   

    Teaser 2973: Something in common 

    From The Sunday Times, 15th September 2019 [link] [link]

    I have written down four different numbers. The third number is the highest common factor of the first two (i.e. it is the largest number that divides exactly into both of them). The fourth number is the lowest common multiple of the first two (i.e. it is the smallest number that both of them divide exactly into).

    I can consistently replace digits by letters in my numbers so that the highest common factor is HCF and the lowest common multiple is LCM.

    What are the first two numbers?

    [teaser2973]

     
    • Jim Randell's avatar

      Jim Randell 4:06 pm on 13 September 2019 Permalink | Reply

      The two mystery numbers have a common divisor that is 3 digits, and also the have a common multiple that is 3 digits, so they are both 3 digit numbers themselves.

      Denoting the numbers UVW and XYZ we can use the [[ SubstitutedExpression() ]] solver from the enigma.py library to give a direct interpretation of the the puzzle.

      This run file executes in 989ms.

      Run: [ @repl.it ]

      #! python -m enigma -rr
      
      SubstitutedExpression
      
      --distinct="CFHLM"
      --answer="(UVW, XYZ)"
      
      "gcd(UVW, XYZ) = HCF"
      "lcm(UVW, XYZ) = LCM"
      
      "all_different(UVW, XYZ, HCF, LCM)"
      
      "UVW < XYZ"
      

      Solution: The first two numbers are 278 and 417.

      hcf(278, 417) = 139
      lcm(278, 417) = 834

      Like

      • Jim Randell's avatar

        Jim Randell 5:14 pm on 13 September 2019 Permalink | Reply

        Here’s an alternative approach that uses a bit of analysis:

        Each of the mystery numbers must be some small (proper) multiple of HCF, say, A × HCF and B × HCF. And A and B must be co-prime.

        We can then use the fact that:

        hcf(p, q) × lcm(p, q) = p × q

        to give a faster alphametic approach.

        The following run file executes in 173ms.

        Run: [ @repl.it ]

        #! python -m enigma -rr
        
        SubstitutedExpression
        
        --distinct="CFHLM"
        --answer="(A * HCF, B * HCF)"
        
        "1 < A < B"
        "gcd(A, B) = 1"
        
        "A * B * HCF = LCM"
        

        Actually it is clear that A × B < 10, so the only options are A = 2, B = 3, giving rise to the following one-line solution:

        % python -m enigma SubstitutedExpression "6 * HCF = LCM" --answer="(2 * HCF, 3 * HCF)"
        (6 * HCF = LCM) ((2 * HCF, 3 * HCF))
        (6 * 139 = 834) ((2 * 139, 3 * 139)) / C=3 F=9 H=1 L=8 M=4
        (2 * HCF, 3 * HCF) = (278, 417) [1 solution]
        

        Like

    • GeoffR's avatar

      GeoffR 10:09 am on 17 September 2019 Permalink | Reply

      % A Solution in MiniZinc
      include "globals.mzn";
      
      var 1..9:H; var 0..9:C; var 0..9:F;
      var 1..9:L; var 0..9:M;
      
      var 100..999:N1; var 100..999:N2;
      var 100..999:HCF = 100*H + 10*C + F;
      var 100..999:LCM = 100*L + 10*C + M;
      
      constraint all_different( [N1, N2, HCF, LCM] );
      constraint all_different( [H, C, F, L, M] );
      
      constraint LCM * HCF == N1 * N2;
      
      constraint N1 mod HCF == 0 /\ N2 mod HCF == 0;
      
      solve maximize(HCF);
      
      output [ " First number = " ++ show(N1) ++ "\n"
      ++ " Second number = " ++ show(N2) ++ "\n"
      ++ " Highest common factor = " ++ show(HCF) ++ "\n"
      ++ " Lowest common multiple = " ++ show(LCM) ]; 
      
      

      Like

  • Unknown's avatar

    Jim Randell 8:29 am on 13 September 2019 Permalink | Reply
    Tags: ,   

    Teaser 2783: Old boys’ banquet 

    From The Sunday Times, 24th January 2016 [link] [link]

    George and Martha have arranged the seating plan for the annual Old Boys banquet; it involves a number of tables, each seating 50 diners. More than half the Old Boys are bringing one female guest each and the rest are coming alone. Martha wrote down three numbers, namely the number of Old Boys bringing a guest, the number of Old Boys coming alone, and the total number of Old Boys coming. George noted that the three numbers between them used each of the digits 0 to 9 exactly once.

    How many Old Boys are bringing a guest, and how many are coming alone?

    [teaser2783]

     
    • Jim Randell's avatar

      Jim Randell 8:30 am on 13 September 2019 Permalink | Reply

      If s is the number of old boys without guests and g is the number with guests, then we have a pandigital sum of the form:

      s + g = b

      where s < g.

      Altogether there are 10 digits used so, alphametically, the sum is one of:

      AB + CDEF = GHIJ
      ABC + DEF = GHIJ

      This Python program uses the [[ SubstitutedSum() ]] solver from the enigma.py library to examine solutions to both sums. It runs in 277ms.

      Run: [ @repl.it ]

      from enigma import SubstitutedSum, div, printf
      
      # solve the pandigital sum
      digits = 'ABCDEFGHIJ'
      for k in (2, 3):
        (x, y, z) = (digits[0:k], digits[k:6], digits[6:])
        p = SubstitutedSum([x, y], z)
        for s in p.solve():
          # turn the solution into numbers
          (s, g, b) = (int(p.substitute(s, w)) for w in (x, y, z))
          # more than half the old boys have guests
          if not (g > s): continue
          # so the total number of people is...
          t = b + g
          # and the number of tables is...
          n = div(t, 50)
          if n is None: continue
        
          printf("s={s} g={g} boys={b}, people={t} tables={n}")
      

      Solution: There are four possible solutions:

      26 without guests, 4987 with guests; 5013 total boys, 10000 total people, 200 tables
      74 without guests, 5938 with guests; 6012 total boys, 11950 total people, 239 tables
      86 without guests, 1957 with guests; 2043 total boys, 4000 total people, 80 tables
      346 without guests, 752 with guests; 1098 total boys, 1850 total people, 37 tables

      I suspect the setter intended the final solution to be the correct answer, which is the only solution where the pandigital sum is of the form: ABC + DEF = GHIJ.

      A suitable upper limit on the total number of old boys, total number of people, or number of tables would eliminate the other solutions.

      However if we change the condition in the puzzle text to:

      More than half the Old Boys are coming alone and the rest are bringing one female guest each.

      (i.e. we require s > g).

      Then there is only a single solution to the puzzle:

      746 without guests, 352 with guests; 1098 total boys, 1450 total people, 29 tables

      Reversing the inequality at line 12 of the program will give this solution.

      Like

    • GeoffR's avatar

      GeoffR 1:59 pm on 14 September 2019 Permalink | Reply

      % A Solution in MiniZinc
      include "globals.mzn"; 
      
      var 0..9: a; var 0..9: b; var 0..9: c; var 0..9: d; var 0..9: e;
      var 0..9: f; var 0..9: g; var 0..9: h; var 0..9: i; var 0..9: j;
      
      % Assume boys/boys with guest/total boys are in ratio 3:3:4
      var 100..999: abc;     % boys with guest
      var 100..999: def;     % boys alone
      var 1000..2000: ghij;  % total boys
      var 0..250: tables;    % total tables
      
      % All ten digits are used exactly once
      constraint alldifferent([a,b,c,d,e,f,g,h,i,j]) 
                 /\ a > 0 /\ d > 0 /\ g > 0;
      
      constraint  abc = 100*a + 10*b + c
               /\ def = 100*d + 10*e + f
               /\ ghij = 1000*g + 100*h + 10*i + j ;
      
      % More than half the boys brought a female guest
      constraint abc > ghij div 2;
      
      constraint abc + def == ghij;
      
      constraint tables * 50 == abc * 2 + def;
      
      solve satisfy;
      
      output [" Boys with a guest: " ++ show(abc) ++ "\n" ++
              " Boys on their own: " ++ show(def) ++ "\n" ++
              " Total boys: " ++ show(ghij) ++ "\n" ++
              " Tables: " ++ show(tables)];  
      
      % Boys with a guest: 752
      % Boys on their own: 346
      % Total boys: 1098
      % Tables: 37
      % ----------
      % ==========
      
      

      Like

  • Unknown's avatar

    Jim Randell 9:03 am on 10 September 2019 Permalink | Reply
    Tags: by: David W Poyner   

    Brain-Teaser 499: [League table] 

    From The Sunday Times, 20th December 1970 [link]

    Paddy was in a reminiscent mood. “Sure it was a good year for Ireland, for didn’t we beat England by 4 goals to 1 and win the championship?” he said, proudly showing us the league table of the championship in which each country had played against each of the other three.

    “Of course”, he added slyly, “you can now work out the score in one of the other matches”.

    Which match? And what was the score?

    This puzzle was originally published with no title.

    [teaser499]

     
    • Jim Randell's avatar

      Jim Randell 9:04 am on 10 September 2019 Permalink | Reply

      This Python program uses the [[ Football() ]] helper class from the enigma.py library. It runs in 95ms.

      from enigma import (Football, digit_map, Accumulator, printf)
      
      # scoring system
      football = Football(games='wdl')
      
      # labels for the teams (in table order)
      order = (I, W, E, S) = (0, 1, 2, 3)
      teams = "IWES"
      
      # values stand for themselves
      d = digit_map(0, 9)
      
      # columns of the table
      (table, gf, ga) = (dict(w="3110", d="0101", l="0122"), "9565", "3589")
      
      # known matches
      (ms0, ss0) = ({ (I, E): 'w' }, { (I, E): (4, 1) })
      
      # find scores common to each scenario
      r = Accumulator(fn=lambda s, v: s.intersection(v))
      
      # find possible match outcomes
      for (ms, _) in football.substituted_table(table, d=d, matches=ms0):
      
        # find possible scores
        for ss in football.substituted_table_goals(gf, ga, ms, d=d, scores=ss0):
      
          # output scenario
          football.output_matches(ms, ss, teams=teams)
      
          # record scores
          r.accumulate(set(ss.items()))
      
      # output fixed scores (other than for I vs E)
      printf("SOLUTION:")
      for ((x, y), (sx, sy)) in r.value:
        if (x, y) == (I, E): continue
        printf("-> {x} vs {y} = {sx}-{sy}", x=teams[x], y=teams[y])
      

      Solution: The score in the Wales vs Scotland match must be 2-2.

      There are 5 different scenarios for the scores, but in each of them W vs S is 2-2.

      Like

      • John Crabtree's avatar

        John Crabtree 3:39 pm on 10 September 2019 Permalink | Reply

        As league table puzzles go, this is an easier one.

        If the score in IvW is x – y, and the score in WvS is d – d, the other scores are:
        IvS (5 – x) – (2 – y)
        WvE (5 – d – y) – (5 – d – x)
        EvS (d + x) – (d + y – 1)

        Looking at the goals scored by Scotland, 5 = d + (2 – y) + (d + y – 1) = 2d + 1, ie d = 2

        And so the score in Wales v. Scotland is 2 – 2

        By inspection, the possible values for (x,y) are (1, 0), (2, 1), (2,0), (3, 1), and (3, 2)

        Like

  • Unknown's avatar

    Jim Randell 8:59 am on 9 September 2019 Permalink | Reply
    Tags:   

    Teaser 2802: That’s the ticket! 

    From The Sunday Times, 5th June 2016 [link] [link]

    Alan, Betty and Charlie each chose a different set of six numbers (from 1 to 49) for their lottery ticket. In each case the product of the six numbers was a perfect square and also each set of six numbers used each of the digits 0 to 9 exactly once.

    Alan won the lottery by getting all six numbers correct. Betty and Charlie also got prizes because they each had at least three numbers correct.

    What were Alan’s six numbers?

    [teaser2802]

     
    • Jim Randell's avatar

      Jim Randell 8:59 am on 9 September 2019 Permalink | Reply

      We have six numbers (between 1 and 49) that between them use 10 digits (each of the digits 0-9 exactly once). So four of the numbers must have 2 digits, and their tens digits are all different, so the set of six numbers is of the form (alphametically):

      a, b, 1c, 2d, 3e, 4f

      where a, b, c, d, e, f are the digits 0, 5, 6, 7, 8, 9 (in some order).

      It turns out there are only three possible sets of six numbers that use the digits 0-9 exactly once and multiply together to give a square. Fortunately one of them shares 3 or more numbers with the other two, so this gives us A’s numbers.

      This Python program runs in 36ms.

      Run: [ @repl.it ]

      from enigma import subsets, multiply, is_square, printf
      
      # find possible sets of numbers
      ss = list()
      for (a, b, c, d, e, f)  in subsets((0, 5, 6, 7, 8, 9), size=len, select="P"):
        if not (0 < a < b): continue
        s = (a, b, 10 + c, 20 + d, 30 + e, 40 + f)
        # we only want sets whose product is a perfect square
        if not is_square(multiply(s)): continue
        ss.append(set(s))
        printf("{s}")
      
      # now choose a set for A
      for A in ss:
        # and find other sets that share at least 3 numbers
        BC = list(s for s in ss if s != A and len(A.intersection(s)) > 2)
        if len(BC) > 1:
          printf("A={A}, BC={BC}", A=sorted(A), BC=list(map(sorted, BC)))
      

      Solution: Alan’s numbers were: 8, 9, 16, 27, 30, 45.

      There are only two options for Betty and Charlie:

      5, 8, 16, 27, 30, 49 = 4 matched numbers
      8, 9, 15, 27, 36, 40 = 3 matched numbers

      Like

    • GeoffR's avatar

      GeoffR 9:47 am on 19 September 2019 Permalink | Reply

      
      % A Solution in MiniZinc
      include "globals.mzn";
      
      % Let digits used be (a, b, cd, ef, gh, ij) for the six numbers
      
      predicate is_sq(var int: y) =
        let {
           var 1..ceil(sqrt(int2float(ub(y)))): z
        } in
         z*z = y;
      
      var 1..9:a; var 1..9:b; var 1..9:c; var 0..9:d;
      var 1..9:e; var 0..9:f; var 1..9:g; var 0..9:h;
      var 1..9:i; var 0..9:j;
      
      var 10..49: cd = 10*c + d;
      var 10..49: ef = 10*e + f;
      var 10..49: gh = 10*g + h;
      var 10..49: ij = 10*i + j;
      
      % six numbers used each of the digits 0 to 9 exactly once
      var set of int: all_dig = {a, b, c, d, e, f, g, h, i, j};
      constraint all_dig = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
      
      % product of six numbers is a square
      constraint is_sq(a * b * cd * ef * gh * ij);
      
      % put six numbers in order
      constraint increasing ([a, b, cd, ef, gh, ij]);
      
      solve satisfy;
      
      output [" Six Numbers are " ++ show([a, b, cd, ef, gh, ij]) ];
      
      % First two solutions are for Betty and Charlie
      % Six Numbers are [5, 8, 16, 27, 30, 49] - 4 nos same as Alan(8,16,27,30)
      %  ----------
      % Six Numbers are [8, 9, 15, 27, 36, 40] - 3 nos same as Alan (8,9,27)
      % ----------
      % Six Numbers are [8, 9, 16, 27, 30, 45] -  Alan's six numbers
      % ----------
      % ========== 
      

      Like

  • Unknown's avatar

    Jim Randell 9:19 am on 8 September 2019 Permalink | Reply
    Tags:   

    Brainteaser 1688: Sunday paper 

    From The Sunday Times, 22nd January 1995 [link]

    As usual, in this letters-for-digits puzzle different digits have consistently been replaced by different letters:

    Each letter in the second row is the sum of its two nearest letters in the row above.

    What is the value of READER?

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

    [teaser1688]

     
    • Jim Randell's avatar

      Jim Randell 9:20 am on 8 September 2019 Permalink | Reply

      I used the [[ SubstitutedExpression() ]] solver from the enigma.py library to solve the 5 sums.

      The following run files executes in 150ms.

      Run: [ @replit ]

      #! python3 -m enigma -rr
      
      SubstitutedExpression
      
      "S + U = P"
      "U + N = A"
      "N + D = P"
      "D + A = E"
      "A + Y = R"
      
      --answer="READER"
      

      Solution: READER = 694596.

      Like

    • GeoffR's avatar

      GeoffR 8:25 pm on 8 September 2019 Permalink | Reply

      from itertools import permutations
      
      for x in permutations (range(1,10)):
          s, u, n, d, a, y, p, e, r = x
          if s + u == p:
            if u + n == a:
              if n + d == p:
                if d + a == e:
                  if a + y == r: 
                    reader = 100001*r + 10010*e + 1000*a + 100*d
                    print("READER = ", reader)
                    # READER =  694596
      
      

      Like

  • Unknown's avatar

    Jim Randell 5:56 pm on 6 September 2019 Permalink | Reply
    Tags:   

    Teaser 2972: A relaxing day 

    From The Sunday Times, 8th September 2019 [link] [link]

    George and Martha have a digital clock, which displays time with six digits on the 24-hour system (i.e. HH:MM:SS).

    One afternoon, George looked at the clock and saw a six-digit display involving six different positive digits. He dozed off immediately, and when he awoke in the evening he saw another display of six digits, again all positive and different. He dozed off immediately and later on (before midnight) he awoke, having slept for exactly 23 minutes longer than the previous time. At that time, he saw a third display, yet again six different positive digits. He thus had seen eighteen digits and the nine positive digits had each appeared exactly twice.

    At what time did George wake up after his first sleep?

    [teaser2972]

     
    • Jim Randell's avatar

      Jim Randell 6:30 pm on 6 September 2019 Permalink | Reply

      This Python program looks for possible 6-digit times composed of different digits, it separates them into afternoon (before 6pm) and evening (after 6pm) and the looks for two times in the evening that have a difference that is 23 minutes longer than the difference between the first time and one of the afternoon times. We then check the three times between them use each of the digits exactly twice. It runs in 460ms.

      Run: [ @repl.it ]

      from enigma import (irange, nsplit, cproduct, subsets, multiset, sprintf, printf)
      
      # format a number of seconds as HH:MM:SS
      def hms(t):
        (h, m, s) = nsplit(t, 3, base=60)
        return sprintf("{h:02d}:{m:02d}:{s:02d}")
      
      # consider 2-digit numbers with different digits that make valid times
      (hs, mss) = (list(), list())
      for n in irange(12, 59):
        (a, b) = nsplit(n, 2)
        if a == b or b == 0: continue
        if n < 24: hs.append((a, b))
        mss.append((a, b))
      
      # collect times composed of 6 different digits
      (aft, eve) = (dict(), dict())
      for ((h1, h0), (m1, m0), (s1, s0)) in cproduct([hs, mss, mss]):
        ds = (h1, h0, m1, m0, s1, s0)
        if len(set(ds)) != 6: continue
        # time as a number of seconds
        t = ((h1 * 10 + h0) * 60 + (m1 * 10 + m0)) * 60 + (s1 * 10 + s0)
        (aft if t < 64800 else eve)[t] = ds
      
      # find times t2, t3, both in the evening
      for (t2, t3) in subsets(sorted(eve.keys()), size=2):
        d = t3 - t2 - 1380
        if not (d > 0): continue
        # and t1 in the afternoon
        t1 = t2 - d
        if t1 not in aft: continue
      
        # check each digit is used exactly twice
        m = multiset(aft[t1], eve[t2], eve[t3])
        if not all(v == 2 for v in m.values()): continue
      
        # output solution
        printf("{t1} -> {t2} -> {t3}", t1=hms(t1), t2=hms(t2), t3=hms(t3))
      

      Solution: After the first nap George awoke when the clock read 19:56:48.

      There are two possible start times for the first nap (although they are within a minute of each other), but in both cases the wake time from the first nap is the same, and so there is a unique answer to the puzzle.

      The two possible sequences are:

      16:27:39 → (3h29m09s) → 19:56:48 → (3h52m09s) → 23:48:57
      16:28:37 → (3h28m11s) → 19:56:48 → (3h51m11s) → 23:47:59

      And these are the only two sequences even if we don’t restrict the first time to be “afternoon” and the final two times to be “evening”.

      Like

    • GeoffR's avatar

      GeoffR 3:33 pm on 10 September 2019 Permalink | Reply

      % A Solution in MiniZinc
      include "globals.mzn";
      
      % hours, min and sec for afternoon time
      var 12..17: ah;
      var 12..59: am;
      var 12..59: as;
      
      % No zeroes in six positive digits
      constraint am != 20 /\ am != 30 /\ am != 40 /\ am != 50;
      constraint as != 20 /\ as != 30 /\ as != 40 /\ as != 50;
      
      constraint  all_different([ah div 10, ah mod 10,
      am div 10, am mod 10, as div 10, as mod 10]);
      
      % afternoon time in sec (range from midday to midnight)
      var 43000..90000: a_sec = ah*3600 + am*60 + as;
      
      % hours, min and sec for 1st evening time 
      var 18..23: eh1;
      var 12..59: em1;
      var 12..59: es1;
      
      constraint eh1 != 20;
      
      % No zeroes in six positive digits of time
      constraint em1 != 20 /\ em1 != 30 /\ em1 != 40 /\ em1 != 50;
      constraint es1 != 20 /\ es1 != 30 /\ es1 != 40 /\ es1 != 50;
      
      constraint all_different ([eh1 div 10, eh1 mod 10,
      em1 div 10, em1 mod 10, es1 div 10, es1 mod 10]);
      
      % 1st evening time in sec
      var 43000..90000: e1_sec = eh1*3600 + em1*60 + es1;
      
      % 2nd evening time 
      % hours, min and sec for 2nd evening time
      var 18..23: eh2;
      var 12..59: em2;
      var 12..59: es2;
      
      constraint all_different ([eh2 div 10, eh2 mod 10,
      em2 div 10, em2 mod 10, es2 div 10, es2 mod 10]);
      
      constraint eh2 != 20;
      
      % No zeroes in six positive digits
      constraint em2 != 20 /\ em2 != 30 /\ em2 != 40 /\ em2 != 50;
      constraint es2 != 20 /\ es2 != 30 /\ es2 != 40 /\ es2 != 50;
      
      % 2nd evening time in sec
      var 43000..90000: e2_sec = eh2*3600 + em2*60 + es2;
      
      % all digits 1..9 in the three 6-digit times occur exactly twice
      constraint forall(i in 1..9) 
      (count ([ 
      ah div 10, ah mod 10,am div 10, am mod 10, as div 10, as mod 10,
      eh1 div 10, eh1 mod 10,em1 div 10, em1 mod 10, es1 div 10, es1 mod 10,
      eh2 div 10, eh2 mod 10, em2 div 10, em2 mod 10, es2 div 10, es2 mod 10
              ], i, 2) );
      
      % 2nd time span is 23 minutes longer than the 1st time span
      constraint (e1_sec - a_sec) ==  (e2_sec - e1_sec) - 23 * 60;
      
      solve satisfy;
      
      output  [ "Time are in format [hh mm ss] " ++ "\n" ++
      show ([ah, am, as])  ++ " " ++ show(a_sec) ++ " total sec"
      ++"\n" ++ show([eh1, em1, es1]) ++ " " ++ show(e1_sec) ++ " total sec"
      ++"\n" ++ show([eh2, em2, es2]) ++ " " ++ show(e2_sec) ++ " total sec"
      ++"\n" ++ "George woke up after his first sleep at " 
      ++ show(eh1) ++ ":" ++ show(em1) ++ ":" ++ show(es1)  ];
      
      % Time are in format [hh mm ss] 
      % [16, 27, 39] 59259 total sec
      % [19, 56, 48] 71808 total sec
      % [23, 48, 57] 85737 total sec
      % George woke up after his first sleep at 19:56:48
      % ----------
      % Time are in format [hh mm ss] 
      % [16, 28, 37] 59317 total sec
      % [19, 56, 48] 71808 total sec
      % [23, 47, 59] 85679 total sec
      % George woke up after his first sleep at 19:56:48
      % ----------
      % ==========
      
      
      

      Like

  • Unknown's avatar

    Jim Randell 10:30 am on 6 September 2019 Permalink | Reply
    Tags:   

    Teaser 2804: Spots before the eyes 

    From The Sunday Times, 19th June 2016 [link] [link]

    At the opticians I was shown a sequence of six screens. On each there was a different number of spots ranging from 0 to 5 and I had to say how many I thought I could see. This was done with the left eye and then repeated with the right. The optician always used the same sequence and my answers were:

    (5 2 3 4 4 3)
    (4 1 4 5 2 3)

    In each case I got two correct. When I asked if this was the worst he’d seen, the optician showed me these three earlier sets of answers in which just one was correct in each:

    (2 2 1 2 1 4)
    (3 3 2 3 5 1)
    (0 4 5 1 3 2)

    What was the correct sequence?

    [teaser2804]

     
    • Jim Randell's avatar

      Jim Randell 10:33 am on 6 September 2019 Permalink | Reply

      Programatically we can consider all possible orderings of the numbers from 0 to 5, and look for a sequence that gives the appropriate number of matches in the 5 cases.

      This Python program runs in 39ms.

      Run: [ @repl.it ]

      from enigma import subsets, irange, printf
      
      # sequences, values to check
      ss = (
        ((5, 2, 3, 4, 4, 3), 2),
        ((4, 1, 4, 5, 2, 3), 2),
        ((2, 2, 1, 2, 1, 4), 1),
        ((3, 3, 2, 3, 5, 1), 1),
        ((0, 4, 5, 1, 3, 2), 1),
      )
      
      # count matches
      def check(s1, s2):
        return sum(a == b for (a, b) in zip(s1, s2))
      
      # consider possible sequences
      for s in subsets(irange(0, 5), size=len, select="P"):
        if all(check(s, t) == n for (t, n) in ss):
          printf("{s}")
      

      Solution: The correct sequence is (4 2 0 1 5 3).

      Like

    • GeoffR's avatar

      GeoffR 11:00 am on 6 October 2020 Permalink | Reply

      
      % A Solution in MiniZinc 
      include "globals.mzn";
      
      % Correct sequence is A,B,C,D,E,F
      var 0..5: A; var 0..5: B; var 0..5: C; var 0..5: D;
      var 0..5: E; var 0..5: F;
      
      constraint all_different ([A,B,C,D,E,F]);
      
      % Two sequences with two correct answers
      % Sequence 1 - 5 2 3 4 4 3
      constraint sum ([A==5,B==2,C==3,D==4,E==4,F==3]) == 2;
      
      % Sequence 2 - 4 1 4 5 2 3
      constraint sum ([A==4,B==1,C==4,D==5,E==2,F==3]) == 2;
      
      % Three sequences with one correct answers
      % Sequence 3 - 2 2 1 2 1 4)
      constraint sum ([A==2,B==2,C==1,D==2,E==1,F==4]) == 1;
      
      % Sequence 4 - (3 3 2 3 5 1)
      constraint sum ([A==3,B==3,C==2,D==3,E==5,F==1]) == 1;
      
      % Sequence 5 - (0 4 5 1 3 2)
      constraint sum ([A==0,B==4,C==5,D==1,E==3,F==2]) == 1;
      
      solve satisfy;
      
      output ["Correct sequence = " ++ show([A,B,C,D,E,F]) ];
      
      % Correct sequence = [4, 2, 0, 1, 5, 3]
      % ----------
      % ==========
      
      
      

      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