Updates from May, 2019 Toggle Comment Threads | Keyboard Shortcuts

  • Unknown's avatar

    Jim Randell 8:16 pm on 31 May 2019 Permalink | Reply
    Tags:   

    Teaser 2958: Sudoku crossword 

    From The Sunday Times, 2nd June 2019 [link] [link]

    George and Martha are doing a mathematical crossword. There is a 3×3 grid with the numbers 1 to 9 inclusive appearing once each. The clues are as follows:

    Across:
    top line: a prime number
    middle line: a prime number
    bottom line: a prime number

    Down:
    left column: a perfect square
    middle column: a perfect square
    right column: a prime number

    Although you do not need to know this, one of the diagonal three-digit numbers is also prime.

    What is the sum of the three “across” numbers?

    [teaser2958]

     
    • Jim Randell's avatar

      Jim Randell 8:18 pm on 31 May 2019 Permalink | Reply

      We can solve this using the [[ SubstitutedExpression() ]] solver from the enigma.py library.

      This run file executes in 180ms.

      Run: [ @repl.it ]

      #! python -m enigma -rr
      
      # consider the grid:
      #
      #  A B C
      #  D E F
      #  G H I
      
      SubstitutedExpression
      
      --digits="1-9"
      
      "is_prime(ABC)"
      "is_prime(DEF)"
      "is_prime(GHI)"
      
      "is_square(ADG)"
      "is_square(BEH)"
      "is_prime(CFI)"
      
      --answer="ABC + DEF + GHI"
      

      Solution: The sum of the three across numbers is 1449.

      The grid is:

      2 8 3
      5 4 7
      6 1 9

      The across numbers are: 283 (prime), 547 (prime), 619 (prime), and their sum is 1449.

      The down numbers are: 256 (square), 841 (square), 379 (prime), and their sum is 1476.

      The diagonals can be read (left to right) as 249 and 643, and the second of these is prime.

      There are no further solutions if the digit 0 is not excluded.

      Like

    • GeoffR's avatar

      GeoffR 8:43 am on 21 June 2019 Permalink | Reply

      
      % A Solution in MiniZinc
      include "globals.mzn"; 
      
      %  Grid
      %  A B C
      %  D E F
      %  G H I
      
      var 1..9:A; var 1..9:B; var 1..9:C; 
      var 1..9:D; var 1..9:E; var 1..9:F; 
      var 1..9:G; var 1..9:H; var 1..9:I; 
      
      constraint all_different ( [A,B,C,D,E,F,G,H,I]);
      
      % Rows
      var 100..999: ABC = 100*A + 10*B + C;
      var 100..999: DEF = 100*D + 10*E + F;
      var 100..999: GHI = 100*G + 10*H + I;
      
      % Columns
      var 100..999: ADG = 100*A + 10*D + G;
      var 100..999: BEH = 100*B + 10*E + H;
      var 100..999: CFI = 100*C + 10*F + I;
      
      predicate is_prime(var int: x) = 
      x > 1 /\ forall(i in 2..1 + ceil(sqrt(int2float(ub(x))))) 
      ((i < x) -> (x mod i > 0));
      
      set of int: sq3 = {n*n | n in 10..31};
      
      % Rows
      constraint is_prime(ABC) /\ is_prime(DEF) /\ is_prime(GHI);
      
      % Columns
      constraint ADG in sq3 /\ BEH in sq3 /\ is_prime(CFI);
      
      solve satisfy;
      
      output [ "Rows total is "++ show(ABC + DEF + GHI) ]
      ++ [ "\nRows are "++ show(ABC)  ++ ", " ++ show(DEF) ++ 
      " and " ++ show (GHI) ];
      
      % Rows total is 1449
      % Rows are 283, 547 and 619
      % time elapsed: 0.02 s
       %----------
      % ==========
      % Finished in 253msec
      

      Like

  • Unknown's avatar

    Jim Randell 10:39 pm on 24 May 2019 Permalink | Reply
    Tags:   

    Teaser 2957: Beyond the fields we know 

    From The Sunday Times, 26th May 2019 [link] [link]

    A field named “Dunsany levels” has four unequal straight sides, two of which are parallel. Anne — with her dog, Newton — walked from one corner of the field straight towards her opposite corner. Leon did the same from an adjacent corner along his diagonal. Yards apart, they each rested, halfway along their paths, where Leon, Anne and a signpost in the field were perfectly aligned. Straight fences from each corner converged at the signpost, making four unequal-area enclosures.

    Newton made a beeline for the signpost, on which the whole-number area of the field, in acres, was scratched out. Clockwise, the enclosures were named: “Plunkett’s bawn”, “Three-acre meadow”, “Drax sward” and “Elfland lea”. Anne knew that “Three-acre meadow” was literally true and that “Elfland lea” was smaller by less than an acre.

    What was the area of “Dunsany levels” in acres?

    [teaser2957]

     
    • Jim Randell's avatar

      Jim Randell 11:03 pm on 24 May 2019 Permalink | Reply

      The field is a trapezium (trapezoid in US terminology).

      By drawing a diagram of the layout we determine that there is only a limited range of possible values for the area of Elfland Lea, and only one of which gives a whole number for the total area of the field.

      Solution: The total area of the field is 11 acres.

      Here is my analysis:

      We can draw the trapezium, ABCD, with the parallel sides horizontal, and we get a diagram like this:

      I assumed that “halfway” meant exactly at the midpoint.

      The midpoints of the diagonals AC and BD are exactly half way between the parallel lines AB and CD, so the signpost lies on the line XY (and obviously within the field).

      If we suppose the trapezium has a height of 2h, then the line XY is a distance h from both AB and CD.

      Now if we suppose the signpost S lies somewhere on this line:

      If the length of AB is q and the length of CD is p, and the trapezium has a height of 2h, then the area of the trapezium is:

      area(ABCD) = (p + q)h = ph + qh

      And the area of the triangles ABS and CDS are:

      area(ABS) = qh/2
      area(CDS) = ph/2

      (and the exact position of S does not matter, as long as it is on line XY).

      So it follows that the combined area of the triangles ADS and BCS is:

      area(ADS) + area(BCS) = ph/2 + qh/2

      (the same as the combined area of triangles ABS and CDS).

      And one of these pairs consists of “Three-acre meadow” and “Elfland lea”. So one enclosure is exactly 3 acres, and the other is somewhere between 2 and 3 acres (excluding the endpoints), so the combined area of these two enclosures is between 5 and 6 acres (excluding the endpoints).

      The total area of the field is twice this value, so it is an integer between 10 and 12 (excluding the endpoints). The answer follows directly, without the need to write a program.

      Like

  • Unknown's avatar

    Jim Randell 4:50 pm on 16 May 2019 Permalink | Reply
    Tags:   

    Teaser 2956: A nice little earner 

    From The Sunday Times, 19th May 2019 [link] [link]

    The “value” of a number is found by subtracting its first digit from the last. For example, 6, 72, 88 and 164 have values 0, −5, 0 and 3 respectively.

    Raising funds for a local charity, I placed some raffle tickets numbered from 1 up to a certain 3-digit number, in a box. Participants then selected a ticket at random. If the value of their number was positive, they won that amount in £; if the value was negative, they contributed that [positive] amount in £. Otherwise no money changed hands.

    All the tickets having been used, the total amount raised in £ was a rearrangement of the digits in that number of tickets.

    How much was raised?

    [teaser2956]

     
    • Jim Randell's avatar

      Jim Randell 4:51 pm on 16 May 2019 Permalink | Reply

      If the “value” is positive, we have to pay the ticket holder that amount. If it is negative, the ticket holder pays us. And if the value is zero nothing happens.

      So in each case we lose an amount equal to the “value” of the ticket.

      This Python program subtracts the values of the tickets, until we have a positive amount that can be rearranged to give the ticket number.

      Run: [ @repl.it ]

      from enigma import (irange, nsplit, printf)
      
      # total amount raised
      t = 0
      
      # consider ticket numbers (up to a max 3-digit value)
      for n in irange(1, 999):
        # split the number into digits
        ds = nsplit(n)
        # calculate the "value" of the number
        v = ds[-1] - ds[0]
        t -= v
        # solution when the total raised has the digits of n
        if t > 0 and n > 99 and sorted(nsplit(t)) == sorted(ds):
          printf("n={n} t={t}")
      

      Solution: £249 was raised.

      The number of tickets is 942.

      The next solution occurs with 91,727 tickets, and £12,779 raised.

      Like

  • Unknown's avatar

    Jim Randell 5:03 pm on 9 May 2019 Permalink | Reply
    Tags:   

    Teaser 2955: Go forth and multiply 

    From The Sunday Times, 12th May 2019 [link] [link]

    Adam and Eve have convex hexagonal gardens whose twelve sides are all the same whole number length in yards. Both gardens have at least two right-angled corners and the maximum possible area this allows. Each garden has a path from corner to corner down an axis of symmetry. Adam multiplies the sum of the path lengths by the difference of the path lengths (both in yards) and Eve squares Adam’s answer, getting a perfect fifth power with no repeated digit.

    What was Eve’s answer?

    See also: Teaser 2946.

    [teaser2955]

     
    • Jim Randell's avatar

      Jim Randell 5:28 pm on 9 May 2019 Permalink | Reply

      Once you’ve worked out the shapes involved, you find that Eve’s answer is 8x^4, and a simple program (or a simple guess) lets us find the appropriate answer.

      Run: [ @repl.it ]

      from enigma import (irange, inf, is_duplicate, is_power, printf)
       
      # consider the length of the side
      for x in irange(1, inf):
        E = 8 * x**4
        if E > 9876543210: break
        if is_duplicate(E): continue
        if not is_power(E, 5): continue
        printf("E={E} [x={x}]")
      

      Solution: Eve’s answer was 32768.

      Like

      • Jim Randell's avatar

        Jim Randell 9:08 am on 12 May 2019 Permalink | Reply

        Here’s the analysis to work out the formula for Eve’s answer:

        If we consider a hexagon (with sides of unit length) that has a right angle at a given vertex, then we can’t have another right angle at an adjacent vertex, as it becomes impossible to construct a convex hexagon if we do.

        So, we need only consider a pair of right angles separated by 1 or 2 intermediate vertices.

        Taking the case with 2 intermediate vertices we get a hexagon that looks like this:

        The length of the diagonal being (1 + √2).

        In the case with only 1 intermediate vertex we get a hexagon that looks like this:

        If the angle XYZ is θ, then the area of the triangle XYZ is given by:

        area(XYZ) = ((√2)/2)sin(θ)

        which is at a maximum when sin(θ) = 1, i.e. θ = 90°.

        And the length of the diagonal d = √3.

        So, for hexagons with side x, the two diagonals have lengths:

        (1 + √2)x
        (√3)x

        Adam’s value (the sum multiplied by the difference) is:

        A = (1 + √2 + √3)x(1 + √2 − √3)x
        A = 2(√2)x²

        And Eve’s value is the square of this:

        E = 8x⁴

        And we are told E is an exact power of 5.

        Choosing x = 8 gives E = 8⁵ = 32768, which has five different digits as required.

        Like

        • Jim Randell's avatar

          Jim Randell 10:46 pm on 12 May 2019 Permalink | Reply

          For completeness:

          The general case of the first hexagon (with right angles separated by two vertices) is a shape like this:

          The red line bisects the hexagon into two identical shapes (by rotation), but in general is not a line of reflective symmetry.

          Again the area of the triangle XYZ is given by the formula:

          area(XYZ) = ((√2)/2)sin(θ)

          and so the maximum area is achieved when sin(θ) = 1, i.e. θ = 90°.

          Which gives us the diagram originally presented (where the red line is a line of reflective symmetry).

          So both gardens have the same area, being composed of two (1, 1, √2) triangles and two (1, √2, √3) triangles. Giving a total area of (1 + √2).

          Like

  • Unknown's avatar

    Jim Randell 5:41 pm on 2 May 2019 Permalink | Reply
    Tags:   

    Teaser 2954: Lovely meter, RITA made! 

    From The Sunday Times, 5th May 2019 [link] [link]

    Revisiting the old curiosity shop, I bought an unusual moving-iron ammeter (made by Rho Iota Tau Associates). On the non-linear scale “9” was the last possible “whole amperes” scale graduation marked before the “full scale deflection” end stop (which was a half turn of the pointer from zero).

    The booklet gave the pointer swing from zero (in degrees) equal to the current (in amperes) raised to a fixed single-figure positive whole number power, then divided by a positive whole number constant. Curiously, the angle between “exact” pointer swings, calculated using this formula, for two single-figure “whole amperes” values was exactly a right angle.

    What, in amperes, were these two currents (lower first) and to what power were they raised?

    [teaser2954]

     
    • Jim Randell's avatar

      Jim Randell 5:44 pm on 2 May 2019 Permalink | Reply

      The title of the puzzle, of course, is a reference the song Lovely Rita by The Beatles.

      This Python program runs in 82ms.

      Run: [ @repl.it ]

      from enigma import (irange, subsets, div, fdiv, printf)
      
      # the deflection in degrees is d(x) = (x^n)/k
      
      # consider possible single figure powers n
      for n in irange(2, 9):
      
        # choose a and b the two single figure values
        for (a, b) in subsets(irange(0, 9), size=2):
      
          # determine the constant
          k = div(b**n - a**n, 90)
          if not k: continue
      
          # 9 amps -> deflection =< 180 degrees
          # 10 amps -> deflection > 180 degrees
          if not (9**n <= 180 * k < 10**n): continue
          
          d = lambda x: fdiv(x**n, k)
          printf("n={n}, a={a} b={b}, k={k} [a->{da:.2f} b->{db:.2f} 9->{d9:.2f} 10->{d10:.2f}]", da=d(a), db=d(b), d9=d(9), d10=d(10))
      

      Solution: The two currents are 3 A and 9 A. They are raised to the power of 8.

      So the formula for the deflection (in degrees) as a function of the current (in amps) is:

      d(x) = (x^8) / 478224

      Giving the corresponding readings for currents from 0 to 10 amps:

       0 A →   0.000°
       1 A →   0.000°
       2 A →   0.001°
       3 A →   0.014° (d = 9/656)
       4 A →   0.137°
       5 A →   0.817°
       6 A →   3.512°
       7 A →  12.055°
       8 A →  35.082°
       9 A →  90.014° (d = 90 + 9/656)
      10 A → 209.107° (d > 180)

      So if you want to read small currents you had better be good at measuring very small angles.

      There are two further solutions for single digit powers and single digit currents that give a difference of exactly 90°.

      These are:

      d(x) = (x^4) / 72; for 3A and 9A
      d(x) = (x^6) / 2912; for 2A and 8A

      But these are disallowed by the condition that 9A should be on the scale and 10A off the scale. In the first case both 9A and 10A are on the scale, in the second case they are both off the scale. But they would be solutions to similar puzzles where the scale goes to 10A (but not 11A), or 8A (but not 9A), respectively.

      Like

  • Unknown's avatar

    Jim Randell 8:01 am on 26 April 2019 Permalink | Reply
    Tags:   

    Teaser 2953: Marble tower 

    From The Sunday Times, 28th April 2019 [link] [link]

    Liam has a number of bags of marbles; each bag contains the same number (more than 1) of equal-size marbles.

    He is building a tetrahedron with the marbles, starting with a layer which fits snugly in a snooker triangle. Each subsequent triangular layer has one fewer marble along each edge. With just one bag left he had completed a whole number of layers; the number of marbles along the edge of the triangle in the last completed layer was equal to the number of completed layers. The last bag had enough marbles to just complete the next layer.

    How many bags of marbles did Liam have?

    [teaser2953]

     
    • Jim Randell's avatar

      Jim Randell 8:24 am on 26 April 2019 Permalink | Reply

      This Python program runs in 85ms.

      Run: [ @repl.it ]

      from enigma import (irange, inf, T, div, printf)
      
      # P(n) = the nth tetrahedral number
      P = lambda n: (n * (n + 1) * (n + 2)) // 6
      
      def solve():
        # suppose there are n bags, each containing k marbles
        # there are enough marbles in the final bag to complete a layer
        # so the number of marbles in a bag is a triangular number
        for x in irange(2, inf):
          k = T(x)
      
          # and there must be (x + 1) completed layers
          # and layers T(x + 1) ... T(2x + 1) have used (n - 1) k marbles
          # so: P(2x + 1) - P(x) = (n - 1) k
          # solve for (n - 1)
          n = div(P(2 * x + 1) - P(x), k)
          if n:
            yield (k, n + 1, x)
      
      for (k, n, x) in solve():
        printf("{n} bags, each containing {k} marbles, layers 1 - {x} (of {t}) remaining", t=2 * x + 1)
        break
      

      Solution: There were 20 bags of marbles.


      We can simplify the equation:

      P(2x + 1) − P(x) = (n − 1)T(x)

      to:

      n = 7x/3 + 17/3 + 2/x

      For integer x the first two terms give us a whole number of thirds, so the 2/x term must also provide a whole number of thirds, i.e. x = 1, 2, 3, or 6.

      And the only values to give an integer value for n are:

      x = 1, n = 10
      x = 6, n = 20

      There are T(x) marbles in each of the n bags, and this is more than 1, so this eliminates the first solution leaving, T(6) = 21 marbles in each of the 20 bags.

      Here’s a Python program that uses the analysis:

      from enigma import (div, printf)
      
      for x in [2, 3, 6]:
        n = div((7 * x + 17) * x + 6, 3 * x)
        if n:
          printf("n={n} [x={x}]")
      

      Like

  • Unknown's avatar

    Jim Randell 8:57 am on 16 April 2019 Permalink | Reply
    Tags:   

    Teaser 2952: Silly slip 

    From The Sunday Times, 21st April 2019 [link] [link]

    Please help me find my silly slip. I correctly added a five-figure number to a four-figure number to give a six-figure total. Then I tried to substitute letters for digits systematically and I ended up with:

    SILLY + SLIP = PLEASE

    However, in these letters I have made one silly slip, so please find it and then work out what the correct sum was.

    What was the correct six-figure numerical answer?

    This puzzle appears in the books The Sunday Times Brain Teasers 1 (2019) and The Sunday Times Teasers Book 1 (2021).

    [teaser2952]

     
    • Jim Randell's avatar

      Jim Randell 8:58 am on 16 April 2019 Permalink | Reply

      We can use the [[ bungled_sum() ]] solver (originally written for Puzzle 56).

      Run: [ @replit ]

      >>> bungled_sum(['SILLY', 'SLIP', 'PLEASE'])
                      L
      SILLY + SLIP = P?EASE / @[2,1] L -> ?
      97225 + 9271 = 106496 / ?=0 A=4 E=6 I=7 L=2 P=1 S=9 Y=5
      

      Solution: The numerical result of the sum is 106496.

      The mistake is in the L of PLEASE (the result of the sum), it should be a letter that is different from all the other letters, although that does make it hard to make an acceptable word, but we can check this makes a viable alphametic sum using the [[ SubstitutedSum() ]] solver from the enigma.py library.

      % python enigma.py SubstitutedSum "SILLY + SLIP = PXEASE"
      (SILLY + SLIP = PXEASE)
      (97225 + 9271 = 106496) / A=4 E=6 I=7 L=2 P=1 S=9 X=0 Y=5
      

      Like

      • Jim Randell's avatar

        Jim Randell 4:06 pm on 20 April 2019 Permalink | Reply

        I assumed this puzzle was in the same vein as other “bungled sum” problems.

        But the text says that letters are substituted for digits “systematically”, but it doesn’t say that each letter stands for a different digit (which is usual in alphametic puzzles).

        If we allow letters to stand for the same digit, then we can solve the alphametic sum:

        % python enigma.py SubstitutedExpression "SILLY + SLIP = PLEASE" --distinct=""
        (SILLY + SLIP = PLEASE)
        (99007 + 9091 = 108098) / A=0 E=8 I=9 L=0 P=1 S=9 Y=7
        [1 solution]
        

        The duplicated digits are: A and L are both 0, I and S are both 9.

        Like

      • Jim Randell's avatar

        Jim Randell 11:01 pm on 21 April 2019 Permalink | Reply

        Here is a faster (but longer) solution, using the minizinc.py library.

        from minizinc import (MiniZinc, var, alphametic, substitute)
        
        # the sum is a 5-digit number plus a 4-digit number and a 6-digit result
        #
        #    a b c d e      S I L L Y
        #      f g h i        S L I P
        #  -----------    -----------
        #  j k m n p q    P L E A S E
        
        fmt = "{abcde} + {fghi} = {jkmnpq}"
        
        # create the model
        p = MiniZinc(f"""
        
        include "globals.mzn";
        
        % the symbols in the incorrect sum
        {var("0..9", "AEILPSY")};
        
        constraint all_different([A, E, I, L, P, S, Y]);
        
        % symbols for the correct sum
        {var("0..9", "abcdefghijkmnpq")};
        
        % the correct sum
        constraint {alphametic(fmt)};
        
        % no leading zeros
        constraint a != 0 /\ f != 0 /\ j != 0;
        
        % the incorrect sum differs in only one place
        constraint sum([
          a != S, b != I, c != L, d != L, e != Y,
          f != S, g != L, h != I, i != P,
          j != P, k != L, m != E, n != A, p != S, q != E,
        ]) = 1;
        
        solve satisfy;
        
        """)
        
        # solve it
        for s in p.solve():
          # output the sum
          print(substitute(fmt, s))
        

        Like

  • Unknown's avatar

    Jim Randell 11:29 pm on 11 April 2019 Permalink | Reply
    Tags:   

    Teaser 2951: Imprismed 

    From The Sunday Times, 14th April 2019 [link] [link]

    A right regular prism has two ends with identical faces, joined by oblong rectangular faces. I have eight of them, with regular convex polygonal end-faces of 3, 4, 5, 6, 7, 8, 9 and 10 sides (triangle, square and so on). They sit on my flat desk (on oblong faces), and each prism has the same height.

    I chose three prisms at random, and was able to slide them into contact, broadside, in such a way that the middle one overhung both others (and could be lifted without disturbing them). Also, I was able to slide one outer prism to the other side, and the new “middle” prism was overhung by both others (and so vertically “imprisoned” by them).

    I was able to do all this again with three randomly chosen remaining prisms.

    Give the prior chance of this double selection (as a fraction in lowest terms).

    This puzzle appears in the books The Sunday Times Brain Teasers 1 (2019) and The Sunday Times Teasers Book 1 (2021).

    [teaser2951]

     
    • Jim Randell's avatar

      Jim Randell 11:30 pm on 11 April 2019 Permalink | Reply

      I’m not a great fan of this kind of puzzle. Partly because I don’t like probability much, but also because it is not easy to check that the answer you get works.

      I also think the wording for this particular puzzle could have been clearer. I started out with an incorrect interpretation, and got a different answer. If we consider the selection of an appropriate “special” set of three prisms (that can be arranged in the manner described in the puzzle text), then I think the puzzle is asking for the probability of selecting two consecutive “special” sets from the 8 prisms.

      Here is a Python program which works out the solution in 75ms.

      Run: [ @replit ]

      from enigma import (subsets, diff, ordered, fraction, printf)
      
      # prisms that project over another prism when placed side by side
      overhangs = {
        3: [],
        4: [],
        5: [3, 6, 7, 9, 10],
        6: [3, 7],
        7: [3],
        8: [3],
        9: [3, 6, 7, 10],
        10: [3, 7],
      }
      
      # over(x, y) = "x goes over y"
      over = lambda x, y: y in overhangs[x]
      
      # possible prisms
      prisms = sorted(overhangs.keys())
      
      # record special choices
      special = set()
      
      # choose the central prism
      for x in prisms:
        # and choose a left and right prism that are overhung by x
        for (l, r) in subsets(overhangs[x], size=2):
          # check there is a rearrangement that traps the new centre prism
          if over(l, r) or over(r, l):
            special.add(ordered(x, l, r))
      
      printf("{n} special sets", n=len(special))
      
      
      # record the total number of choices, and the number of that give two special sets
      t = n = 0
      
      # choose the first set of 3 prisms
      for s1 in subsets(prisms, size=3):
        # is it a special set?
        p1 = (ordered(*s1) in special)
      
        # choose the second set of 3 prisms
        for s2 in subsets(diff(prisms, s1), size=3):
          # is it a special set?
          p2 = (ordered(*s2) in special)
          if p1 and p2: n += 1
          t += 1
      
      # output the solution
      (a, b) = fraction(n, t)
      printf("chance = {n} / {t} = {a} / {b}")
      

      Solution: The probability of choosing two “special” sets is 3 / 140.


      Here is my analytical solution:

      There are 12 “special” arrangements (centre; outside) that allow a further “special” arrangement to be made from the remaining prisms. They group into 6 sets of mutually distinct pairs:

      (5; 3, 6) ↔ (9; 7, 10)
      (5; 3, 10) ↔ (9; 6, 7)
      (5; 6, 7) ↔ (9; 3, 10)
      (5; 6, 9) ↔ (10; 3, 7)
      (5; 7, 10) ↔ (9; 3, 6)
      (5; 9, 10) ↔ (6; 3, 7)

      There are also 4 “special” arrangements that do not allow a further “special” arrangement to be made:

      (5; 3, 7)
      (5; 3, 9)
      (5; 7, 9)
      (9; 3, 7)

      For the first choice of prisms there are C(8, 3) = 56 possible arrangements, and we must choose one of the arrangements that is part of a “special” pair.

      So, there is a probability of 12 / 56 = 3 / 14 of choosing a suitable first set of prisms.

      For the second choice there are C(8 − 3, 3) = 10 possible arrangements, but only one of these arrangements will be “special” – the arrangement that goes with the first choice to make one of the six “special” pairs given above.

      So overall probability of choosing two suitable sets is (3 / 14) × (1 / 10) = 3 / 140.

      Like

    • Robert Brown's avatar

      Robert Brown 7:44 am on 20 April 2019 Permalink | Reply

      Have you seen John Crabtree’s simple method? I’m also unhappy with probabilities, but wrote a simple program to count how many ways you can select 6 prisms from 8, and how many of these meet his algorithm. The ratio of these 2 numbers confirms the probability.

      Like

      • Jim Randell's avatar

        Jim Randell 2:39 pm on 20 April 2019 Permalink | Reply

        @Robert: Thanks for your comment.

        I try to provide a constructive solution where possible, so constructing the “special” sets, and then counting the number of desired outcomes from all possible outcomes seemed like the best way to understand the solution (and would be the approach least likely to contain a mistake). But it is good that other approaches are able to confirm the answer.

        For me the more difficult part was firstly interpreting what the puzzle was actually asking, and then constructing the “over” relation (to determine when one prism goes over another). Once that was done, counting the possibilities to come up with an answer was the easier part.

        I have got a manual approach to calculating the answer using probabilities, which I intend to post tomorrow along with the answer.

        I did also write code to run a million random trials in selecting six of the prisms to confirm the number I found (see the [[ teaser2951t.py ]] file on @replit).

        Like

    • Robert Brown's avatar

      Robert Brown 11:42 am on 22 April 2019 Permalink | Reply

      Jim
      I wasn’t being critical of your method, which corresponds to that used by the various people who solved it manually. Just drawing your attention to John’s clever method, which doesn’t use any lists – just a couple of rules. Rule one – 6 random selections don’t include 4 or 8 (probability 1/28) Rule 2 – dividing the 6 into 1st 3, then 2nd 3, prisms 6 & 10 must not be in the same group (probability 3/5).

      Like

      • Jim Randell's avatar

        Jim Randell 2:00 pm on 22 April 2019 Permalink | Reply

        It’s certainly neat. I suppose the issue I have is the need to demonstrate that the two rules generate exactly all possible pairs of “special” sets.

        Like

    • Robert Brown's avatar

      Robert Brown 7:42 am on 23 April 2019 Permalink | Reply

      After Rule 1, abc & def must use all of the other 6. Then after Rule 2 every pair within abc or def has one member overhanging the other.

      Like

  • Unknown's avatar

    Jim Randell 9:25 am on 5 April 2019 Permalink | Reply
    Tags:   

    Teaser 2950: Ten digits 

    From The Sunday Times, 7th April 2019 [link] [link]

    Without repeating a digit I have written down three numbers, all greater than one. Each number contains a different number of digits. If I also write down the product of all three numbers, then the total number of digits I have used is ten. The product contains two pairs of different digits, neither of which appear in the three original numbers.

    What is the product?

    This puzzle appears in the books The Sunday Times Brain Teasers 1 (2019) and The Sunday Times Teasers Book 1 (2021).

    [teaser2950]

     
    • Jim Randell's avatar

      Jim Randell 9:26 am on 5 April 2019 Permalink | Reply

      The product has to be long enough to accommodate two pairs of different digits in, so it must be at least 4 digits long.

      But the total multiplication sum only uses 10 digits, so the three original numbers can use at most 6 digits, and as the number of digits in each multiplicand is different they must use at least 6 digits, so the sum looks like one of these:

      A × BC × DEF = XXYY
      A × BC × DEF = XYXY
      A × BC × DEF = XYYX

      We can solve these using the [[ SubstitutedExpression() ]] solver from the enigma.py library (although it is not especially quick). The following run file executes in 619ms.

      Run: [ @replit ]

      #! python -m enigma -rr
      
      SubstitutedExpression
      
      --invalid="0,ABDX"
      --invalid="1,A"
      
      "A * BC * DEF in (XXYY, XYXY, XYYX)"
      
      --answer="A * BC * DEF"
      

      Solution: The product is 8778.

      The full sum is:

      3 × 14 × 209 = 8778

      The solution uses the XYYX pattern for the product, and is the only solution using that pattern.

      However, without the restriction that A is greater than 1 we can find a further solution using the XXYY pattern:

      1 × 36 × 275 = 9900

      And there are no solutions that use the remaining XYXY pattern. (This can be seen by observing that the product has a prime factor of 101, and we cannot have a three digit multiple of 101 that does not have repeated digits).

      Like

      • Jim Randell's avatar

        Jim Randell 10:35 am on 5 April 2019 Permalink | Reply

        Here is a faster solution in Python. It considers possible values for the result of the multiplication, and then factors the result into 1-,2-,3-digit numbers.

        It runs in 96ms.

        from enigma import (irange, subsets, divisors_pairs, nsplit, printf)
        
        # choose X and Y
        for (X, Y) in subsets(irange(0, 9), size=2, select='P'):
          if X == 0: continue
        
          # consider possible results
          for (i, j) in [(1100, 11), (1010, 101), (1001, 110)]:
            n = X * i + Y * j
        
            # find 1-, 2-, 3- digit factors of n
            for (A, m) in divisors_pairs(n):
              if A < 2: continue
              if A > 9: break
              if len(set((A, X, Y))) != 3: continue
        
              for (BC, DEF) in divisors_pairs(m):
                if BC < 10: continue
                if BC > 99: break
                if not (99 < DEF < 1000): continue
                (B, C) = nsplit(BC)
                (D, E, F) = nsplit(DEF)
                if len(set((A, B, C, D, E, F, X, Y))) != 8: continue
        
                # output solution
                printf("{A} * {BC} * {DEF} = {n}")
        

        Like

    • GeoffR's avatar

      GeoffR 11:28 am on 11 April 2019 Permalink | Reply

      % A Solution in MiniZinc
      include "globals.mzn";
      
      % three numbers are A, BC and DEF, plus 2 digit pairs from X and Y
      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:X; var 0..9:Y;
      
      constraint A > 1 /\ B > 0 /\ D > 0 /\ X > 0 /\ Y > 0;
      constraint all_different ([ A, B, C, D, E, F, X, Y]);
       
      var 10..99: BC = 10*B + C;
      var 100..999: DEF = 100*D + 10*E + F;
      
      % possible arrangements of product are XXYY, XYXY and XYYX
      constraint (A * BC * DEF) == (1000*X + 100*X + 10*Y + Y) 
      \/ (A * BC * DEF) == (1000*X + 100*Y + 10*X + Y) 
      \/ (A * BC * DEF) == (1000*X + 100*Y + 10*Y + X); 
      
      solve satisfy;
      
      output [ "Product = " ++ show(A * BC * DEF) ];
      
      

      Like

    • GeoffR's avatar

      GeoffR 8:58 am on 8 February 2024 Permalink | Reply

      
      # Sum digit pattern is A × BC × DEF = XXYY, XYXY or XYYX
      # LHS of sum
      for A in range(2, 10):
        for BC in range(12, 99):
          B, C = BC //10, BC % 10
          if A in (B, C):continue
          for DEF in range(123, 988):
            D, E, F = DEF // 100, DEF // 10 % 10, DEF % 10
            if len({A, B, C, D, E, F}) == 6:
                
              # RHS of  sum
              prod = A * BC * DEF
              if not 1000 < prod < 9999:continue
              M, N = prod // 1000, prod // 100 % 10
              P, Q = prod // 10 % 10, prod % 10
              # Digit pattern of MNPQ is XXYY, XYXY or XTTX
              if len({M, N, P, Q}) == 2:
                if (M == N and P == Q) or (M == P and N == Q) \
                   or (M == Q and N == P):   
                 if len({A, B, C, D, E, F, M, N, P, Q}) == 8:   
                    print(f"Sum: {A} x {BC} x {DEF} = {prod}.")
      
      # Sum: 3 x 14 x 209 = 8778.
      

      Like

    • Frits's avatar

      Frits 3:21 pm on 8 February 2024 Permalink | Reply

          
      # dictionary of product a * bc with different digits (not ending on 1)
      d = dict()
      for i in range(2, 10):
        for j in range(10, 50):
          if i < j and i * j < 100 and (i * j) % 10 != 1 and j % 10 and \
             len(set(ij := str(i) + str(j))) == len(ij):
            d[i * j] = d.get(i * j, []) + [(str(i), str(j))] 
                   
      # A * BC * DEF = RHS
      # RHS = XYXY is not possible as XYXY is a multiple of 101
      
      # A number is divisible by 11 if the difference between the sum of its digits
      # in odd places and the sum of the digits in even places is either 0 or 
      # a multiple of 11
      # thus RHS is a multiple of 11 for XXYY and XYYX
      for i in range(10, 91):
        DEF = 11 * i
        sDEF = str(DEF)
        if sDEF[-1] == '0' or len(set(sDEF)) != 3: continue
        
        # ABC * DEF = RHS
        for ABC in range(max(20, (999 // DEF) + 1), (9999 // DEF) + 1):
          sRHS = str(ABC * DEF)
          
          if len(set(sRHS)) != 2 or any(x in sRHS for x in sDEF) or \
             sRHS.count(sRHS[0]) != 2: continue
          
          # is ABC a valid product
          if ABC not in d: continue  
          for a, b in d[ABC]: 
            # different digits
            if len(set(s := (a + b + sDEF + sRHS))) != len(s) - 2: continue 
            print(f"answer: {sRHS} ({a} * {b} * {DEF})")  
      

      Like

  • Unknown's avatar

    Jim Randell 8:10 am on 31 March 2019 Permalink | Reply
    Tags:   

    Teaser 2949: Mystery numbers 

    From The Sunday Times, 31st March 2019 [link] [link]

    I wrote down a 2-digit number and a 5-digit number and then carried out a long division.

    I then erased all of the digits in the calculation, other than one of them, which I have indicated by X.

    This gave me the image above.

    What were my two original numbers?

    [teaser2949]

     
    • Jim Randell's avatar

      Jim Randell 8:15 am on 31 March 2019 Permalink | Reply

      We can feed this problem directly to the [[ SubstitutedDivision() ]] solver from the enigma.py library.

      This run file executes in 153ms.

      Run: [ @repl.it ]

      #! python -m enigma -rr
      
      SubstitutedDivision
      
      "XX??X / ?X = ????"
      
      "XX - ?X = ??"
      "??? - ?? = ??"
      "??? - ?X? = ?"
      "?X - ?X = 0"
      

      Solution: The two original numbers were: 23 and 33603.

      Like

      • Jim Randell's avatar

        Jim Randell 4:32 pm on 31 March 2019 Permalink | Reply

        Although the run file given above does find the correct answer, which can be verified by inspection. I think there is a little bit more work to do to ensure that the erased digits are all different from the digit X.

        Here is a run file that uses symbols for the erased digits (instead of the wildcard “?”), and includes an extra check to make sure they are all different from X.

        #! python -m enigma -rr
        
        #          D E F G
        #      -----------
        #  C X ) X X A B X
        #        H X
        #        ---
        #        I J A
        #          K M
        #        -----
        #          N P B
        #          Q X R
        #          -----
        #              S X
        #              S X
        #              ===
        
        SubstitutedDivision
        
        "XXABX / CX = DEFG"
        
        "XX - HX = IJ"
        "IJA - KM = NP"
        "NPB - QXR = S"
        "SX - SX = 0"
        
        --distinct="XA,XB,XC,XD,XE,XF,XG,XH,XI,XJ,XK,XM,XN,XP,XQ,XR,XS"
        

        Like

    • GeoffR's avatar

      GeoffR 12:34 pm on 21 April 2019 Permalink | Reply

      % A Solution in MiniZinc  
      include "globals.mzn";
      
      %           D E F G
      %       -----------
      %   C X ) X X A B X
      %         H X
      %         ---
      %         I J A
      %           K M
      %         -----
      %           N P B
      %           Q X R
      %           -----
      %               S X
      %               S X
      %               ===
      
      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;
      var 0..9:K; var 0..9:M; var 0..9:N; var 0..9:P; var 0..9:Q;
      var 0..9:R; var 0..9:S; var 0..9:X; 
      
      constraint D > 0 /\ C > 0 /\ X > 0 /\ I > 0 /\ K > 0 
      /\ N > 0 /\ Q > 0 /\ S > 0;
      
      var 10..99: XX = 11*X;
      var 10..99: HX = 10*H + X;
      
      var 10..99: CX = 10*C + X;
      var 10..99: KM = 10*K + M;
      var 10..99: IJ = 10*I + J;
      var 10..99: NP = 10*N + P;
      var 10..99: SX = 10*S + X;
      
      var 100..999: XXA = 110*X + A;
      var 100..999: IJA = 100*I + 10*J + A;
      var 100..999: NPB = 100*N + 10*P + B;
      var 100..999: QXR = 100*Q + 10*X + R;
      
      var 1000..9999: DEFG = 1000*D + 100*E + 10*F + G;
      var 10000..99999: XXABX = 11001*X + 100*A + 10*B;
      
      % main sum
      constraint CX * DEFG == XXABX;
      
      % partial products and subtractions
      constraint D * CX == HX /\ XX - HX == IJ;
      
      constraint E * CX == KM /\ IJA - KM == NP;
      
      constraint F * CX == QXR /\ NPB - QXR == S;
      
      constraint G * CX == SX;
      
      solve satisfy;
       
      % A = 6; B = 0; C = 2; D = 1; E = 4; F = 6; G = 1;
      % H = 2; I = 1; J = 0; K = 9; M = 2; N = 1; P = 4;
      % Q = 1; R = 8; S = 2; X = 3;
      % ----------
      % ==========
      % Finished in 271msec
      
      % The only full division sum is :
      
      %        1 4 6 1
      %     -----------     
      %  2 3)3 3 6 0 3
      %      2 3
      %      ---
      %      1 0 6
      %        9 2
      %      -----
      %        1 4 0
      %        1 3 8
      %        -----
      %            2 3
      %            2 3
      %            ===     
      % My two original numbers were therefore 23 and 33603.
      

      Like

  • Unknown's avatar

    Jim Randell 6:36 am on 24 March 2019 Permalink | Reply
    Tags:   

    Teaser 2948: A hardy annual 

    From The Sunday Times, 24th March 2019 [link] [link]

    Yesterday was my grandson’s birthday and we continued a family tradition. I asked him to use any eight different non-zero digits (once each) to form a set of numbers that added to 2019. Last year I asked the equivalent question with a sum of 2018, and I have done this each year for over ten years. Only on one occasion has he been unable to complete the task.

    In this year’s answer his set of numbers included a 3-figure prime that had also featured in last year’s numbers.

    (a) In which year was he unable to complete the task?

    (b) What was the 3-figure prime that featured in this year’s answer?

    [teaser2948]

     
    • Jim Randell's avatar

      Jim Randell 7:48 am on 24 March 2019 Permalink | Reply

      I assumed the numbers are formed only by concatenation of digits, and not any other method.

      This Python program considers the number of digits present in each column of the sum to construct viable solutions.

      It runs in 84ms.

      Run: [ @repl.it ]

      from itertools import (combinations, product)
      from enigma import (nsplit, irange, nconcat, is_prime, printf)
      
      # different ways to construct the sum (for the years under consideration)
      # (number of digits in each column)
      exprs = [ (1, 2, 2, 3), (1, 1, 3, 3), (1, 1, 2, 4), (1, 1, 1, 5) ]
      
      # solve for the end column
      def _solve(ds, expr, digits, c, ss):
        # are we done?
        if not ds:
          # check there is no carry
          if c == 0:
            yield ss
        else:
          # consider digits for this columns
          for s in combinations(digits, expr[-1]):
            (c1, r) = divmod(sum(s) + c, 10)
            # check the sum matches the desired result
            if r == ds[-1]:
              # solve for the remaining columns
              yield from _solve(ds[:-1], expr[:-1], digits.difference(s), c1, [s] + ss)
      
      # find solutions for result n
      # return (<construction>, <digits>)
      def solve(n):
      
        # split the result into digits
        ds = nsplit(n)
      
        # digits to use (can remove (9 - digrt(n)))
        digits = set(irange(1, 9))
      
        # try to solve for each construction
        for expr in exprs:
          for ss in _solve(ds, expr, digits, 0, []):
            yield (expr, ss)
      
      # return 3-digit primes involved in solutions
      def collect(ss):
        r = set()
        for (expr, s) in ss:
          if expr != (1, 2, 2, 3): continue
          for ds in product(s[1], s[2], s[3]):
            n = nconcat(ds)
            if is_prime(n):
              r.add(n)
        return r
      
      # there must be a non-viable year in the last 11 years
      for n in irange(2019, 2009, step=-1):
        ss = list(solve(n))
      
        # are there any solutions?
        if not ss:
          printf("(a) {n} has no viable solutions")
          break
      
        if n == 2019:
          ps2019 = collect(ss)
      
        if n == 2018:
          ps2018 = collect(ss)
          ps = ps2018.intersection(ps2019)
          printf("(b) primes = {ps}")
      

      Solution: (a) 2015. (b) 523.

      Like

      • Jim Randell's avatar

        Jim Randell 8:30 am on 31 March 2019 Permalink | Reply

        There are 9 different ways we can construct the sum to potentially give a 4-digit result.

        Counting the number of digits in each of the columns of the sum (<thousands>, <hundreds>, <tens>, <ones>), we have:

        (2, 2, 2, 2) → ABCD + EFGH
        (1, 2, 2, 3) → ABCD + EFG + H
        (1, 1, 3, 3) → ABCD + EF + GH
        (1, 1, 2, 4) → ABCD + EF + G + H
        (1, 1, 1, 5) → ABCD + E + F + G + H
        (0, 2, 3, 3) → ABC + DEF + GH
        (0, 2, 2, 4) → ABC + DEF + G + H
        (0, 1, 3, 4) → ABC + DE + FG + H
        (0, 1, 2, 5) → ABC + DE + F + G + H

        However, for years in the range 2009 to 2019 we only need to consider the constructions that have a single 4-digit number, i.e.:

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

        It turns out there are 132 sets of numbers that can be made that sum to 2019. And 114 that sum to 2018.

        We can compute the number of solutions for various years as follows:

        2019: 132
        2018: 114
        2017: 114
        2016: 96
        2015: 0
        2014: 132
        2013: 132
        2012: 114
        2011: 132
        2010: 132
        2009: 132
        2008: 234
        2007: 114
        2006: 0
        2005: 65
        2004: 71
        2003: 95
        2002: 65
        2001: 71
        2000: 95
        1999: 96
        1998: 48
        1997: 0
        1996: 83
        1995: 83
        1994: 107
        1993: 89
        1992: 113
        1991: 108
        1990: 101
        1989: 66
        1988: 0

        Using digital roots we can see that the missing digit in the sum for year n is:

        9 − digrt(n)

        So every 9 years (when the year has remainder of 8 when divided by 9), we get a year that has no solutions, as it is not possible to make a year after 1889 without using the digit 1, until we get to 2375. The years we are considering fall within this range, and so there is one year in the required range can have no solutions. This provides the answer to the first part of puzzle.

        The possible solutions for the year 2018 are (with the solutions involving 3 digit numbers indicated (*)):

        [1][36][28][459] = 2018 (*)
        [1][45][28][369] = 2018 (*)
        [1][9][235][468] = 2018
        [1][9][28][3456] = 2018
        [1][9][46][2358] = 2018

        The digits are grouped into columns, so the first number is made by choosing one digit from each of the groups, e.g. 1324, then the second number is made by choosing from the remaining digits, e.g. 685, and the next number is formed from the remaining digits, in this case 9. This exhausts all the digits, so: 1324 + 685 + 9 = 2018.

        In this way we see the possible 3-digit numbers involved are:

        [36][28][459]
        [45][28][369]

        and the only ones that are prime are 389 and 523.

        For 2019 the corresponding solutions are:

        [1][45][28][379] = 2019 (*)
        [1][45][37][289] = 2019 (*)
        [1][8][579][234] = 2019
        [1][9][235][478] = 2019
        [1][9][28][3457] = 2019
        [1][9][37][2458] = 2019

        So the 3-digit prime needs to match:

        [45][28][379]
        [45][37][289]

        And the only one of our candidates that matches is 523.

        So we have:

        2018 = 523 + [1][4][8][69] = (523 + 1486 + 9, 523 + 1489 + 6)

        missing out the digit 7.

        And:

        2019 = 523 + [1][4][8][79] = (523 + 1487 + 9, 523 + 1489 + 7)

        missing out the digit 6.

        This provides the answer to the second part of the puzzle.

        Like

  • Unknown's avatar

    Jim Randell 6:17 am on 17 March 2019 Permalink | Reply
    Tags:   

    Teaser 2947: 55 Divisions 

    From The Sunday Times, 17th March 2019 [link] [link]

    To mark her 55th birthday, Martha, a school teacher, gave each of her nine pupils a sheet of paper with a single different digit from 1 to 9 written on it.

    They stood at the front of the classroom in a row and the 9-digit number on display was divisible by 55. Martha then asked the first 3 in the row (from the left) to sit down. The remaining 6-digit number was also divisible by 55. The next 3 then sat down and the remaining 3-digit number was also divisible by 55.

    The 9 digit number was the smallest possible. What was it?

    [teaser2947]

     
    • Jim Randell's avatar

      Jim Randell 6:25 am on 17 March 2019 Permalink | Reply

      We can treat the problem as an alphametic puzzle, use the [[ SubstitutedExpression() ]] solver from the enigma.py library to find all possible solutions, and then find the smallest of these.

      This Python program runs in 98ms.

      Run: [ @replit ]

      from enigma import (SubstitutedExpression, Accumulator, irange, printf)
      
      # the alphametic puzzle
      p = SubstitutedExpression(
        [ "ABCDEFGHI % 55 = 0", "DEFGHI % 55 = 0", "GHI % 55 = 0" ],
        answer="ABCDEFGHI",
        digits=irange(1, 9),
      )
      
      # find the minimum answer
      r = Accumulator(fn=min).accumulate_from(p.answers())
      
      # output solution
      printf("min answer = {r.value} [of {r.count} solutions]")
      

      Solution: The number is 143869275.

      There are 48 different solutions to the alphametic puzzle.

      Like

    • GeoffR's avatar

      GeoffR 2:46 pm on 19 March 2019 Permalink | Reply

      % A Solution in MiniZinc
      include "globals.mzn";
      
      enum letters = {A, B, C, D, E, F, G, H, I};  
      array [letters] of var 1..9: v;
      
      constraint all_different(v);
      
      var 100000000..999999999: ABCDEFGHI = v[A] * pow(10,8) + v[B] * pow(10,7) 
      + v[C] * pow(10,6) + v[D] * pow(10,5) + v[E] * pow(10,4) + v[F] * 1000 
      + v[G] * 100 + v[H] * 10 + v[I];
      
      var 100000..999999: DEFGHI = 100000 * v[D] + 10000 * v[E] + 1000 * v[F] 
      + 100 * v[G] + 10 * v[H] + v[I];
      
      var 100..999: GHI = 100 * v[G] + 10 * v[H] + v[I];
      
      constraint ABCDEFGHI mod 55 == 0 /\ DEFGHI mod 55 == 0 /\ GHI mod 55 == 0;
      
      solve minimize(ABCDEFGHI);
      
      output ["Smallest 9-digit number = " ++ show(ABCDEFGHI) ];
      
      % Smallest 9-digit number = 143869275
      % time elapsed: 0.03 s
      % ----------
      % ==========
      % Finished in 241msec
      
      
      

      Like

      • Jim Randell's avatar

        Jim Randell 11:09 am on 20 March 2019 Permalink | Reply

        This puzzle is an ideal candidate for using the [[ solve minimize(...) ]] target in a MiniZinc model.

        Also I didn’t know MiniZinc had [[ enum ]]. (In fact, in the tutorial I used I seem to remember there was a section on how it didn’t have them and how to emulate them. I suppose they must have come along in a later version).

        Like

    • GeoffR's avatar

      GeoffR 12:14 pm on 20 March 2019 Permalink | Reply

      The latest version of MiniZinc( Ver 2.2.3) has much improved documentation and a new menu, including timing for Windows and other features. It seems odd that a solution can be found in 20 -30 msec, but still takes over 200msec to finish.

      Here is the link for enums:

      https://www.minizinc.org/doc-2.2.3/en/spec.html#enumerated-types

      Like

    • Jim Randell's avatar

      Jim Randell 10:29 am on 29 July 2020 Permalink | Reply

      I’ve recently added the [[ accumulate ]] parameter to the [[ SubstitutedExpression() ]] solver, which allows values to be computed from all the solutions.

      So, my Python program above can be modified to:

      from enigma import (SubstitutedExpression, irange, printf)
      
      # the alphametic puzzle
      p = SubstitutedExpression(
        [ "ABCDEFGHI % 55 = 0", "DEFGHI % 55 = 0", "GHI % 55 = 0" ],
        digits=irange(1, 9),
        answer="ABCDEFGHI",
        accumulate=min,
      )
      
      # solve the puzzle
      r = p.run()
      
      # output solution
      printf("min answer = {r.accumulate} [of {r.n} values]")
      

      Although the accumulated value will be output twice.

      We can also achieve the same result using a run file:

      Run: [ @replit ]

      #! python -m enigma -rr
      
      SubstitutedExpression
      
      --digits="1-9"
      
      "ABCDEFGHI % 55 = 0"
      "DEFGHI % 55 = 0"
      "GHI % 55 = 0"
      
      --answer="ABCDEFGHI"
      --accumulate="min"
      

      Note that changing the [[ --accumulate ]] parameter to [[ --accumulate="(min, max)" ]] allows us to calculate the minimum and maximum values from the answers.

      This functionality is available in the 2020-07-29 version of the enigma.py library.

      Like

  • Unknown's avatar

    Jim Randell 6:49 am on 11 March 2019 Permalink | Reply
    Tags:   

    Teaser 2937: Long division 

    From The Sunday Times, 6th January 2019 [link] [link]

    I wrote down a 2-digit number and a 5-digit number and then carried out a long division.

    I then erased all of the digits in the calculation, other than the 1’s, and so finished up with the image above.

    If I told you how many different digits I had erased, then you should be able to work out my two original numbers.

    What were my two original numbers?

    [teaser2937]

     
    • Jim Randell's avatar

      Jim Randell 6:52 am on 11 March 2019 Permalink | Reply

      Here’s a solution using the [[ SubstitutedDivision() ]] and [[ filter_unique() ]] functions from the enigma.py library.

      This program runs in 63ms. (Internal runtime is 7.2ms).

      Run: [ @replit ]

      from enigma import (SubstitutedDivision, filter_unique, printf)
      
      # the division sum
      p = SubstitutedDivision(
        "????1 / ?? = 1???",
        [ "?? - ?? = ?1", "?1? - 1?? = ??", "??? - ??? = 11", "111 - 111 = 0" ],
        digits=(0, 2, 3, 4, 5, 6, 7, 8, 9),
        verbose="T",  # show candidate solutions
      )
      
      # find solutions unique by the number of digits involved
      f = lambda s: len(set(s.s.values()))
      g = lambda s: (s.a, s.b)
      ss = filter_unique(p.solve(), f, g).unique
      
      # output solutions
      for s in ss:
        printf("SOLUTION: {s.a} / {s.b} = {s.c} [{n} digits]", n=f(s))
      

      Solution: The two original numbers were 37 and 58571.

      The diagram can describe 3 possible divisions:

      58201 ÷ 37 = 1573
      58571 ÷ 37 = 1583
      58941 ÷ 37 = 1593

      The first and third of these have 8 different digits in the long division sum, the second one uses 9 different digits and so gives the solution.

      Although the puzzle states that the erased digits are not 1 (and the program ensures this), there are no further solutions to the more general problem where the erased digits may be 1. We can see this by adding [[ 1 ]] in the [[ digits ]] specification on line 7 (or just removing that line completely to allow any digit to be used).

      Like

    • GeoffR's avatar

      GeoffR 7:16 pm on 14 March 2019 Permalink | Reply

      This solution found the same three possible solutions

      However, only the solution 58571 / 37 = 1583 had a unique number of digits erased by the setter, as the other two solutions had the same number of digits erased. The two digit number is therefore 37 and the five digit number is 58571.

      % A Solution in MiniZinc
      include "globals.mzn";                   
      
      %        w c d e         1 5 8 3
      %      ---------       ----------    
      %  a b)f g h i w    3 7)5 8 5 7 1
      %      a b              3 7
      %      ---              ---
      %      m 1 h            2 1 5
      %      w p q            1 8 5
      %      -----            -----          
      %        r s i            3 0 7
      %        t u v            2 9 6 
      %        -----            -----   
      %          1 1 1            1 1 1
      %          1 1 1            1 1 1 
      %          =====            =====
                                                                                                                                          
      int: w == 1;
      
      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;
      var 0..9: k; var 0..9: m; var 0..9: p; var 0..9: q; var 0..9: r; 
      var 0..9: s; var 0..9: t; var 0..9: u; var 0..9: v;
       
      constraint a > 0 /\ j > 0 /\ m > 0 /\ r > 0 /\ t > 0;
      
      var 10..99: ab = 10*a + b;
      var 1000..1999: wcde = 1000*1 + c*100 + d*10 + e;
      var 10000..99999: fghiw = 10000*f + 1000*g + 100*h + 10*i + w;
      
      var 10..99: jk = 10*j + k;
      var 100..999: m1h = 100*m + 10^1 + h;
      var 100..199: wpq = 100*1 + 10*p + q;
      var 100..999: rsi = 100*r + 10*s + i;
      var 100..999: tuv = 100*t + 10*u + v;
      
      var 10..99: rs = 10*r + s;
      var 10..99: m1 = 10*m + 1;
      var 10..99: fg = 10*f + g;
      
      constraint ab * wcde == fghiw;
      constraint fg - ab == m1;
      constraint c * ab = wpq /\ m1h - wpq == rs;
      
      constraint d * ab == tuv /\ rsi - tuv == 11;
      constraint e * ab == 111;
      
      % variables used in programme - all erased by setter (but not including w = 1)
      var set of int: s1 = {a, b, c, d, e, f, g, h, i, m, p, q, r, s, t, u, v};  
      
      solve satisfy;
      
      output [ show(fghiw) ++ " / " ++ show (ab) ++ " = " ++ show(wcde) 
      ++ ", digit set used (exc w=1) = " ++ show(s1) ++ "\n"
      ++ "\n[a, b, c, d, e, f, g, h, i, m, p, q, r, s, t, u, v ]  "
      ++ "\n" ++  show ( [a, b, c, d, e, f, g, h, i, m, p, q, r, s, t, u, v ] )];  % excludes w = 1
      
      % 58201 / 37 = 1573, digit set used (exc w=1) = {0,2,3,5,7,8,9}
      % 7 no. digit variables used, not inc 1
      
      % [a, b, c, d, e, f, g, h, i, m, p, q, r, s, t, u, v ]  
      % [3, 7, 5, 7, 3, 5, 8, 2, 0, 2, 8, 5, 2, 7, 2, 5, 9]
      % % time elapsed: 0.02 s
      % ----------
      % 58571 / 37 = 1583, digit set used (exc w=1) = {0,2,3,5,6,7,8,9} - ANSWER
      % 8 no. digit variables used, not inc 1
      
      % [a, b, c, d, e, f, g, h, i, m, p, q, r, s, t, u, v ]  
      % [3, 7, 5, 8, 3, 5, 8, 5, 7, 2, 8, 5, 3, 0, 2, 9, 6]
      % % time elapsed: 0.02 s
      % ----------
      % 58941 / 37 = 1593, digit set used (exc w=1) = {2,3,4,5,7,8,9}
      % 7 no. digit variables used, not inc 1
      
      % [a, b, c, d, e, f, g, h, i, m, p, q, r, s, t, u, v ]  
      % [3, 7, 5, 9, 3, 5, 8, 9, 4, 2, 8, 5, 3, 4, 3, 3, 3]
      % % time elapsed: 0.02 s
      % ----------
      % ==========
      % Finished in 232msec
      
      
      

      Like

    • elbaz haviv's avatar

      elbaz haviv 1:10 pm on 30 August 2023 Permalink | Reply

      1593 x 37 and 1573 x 37 also fit the puzzle

      Like

      • Jim Randell's avatar

        Jim Randell 1:35 pm on 30 August 2023 Permalink | Reply

        As noted above these 2 candidate solutions are eliminated as they both have 7 different digits erased. The remaining candidate has 8 different erased digits, and so provides the required answer to the puzzle.

        Like

    • elbaz haviv's avatar

      elbaz haviv 4:18 pm on 30 August 2023 Permalink | Reply

      ok later I noticed that but I don’t find
      an edit future to correct my self.
      anyway Thank you.

      Like

  • Unknown's avatar

    Jim Randell 12:16 am on 10 March 2019 Permalink | Reply
    Tags:   

    Teaser 2946: Pentagonal gardens 

    From The Sunday Times, 10th March 2019 [link] [link]

    Adam and Eve have convex pentagonal gardens consisting of a square lawn and paving. Both gardens have more than one right-angled corner. All the sides of the gardens and lawns are the same whole number length in metres, but Adam’s garden has a larger total area. Eve has worked out that the difference in the areas of the gardens multiplied by the sum of the paved areas (both in square metres) is a five-digit number with five different digits.

    What is that number?

    [teaser2946]

     
    • Jim Randell's avatar

      Jim Randell 1:16 am on 10 March 2019 Permalink | Reply

      If I’ve understood this correctly there are only two ways to construct the gardens, and this gives a fairly limited set of integer sides. And only one of those gives a viable 5-digit number.

      I worked out 2 possible shapes for the gardens, where the lawn forms most of the perimeter:

      To make calculating the area easier I have split the lawn of A’s garden in two and inserted the paved area between. The areas are the same as if the lawn was a contiguous square.

      If we suppose the line segments making up the perimeter of the gardens are units, then both squares are unit squares and both triangles have a base of length 1.

      A’s triangle has a height of √(7)/2 and an area of √(7)/4. E’s triangle has a height of √(3)/2 and an area of √(3)/4.

      The difference in the total areas of the gardens is:

      (1 + √(7)/4) − (1 + √(3)/4) = (√7 − √3) / 4

      The sum of the paved areas is:

      √(7)/4 + √(3)/4 = (√7 + √3) / 4

      Multiplying these together we get:

      (√7 + √3) × (√7 − √3) / (4 × 4) = 1 / 4

      So, if the gardens were all of side x, the number N would be:

      N = (x^4) / 4

      For a 5-digit value for N there are only a few values of x to try, and this can be completed manually or programatically.

      This Python program runs in 77ms.

      Run: [ @repl.it ]

      from enigma import (irange, div, is_duplicate, printf)
      
      # consider 5 digit values for N
      for x in irange.round(pow(4 * 10000, 0.25), pow(4 * 99999, 0.25)):
        N = div(pow(x, 4), 4)
        if N is None or is_duplicate(N): continue
        # output solution
        printf("x={x} N={N}")
      

      Solution: The number is 16384.

      Like

      • Jim Randell's avatar

        Jim Randell 8:55 am on 10 March 2019 Permalink | Reply

        I’m pretty sure these are the only two possible shapes.

        If you imagine trying to form a set of 5 equal length linked rods into a convex pentagon with more than one right angle, then it is not possible with 3 right angles, so there must be exactly 2 right angles. And these are either on adjacent vertices or have one vertex between them.

        Either way, the remaining rods are forced into unique positions, giving the shapes A and E.

        Although note that with A there are many ways that a unit square can fit inside the pentagon (not necessarily touching the perimeter).

        Like

  • Unknown's avatar

    Jim Randell 8:16 am on 6 March 2019 Permalink | Reply
    Tags:   

    Teaser 2939: Betting to win 

    From The Sunday Times, 20th January 2019 [link] [link]

    Two teams, A and B, play each other.

    A bookmaker was giving odds of 8-5 on a win for team A, 6-5 on a win for team B and X-Y for a draw (odds of X-Y mean that if £Y is bet and the bet is successful then £(X + Y) is returned to the punter). I don’t remember the values of X and Y, but I know that they were whole numbers less than 20.

    Unusually, the bookmaker miscalculated! I found that I was able to make bets of whole numbers of pounds on all three results and guarantee a profit of precisely 1 pound.

    What were the odds for a draw, and how much did I bet on that result?

    [teaser2939]

     
    • Jim Randell's avatar

      Jim Randell 8:17 am on 6 March 2019 Permalink | Reply

      If the integer stakes are p for A to win, q for B to win, r for a draw, we have:

      (13/5)p = p + q + r + 1
      (11/5)q = p + q + r + 1
      ((X + Y)/Y)r = p + q + r + 1

      which, given X and Y, we can solve as:

      p = 55(X + Y) / (23X – 120Y)
      q = 65(X + Y) / (23X – 120Y)
      r = 143Y / (23X – 120Y)

      and we want these to be integers.

      X and Y are limited to be integers between 1 and 19, so we can easily check all possibilities.

      This Python program runs in 72ms.

      Run: [ @repl.it ]

      from itertools import product
      from enigma import (irange, printf)
      
      # consider possible values for X, Y
      for (X, Y) in product(irange(1, 19), repeat=2):
        # calculate integer stakes:
        # p (for A to win)
        # q (for B to win)
        # r (for a draw)
        d = 23 * X - 120 * Y
        if not (d > 0): continue
        (p, x) = divmod(55 * (X + Y), d)
        if x != 0: continue
        (q, x) = divmod(65 * (X + Y), d)
        if x != 0: continue
        (r, x) = divmod(143 * Y, d)
        if x != 0: continue
      
        # output solution
        printf("X={X} Y={Y}, p={p} q={q} r={r}")
      
        # verify the winnings
        w = p + q + r + 1
        assert divmod(13 * p, 5) == (w, 0)
        assert divmod(11 * q, 5) == (w, 0)
        assert divmod((X + Y) * r, Y) == (w, 0)
      

      Solution: The odds for a draw were 11-2. The bet on a draw was £22.

      A variation: If the bets can be whole numbers of pennies, instead of whole numbers of pounds, then there is another solution where X-Y is 10-1 and the bets are £5.50 on A to win, £6.50 for B to win, £1.30 on a draw. The winnings are £14.30 for a total outlay of £13.30.

      Like

    • GeoffR's avatar

      GeoffR 8:22 am on 7 March 2019 Permalink | Reply

      % A solution in MinZinc 
      var 1..19: X; var 1..19: Y;
      
      % Integer stakes are p for A to win, q for B to win, and r for a draw
      % For bets of p, q and r, a return of (p + q + r + 1) makes a profit of £1
      var 1..100: p; var 1..100: q; var 1..100: r;
      
      constraint 13 * p = (p + q + r + 1) * 5;        % 8-5 odds for team A
      constraint 11 * q = (p + q + r + 1) * 5;        % 6-5 odds for team B
      constraint (X + Y )* r = (p + q + r + 1) * Y;   % X-Y odds for a draw
      
      solve satisfy;
      
      % X = 11; Y = 2; p = 55; q = 65; r = 22;
      % ==========
      % Finished in 195msec 
      % Odds for a draw were 11/2 and the stake for a draw was £22
      
      

      Like

  • Unknown's avatar

    Jim Randell 12:31 pm on 1 March 2019 Permalink | Reply
    Tags:   

    Teaser 2941: Big deal 

    From The Sunday Times, 3rd February 2019 [link] [link]

    My wife and I play bridge with Richard and Linda. The 52 cards are shared equally among the four of us – the order of cards within each player’s hand is irrelevant but it does matter which player gets which cards. Recently, seated in our fixed order around the table, we were discussing the number of different combinations of cards possible and we calculated that it is more than the number of seconds since the “big bang”!

    We also play another similar game with them, using a special pack with fewer cards than in the standard pack – again with each player getting a quarter of the cards. Linda calculated the number of possible combinations of the cards for this game and she noticed that it was equal to the number of seconds in a whole number of days.

    How many cards are there in our special pack?

    [teaser2941]

     
    • Jim Randell's avatar

      Jim Randell 12:32 pm on 1 March 2019 Permalink | Reply

      If there are k players, and each player receives n cards in the deal, then there are n.k cards in total.

      The number of ways of dealing n cards to the first player from the total set of n.k cards are:

      C(n.k, n) = (n.k)! / [ n! (n(k − 1))! ]

      For the second player there are only n(k − 1) cards remaining, and dealing n cards from that we get:

      C(n(k − 1), n) = (n(k − 1))! / [ n! (n(k − 2))! ]

      For the third player:

      C(n(k − 2), n) = (n(k − 2))! / [ n! (n(k − 3))! ]

      and so on up to the final player

      C(n, n) = n! / [ n! 0! ] = 1

      Multiplying all these together we find that one of the terms in the denominator cancels with the numerator for the next player, giving a total number of possible deals of:

      deals(k, n) = (n.k)! / (n!)^k

      We can use this rather neat formula to find the required number of cards in the puzzle.

      This Python program runs in 74ms.

      from enigma import (irange, inf, factorial, arg, printf)
      
      # number of players
      k = arg(4, 0, int, prompt="number of players")
      
      # multiple = number of seconds in a day (assumed constant)
      m = arg(60 * 60 * 24, 1, int, prompt="multiple")
      
      printf("[{k} players, m = {m}]")
      
      # number of cards per player
      for n in irange(1, inf):
        p = factorial(n * k) // pow(factorial(n), k)
        (d, r) = divmod(p, m)
        printf("{t} cards, {n} each, {p} deals, {d} days (+ {r}s)", t=n * k)
        if r == 0: break
      

      Solution: There are 28 cards in the special pack.

      Like

  • Unknown's avatar

    Jim Randell 8:14 am on 25 February 2019 Permalink | Reply
    Tags:   

    Teaser 2945: Infernal indices 

    From The Sunday Times, 3rd March 2019 [link] [link]

     

    The above is the size of the evil multitude in the last “Infernal indices” novel: “A deficit of daemons”.

    Spoiler Alert: At the end, the forces of good engage in the fewest simultaneous battles that prevent this evil horde splitting, wholly, into equal-sized armies for that number of battles. The entire evil horde is split into one army per battle, all equally populated, bar one which has a deficit of daemons, leading to discord and a telling advantage for the forces of good.

    How many battles were there?

    [teaser2945]

     
    • Jim Randell's avatar

      Jim Randell 8:15 am on 25 February 2019 Permalink | Reply

      Although the given number (let’s call it N) is large (it is 36,306 decimal digits), it is not too large for Python to cope with.

      We need to find the smallest whole number n that does not divide N. This is a much smaller number.

      The following Python program runs in 107ms.

      Run: [ @replit ]

      from enigma import (irange, inf, printf)
      
      # construct the large number N
      x = 6**6
      N = (6**x) - (x**6)
      
      # find the smallest number that does not divide it
      for n in irange(2, inf):
        if N % n != 0:
          printf("n={n}")
          break
      

      Solution: There were 17 battles.

      (N mod 17) = 14, so the best the evil horde could manage would be 16 armies the same size and 1 army that had 3 fewer demons.

      Like

      • Jim Randell's avatar

        Jim Randell 4:46 pm on 2 March 2019 Permalink | Reply

        We can use the technique given in Enigma 1494 to compute the residues of large powers without the need to construct the huge numbers.

        The internal runtime for the following program is significantly less than the simple program given above (169µs vs. 961µs for the program given above). Although in practise both programs run instantaneously.

        from enigma import (irange, inf, printf)
        
        # compute a^b mod n
        def mpow(a, b, n):
          s = 1
          while b > 0:
            (b, r) = divmod(b, 2)
            if r > 0: s = (s * a) % n
            a = (a * a) % n
          return s
        
        # N = 6^x - x^6
        x = 6**6
        
        # find the smallest number that does not divide it
        for n in irange(2, inf):
          # find the residue N mod n
          if mpow(6, x, n) != mpow(x, 6, n):
            printf("n={n}")
            break
        

        Using the 3-argument version of the Python builtin [[ pow() ]] instead of [[ mpow() ]] gets the internal run time down to 40µs.


        For a manual solution we can use “the difference of two squares” method to express the number as:

        N = (6^36)(6^23310 − 1)(6^23310 + 1)

        From which it is easy to see that N will have a large number of factors of 2 and 3, and the fact that any power of 6 ends in a 6 means that the difference of two powers of 6 will end in a 0, so it will also be divisible by 5.

        So we can start by considering the primes: 7, 11, 13, 17, 19, 23 when looking for a suitable n.

        When evaluating mpow(6, x, n) the exponent can be reduced modulo (n − 1) (as n is prime) using Euler’s Theorem, and we can always evaluate the mpow(x, 6, n) in 3 iterations.

        In the end we don’t even need to consider all these primes in order to get the answer, so we can arrive at the solution with only a modest amount of calculation.

        Like

        • Jim Randell's avatar

          Jim Randell 12:14 pm on 3 March 2019 Permalink | Reply

          Here’s my complete manual solution:

          Writing:

          N = (6^36)(6^23310 − 1)(6^23310 + 1)

          We can start to examine divisors:

          For n = 2, it clearly divides the (6^36) term. Similarly for n = 3, 4, 6, 8, 9, 12, 16, ….

          For n = 5, it doesn’t divide the (6^36) term, so let’s consider the value of (6^23310 mod 5):

          5 is prime, so we can use Euler’s Theorem to reduce the exponent mod (p − 1):

          6^23310 mod 5 =
          6^(23310 mod (5 − 1)) mod 5 =
          6^2 mod 5 =
          36 mod 5 =
          1

          And if (6^23310 mod 5) = 1 then 5 divides the (6^23310 − 1) term.

          For n = 7, we consider the value of (6^23310 mod 7):

          6^23310 mod 7 =
          6^(23310 mod 6) mod 7 =
          6^0 mod 7 =
          1 mod 7 =
          1

          So 7 divides the (6^23310 − 1) term.

          For n = 10 we already know 2 divides the (6^36) term and 5 divides the (6^23310 − 1) term.

          For n = 11:

          6^23310 mod 11 =
          6^(23310 mod 10) mod 11 =
          6^0 mod 11 =
          1 mod 11 =
          1

          So 11 divides the (6^23310 − 1) term.

          For n = 13:

          6^23310 mod 13 =
          6^(23310 mod 12) mod 13 =
          6^6 mod 13 =
          12

          And 12 is equivalent to −1 mod 13, so 13 divides the (6^23310 + 1) term.

          For n = 14, we already have divisors of 2 and 7.

          For n = 15, we already have divisors of 3 and 5.

          for n = 17:

          6^23310 mod 17 =
          6^(23310 mod 16) mod 17 =
          6^14 mod 17 =
          (6^7 mod 17)^2 mod 17 =
          196 mod 17 =
          9

          9 is not equivalent to +1 or −1 mod 17, so 17 does not divide any of the terms, and gives our solution.

          Like

  • Unknown's avatar

    Jim Randell 7:39 am on 24 February 2019 Permalink | Reply
    Tags:   

    Teaser 2944: Happy families 

    From The Sunday Times, 24th February 2019 [link] [link]

    Teaser 2944

    Oliver lives with his parents, Mike and Nellie, at number 5. In each of numbers 1 to 4 lives a family, like his, with a mother, a father and one child. He tries listing the families in alphabetical order and produces the table above.

    However, apart from his own family, there is just one father, one mother and one child in the correct position. Neither Helen nor Beth lives at number 3 and neither Dave nor Ingrid lives at number 1. George’s house number is one less than Larry’s and Beth’s house number is one less than Carol’s. Apart from Oliver’s family, who are correctly positioned?

    [teaser2944]

     
    • Jim Randell's avatar

      Jim Randell 8:05 am on 24 February 2019 Permalink | Reply

      The wording of the puzzle is a little strange. I’m assuming the columns of the correct table are placed in order of house number (not “alphabetical” order), and the names of the fathers, mothers and children have been placed in the correct rows, just not necessarily in the correct columns. It seems like a reasonable assumption, and leads to a unique solution.

      I think I would have described the filling out of the original table like this:

      Oliver knows the names of the fathers, mothers and children, but is not sure who lives where, so he filled out each row in alphabetical order (from left to right), to give the table above. This correctly places his own family at house number 5. However …

      We can easily consider all the possibilities and eliminate those that do not satisfy the requirements.

      This Python program runs in 71ms.

      Run: [ @repl.it ]

      from itertools import permutations
      from enigma import printf
      
      # generate permutations that are only correct in 1 position
      def generate(vs, k=1):
        for s in permutations(vs):
          if sum(x == v for (x, v) in zip(s, vs)) == k:
            yield s
      
      # permute the Mums
      for mums in generate('BEHK'):
        (m1, m2, m3, m4) = mums
      
        # neither H or B live at number 3
        if m3 == 'H' or m3 == 'B': continue
      
        # permute the kids
        for kids in generate('CFIL'):
          (k1, k2, k3, k4) = kids
      
          # I does not live at number 1
          if k1 == 'I': continue
      
          # B's house number is 1 less than C's
          if not (mums.index('B') + 1 == kids.index('C')): continue
      
          # permute the dads
          for dads in generate('ADGJ'):
            (d1, d2, d3, d4) = dads
      
            # D does not live at 1
            if d1 == 'D': continue
      
            # G's house number is 1 less than L's
            if not (dads.index('G') + 1 == kids.index('L')): continue
      
            printf("1 = {d1}+{m1}+{k1}; 2 = {d2}+{m2}+{k2}; 3 = {d3}+{m3}+{k3}; 4 = {d4}+{m4}+{k4}")
      

      Solution: George, Kate and Larry were also correctly placed.

      Like

  • Unknown's avatar

    Jim Randell 8:25 am on 17 February 2019 Permalink | Reply
    Tags:   

    Teaser 2943: Keep your balance 

    From The Sunday Times, 17th February 2019 [link] [link]

    George and Martha have a set of a dozen balls, identical in appearance but each has been assigned a letter of the alphabet, A, B, …, K, L and each is made of a material of varying density so that their weights in pounds are 1, 2…. 11, 12 but in no particular order. They have a balance and the following weighings were conducted:

    (1) {A, C, I} vs {G, J, L}

    (2) {A, H, L} vs {G, I, K}

    (3) {B, I, J} vs {C, F, G}

    (4) {B, D, I} vs {E, G, H}

    (5) {D, F, L} vs {E, G, K}

    On all five occasions, there was perfect balance and the total of the threesome in each was a different prime number, that in (1) being the smallest and progressing to that in (5) which was the largest.

    In alphabetical order, what were the weights of each of the twelve balls?

    [teaser2943]

     
    • Jim Randell's avatar

      Jim Randell 8:38 am on 17 February 2019 Permalink | Reply

      We can solve this using the [[ SubstitutedExpression() ]] solver from the enigma.py library. Treating each symbol as standing for a different non-zero base 13 digit.

      This run-file executes in 332ms.

      Run: [ @replit ]

      #! python3 -m enigma -rr
      
      SubstitutedExpression
      
      --base="13"
      --digits="1-12"
      
      --template=""
      
      # the weighings
      "A + C + I == G + J + L"
      "A + H + L == G + I + K"
      "B + I + J == C + F + G"
      "B + D + I == E + G + H"
      "D + F + L == E + G + K"
      
      # the total weights are prime
      "is_prime(A + C + I)"
      "is_prime(A + H + L)"
      "is_prime(B + I + J)"
      "is_prime(B + D + I)"
      "is_prime(D + F + L)"
      
      # the primes are in increasing order
      "A + C + I < A + H + L"
      "A + H + L < B + I + J"
      "B + I + J < B + D + I"
      "B + D + I < D + F + L"
      

      Solution: The weights of the balls are: A=4, B=8, C=5, D=9, E=12, F=11, G=1, H=6, I=2, J=7, K=10, L=3.

      Like

    • Jim Randell's avatar

      Jim Randell 10:19 am on 17 February 2019 Permalink | Reply

      There are six symbols in the first weighing, and together they must sum to twice the smallest prime, so the smallest possible value for the smallest prime is:

      divc(1 + 2 + 3 + 4 + 5 + 6, 2) = 11

      Similarly the largest possible value for the largest prime is:

      divf(7 + 8 + 9 + 10 + 11 + 12, 2) = 28

      So the list of possible primes is: 11, 13, 17, 19, 23.

      There are only 5 primes on the list, so the weighings give us 10 equations in 12 variables.

      Again using the [[ SubstitutedExpression() ]] solver, this run file executes in 131ms.

      Run: [ @replit ]

      #! python3 -m enigma -rr
      
      SubstitutedExpression
      
      --base="13"
      --digits="1-12"
      --template=""
      
      # the weighings
      "A + C + I == 11"
      "G + J + L == 11"
      "A + H + L == 13"
      "G + I + K == 13"
      "B + I + J == 17"
      "C + F + G == 17"
      "B + D + I == 19"
      "E + G + H == 19"
      "D + F + L == 23"
      "E + G + K == 23"
      

      Like

      • Jim Randell's avatar

        Jim Randell 7:30 am on 5 March 2019 Permalink | Reply

        Here’s a manual solution:

        Given the 10 equations above and adding the equation:

        A + B + C + D + E + F + G + H + I + J + K + L = 78

        Gives us 11 equations in 12 variables.

        These can be solved to give the other values in terms of B:

        A = 44 − 5B
        C = 4B − 27
        D = 25 − 2B
        E = B + 4
        F = 27 − 2B
        G = 17 − 2B
        H = B − 2
        I = B − 6
        J = 23 − 2B
        K = B + 2
        L = 4B − 29

        And all the variables have to take on different values from 1 to 12.

        From I and E, we have:

        B ≥ 7
        B ≤ 8

        So B is 7 or 8.

        The formula for F gives:

        B = 7 → F = 13
        B = 8 → F = 11

        The first of these is not possible so B = 8, giving:

        A = 4; B = 8; C = 5; D = 9; E = 12; F = 11; G = 1; H = 6; I = 2; J = 7; K = 10; L = 3

        Like

        • Frits's avatar

          Frits 3:43 pm on 30 July 2020 Permalink | Reply

          @Jim

          “These can be solved to give the other values in terms of B:” –> easier said than done.

          Can your Enigma functions generate these 11 equations in terms of B?

          Like

          • Jim Randell's avatar

            Jim Randell 5:03 pm on 30 July 2020 Permalink | Reply

            You could use SymPy to reduce the set of equations down using a single parameter.

            But you can also choose a value for B and then you have 12 equations in 12 variables, which you can solve using the [[ Matrix.linear() ]] solver in enigma.py.

            Run: [ @replit ]

            from enigma import (Matrix, irange, join, printf)
            
            eqs = [
              # A  B  C  D  E  F  G  H  I  J  K  L
              ( 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ), # B = ?
              ( 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0 ), # (A, C, I) = 11
              ( 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1 ), # (G, J, L) = 11
              ( 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1 ), # (A, H, L) = 13
              ( 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0 ), # (G, I, K) = 13
              ( 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0 ), # (B, I, J) = 17
              ( 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0 ), # (C, F, G) = 17
              ( 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0 ), # (B, D, I) = 19
              ( 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0 ), # (E, G, H) = 19
              ( 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1 ), # (D, F, L) = 23
              ( 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0 ), # (E, G, K) = 23
              ( 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ), # (A ... L) = 78
            ]
            
            # the collection of weights
            weights = set(irange(1, 12))
            
            # choose a value for B
            for B in weights:
              # evaluate the equations
              s = Matrix.linear(eqs, [B, 11, 11, 13, 13, 17, 17, 19, 19, 23, 23, 78])
              # the answers should be the values in weights
              if not (set(s) == weights): continue
              # output solution
              printf("{s}", s=join((join((w, '=', v)) for (w, v) in zip("ABCDEFGHIJKL", s)), sep=" "))
            

            Like

            • Frits's avatar

              Frits 8:27 pm on 30 July 2020 Permalink | Reply

              Thanks, I ran the following code at [ https://live.sympy.org/ ]:

              from sympy import linsolve, symbols, linear_eq_to_matrix
              A,B,C,D,E,F,G,H,I,J,K,L = symbols("A,B,C,D,E,F,G,H,I,J,K,L", integer=True)
              variables = [A,C,D,E,F,G,H,I,J,K,L,B]
              
              def my_solver(known_vals):
              
                  eqns = [A + C + I - 11,
              G + J + L - 11,
              A + H + L - 13,
              G + I + K - 13,
              B + I + J - 17,
              C + F + G - 17,
              B + D + I - 19,
              E + G + H - 19,
              D + F + L - 23,
              E + G + K - 23,
              A + B + C + D + E + F + G + H + I + J + K + L - 78]
              
                  # add the known variables to equation list
                  for x in known_vals.keys():
                      eqns.append(x - (known_vals[x]))
              
                  X, b = linear_eq_to_matrix(eqns, variables)
                  solution = linsolve((X, b), variables)
              
                  return solution
              
              
              my_solver({})
              

              Output:

              {(44−5B, 4B−27, 25−2B, B+4, 27−2B, 17−2B, B−2, B−6, 23−2B, B+2, 4B−29, B)}

              Like

    • GeoffR's avatar

      GeoffR 3:38 pm on 19 February 2019 Permalink | Reply

      I assumed you did not want the answer shown?

      % A Solution in MiniZinc
      include "globals.mzn";
      
      % The dozen balls weigh between 1 and 12 pounds
      var 1..12:A; var 1..12:B; var 1..12:C; var 1..12:D; var 1..12:E;
      var 1..12:F; var 1..12:G; var 1..12:H; var 1..12:I; var 1..12:J;
      var 1..12:K; var 1..12:L;
      
      % All the balls A..K are of different weight
      constraint all_different([A, B, C, D, E, F, G, H, I, J, K, L]);
      
      predicate is_prime(var int: x) = 
      x > 1 /\ forall(i in 2..1 + ceil(sqrt(int2float(ub(x))))) ((i < x) -> (x mod i > 0));
      
      % The weighing equations
      constraint (A + C + I == G + J + L) 
      /\ (A + H + L == G + I + K)
      /\ (B + I + J == C + F + G) 
      /\ (B + D + I == E + G + H)
      /\ (D + F + L == E + G + K);
      
      % the total weights in the equations are all prime numbers
      constraint is_prime(A + C + I) /\ is_prime(A + H + L) /\ is_prime(B + I + J) 
      /\ is_prime(B + D + I) /\ is_prime(D + F + L);
      
      % The five primes are in increasing order
      constraint (A + C + I) < (A + H + L) /\  (A + H + L) < (B + I + J)
      /\ (B + I + J) < (B + D + I) /\  (B + D + I) < (D + F + L);
      
      solve satisfy;
      
      output [ " A = "++ show(A) ++ ", B = " ++ show(B) ++ ", C = " ++ show(C) ++ "\n"
      ++ " D = " ++ show(D) ++ ", E = " ++ show(E) ++ ", F = " ++ show(F) ++ "\n"
      ++ " G = " ++ show(G) ++ ", H = " ++ show(H) ++ ", I = " ++ show(I) ++ "\n"
      ++ " J = " ++ show(J) ++ ", K = " ++ show(K) ++ ", L = " ++ show(L) ];
      
      
      

      Like

  • Unknown's avatar

    Jim Randell 8:27 pm on 7 February 2019 Permalink | Reply
    Tags:   

    Teaser 2942: What do points make? 

    From The Sunday Times, 10th February 2019 [link] [link]

    In the Premier League table a team’s points are usually roughly equal to their goals scored (Burnley were an interesting exception in 2017-18). That was exactly the case in our football league after the four teams had played each other once, with 3 points for a win and 1 for a draw.

    A ended up with the most points, followed by B, C and D in that order. Fifteen goals had been scored in total, and all the games had different scores. The best game finished 5-0, and the game BvD had fewer than three goals.

    What were the results of B’s three games (in the order BvA, BvC, BvD)?

    [teaser2942]

     
    • Jim Randell's avatar

      Jim Randell 11:38 am on 8 February 2019 Permalink | Reply

      I think this puzzle could have been worded more clearly.

      I took the first part to mean we are looking for situations where each team has exactly the same number of points as the number of goals scored by that team. And that the “best game finished 5-0” means that that game had the most goals scored altogether (i.e. the other games had no more than 4 goals scored in total). I took the fact that all matches had different scores to mean that you couldn’t have (for example) one game with a score of 2-0 and another with a score of 0-2.

      This program uses the [[ Football() ]] helper class from the enigma.py library. It looks for possible games for a team that can give the same number of points as the number of goals scored by that team, and then chooses outcomes for the four teams that satisfy the remaining conditions of the puzzle. It runs in 340ms.

      Run: [ @replit ]

      from itertools import (product, combinations)
      from enigma import (defaultdict, Football, ordered, printf)
      
      # scoring system
      football = Football(games='wdl', points=dict(w=3, d=1))
      
      # possible scores (a 5-0 and then no more than 4 goals in any match)
      scores = dict()
      scores['w'] = set([(1, 0), (2, 0), (3, 0), (4, 0), (5, 0), (2, 1), (3, 1)])
      scores['d'] = set([(0, 0), (1, 1), (2, 2)])
      scores['l'] = set((x, y) for (y, x) in scores['w'])
      
      # record possible games by points (= goals for)
      ss = defaultdict(list)
      
      # consider outcomes for three matches for team T against X, Y, Z
      for (TX, TY, TZ) in football.games(repeat=3):
      
        # make the table for team T
        T = football.table([TX, TY, TZ], [0, 0, 0])
      
        # make possible score lines that give "goals for" = "points"
        for (sTX, sTY, sTZ) in product(scores[TX], scores[TY], scores[TZ]):
      
          (fT, aT) = football.goals([sTX, sTY, sTZ], [0, 0, 0])
      
          if not (fT == T.points): continue
      
          ss[fT].append((sTX, sTY, sTZ))
      
      # choose possible points (= goals for) for A, B, C, D
      for (pA, pB, pC, pD) in combinations(sorted(ss.keys(), reverse=1), 4):
      
        # but points = goals for, and the total number of goals is 15
        if not (pA + pB + pC + pD == 15): continue
      
        # choose matches for B
        for (BA, BC, BD) in ss[pB]:
      
          # B vs D has less than 3 goals scored
          if not (sum(BD) < 3): continue
      
          # choose matches for A
          for (AB, AC, AD) in ss[pA]:
            if not (AB == BA[::-1]): continue
      
            # choose matches for C
            for (CA, CB, CD) in ss[pC]:
              if not (CA == AC[::-1] and CB == BC[::-1]): continue
      
              # check matches for D
              if not ((AD[::-1], BD[::-1], CD[::-1]) in ss[pD]): continue
      
              # all games have different scores
              s = set(ordered(*x) for x in (AB, AC, AD, BC, BD, CD))
              if not (len(s) == 6): continue
      
              # there is a 5-0 game
              if not ((0, 5) in s): continue
      
              printf("AB={AB} AC={AC} AD={AD} BC={BC} BD={BD} CD={CD}, A={pA} B={pB} C={pC} D={pD}")
      

      Solution: The scores in B’s games are: B vs A = 1-2; B vs C = 2-2; B vs D = 1-0.

      It turns out that the fact that there is a 5-0 game means that there are only 10 goals to distribute between the remaining 5 matches, and there are no further solutions if games with more than 4 goals scored are considered, so it is enough to know that there is a 5-0 score.

      If we allow “mirror” scores (e.g. one game with a score of 2-0 and another with a score of 0-2), then there are no further solutions either. (Although if we allow repeated scores then there are additional solutions).

      If we relax the conditions that the number of points is exactly the same as the number of goals scored then there are multiple solutions, even if they must be within 1 of each other.

      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