Updates from Jim Randell Toggle Comment Threads | Keyboard Shortcuts

  • 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:02 am on 5 April 2019 Permalink | Reply
    Tags:   

    Teaser 2926: Coins of Obscura 

    From The Sunday Times, 21st October 2018 [link] [link]

    George and Martha were on holiday in Obscura where coins are circular with radii equal to their whole number value in scurats. They had coffees and George took out some loose change. He placed one 10 scurat and two 15 scurat coins on the table so that each coin touched the other two and a smaller coin between them that touched all three. He then placed a fifth coin on top of these four which exactly covered them and the total value of the five coins was exactly enough to pay the bill.

    How much was the coffee bill?

    [teaser2926]

     
    • Jim Randell's avatar

      Jim Randell 8:02 am on 5 April 2019 Permalink | Reply

      I think by “exactly covered” the setter means that the fifth coin was the smallest possible circle that would cover the original three coins.

      If you’ve encountered “Soddy Circles” the fourth and fifth coins correspond to the inner and outer Soddy circles formed from the first three coins.

      There is a (relatively) straightforward expression that can be used to calculate the radii of these circles (see: [ Descartes Theorem ]).

      Here is a useful reference for Soddy Circles: [ link ]

      This Python program runs in 89ms.

      Run: [ @replit ]

      from enigma import (is_square, div, printf)
      
      # calculate the radius of the inner and outer Soddy circles
      # (we are only interested in integer solutions)
      def soddy(r1, r2, r3):
        x = r1 * r2 * r3
        y = is_square(x * (r1 + r2 + r3))
        if y is None: return (None, None)
        z = r1 * r2 + r1 * r3 + r2 * r3
        return (div(x, 2 * y + z), div(x, 2 * y - z))
      
      # initial parameters
      (r1, r2, r3) = (10, 15, 15)
      
      # the radii of the Soddy circles
      (r, R) = soddy(r1, r2, r3)
      assert not (r is None or R is None)
      printf("[r1={r1} r2={r2} r3={r3} -> r={r} R={R}]")
      
      # add them all together
      t = r1 + r2 + r3 + r + R
      printf("total = {t}")
      

      Solution: The bill came to 72 scurats.

      The additional coins have values of 2 and 30.

      Here is a diagram. The original coins are shown in black, the inner and outer Soddy Circles (corresponding to the fourth and fifth coins) are shown in red:

      Like

  • Unknown's avatar

    Jim Randell 7:37 am on 4 April 2019 Permalink | Reply
    Tags: by: Donald Entwisle   

    Brainteaser 1538: Times square 

    From The Sunday Times, 1st March 1992 [link]

    Alf: Listen to this: “SUN times DAY equals TIMES“.

    Beth: Sounds like a lot of nonsense to me.

    Alf: Let me write it down for you. Like this:

    SUN × DAY = TIMES

    In this sum are 10 different letters representing digits 0 to 9 and in my answer SUN minus DAY is a perfect square. That should help you.

    Beth: That’s a tall order, but I’ll have a go. Where’s my calculator.

    Beth did find Alf’s solution. What was their number for TIMES?

    This puzzle is included in the book Brainteasers (2002), in which it appears in the following modified form:

    With the usual letters-for-digits convention:

    SUN – DAY

    is the square of a prime, and:

    SUN × DAY = TIMES

    What number is TIMES?

    (We do not actually need to know that the square is the square of a prime, but it cuts down the work considerably).

    [teaser1538]

     
    • Jim Randell's avatar

      Jim Randell 7:38 am on 4 April 2019 Permalink | Reply

      The wording (but not most of the meaning) of this Teaser was changed considerably for the book. In the original puzzle we were told that (SUN − DAY) was a square number, but not that it was the square of a prime.

      The puzzle can be solved using the [[ SubstitutedExpression() ]] solver from the enigma.py library.

      This run file executes in 235ms.

      Run: [ @repl.it ]

      #! python -m enigma -rr
      
      SubstitutedExpression
      
      --answer="TIMES"
      
      "is_prime(is_square(SUN - DAY))"
      
      "SUN * DAY = TIMES"
      

      Solution: TIMES = 50862.

      We can remove the call to [[ is_prime() ]] to solve the original puzzle. The answer is the same.

      Without the subtraction constraint at all, the multiplication sum has three solutions:

      % python enigma.py SubstitutedExpression "SUN * DAY = TIMES"
      (SUN * DAY = TIMES)
      (219 * 308 = 67452) / A=0 D=3 E=5 I=7 M=4 N=9 S=2 T=6 U=1 Y=8
      (294 * 173 = 50862) / A=7 D=1 E=6 I=0 M=8 N=4 S=2 T=5 U=9 Y=3
      (254 * 378 = 96012) / A=7 D=3 E=1 I=6 M=0 N=4 S=2 T=9 U=5 Y=8
      [3 solutions]
      

      Like

  • Unknown's avatar

    Jim Randell 9:10 am on 3 April 2019 Permalink | Reply
    Tags:   

    Teaser 2927: On a roll 

    From The Sunday Times, 28th October 2018 [link] [link]

    My son saw the “average sheets per roll” printed on our new pack of four toilet rolls. Curious, he counted each roll’s total sheets by overlaying lines of ten sheets to and fro, tallying layers, and then adding any extra sheets. These totals were four consecutive three-figure numbers, including the printed “average sheets per roll”. For each total, he noticed that there was the same single-figure number of choices for a number of sheets per layer, requiring at least two layers, which would leave no extra sheets. Re-counting the toilet roll with the “average sheets per roll”, he used a two-figure number of sheets per layer and tallied a two-figure number of such layers, with no extras.

    What was the “average sheets per roll”?

    [teaser2927]

     
    • Jim Randell's avatar

      Jim Randell 9:10 am on 3 April 2019 Permalink | Reply

      This Python program runs in 81ms.

      Run: [ @repl.it ]

      from enigma import (tau, irange, divisors_pairs, printf)
      
      # store the last 4 divisor counts
      ds = list()
      
      # consider increasing 3-digit numbers
      for n in irange(100, 996):
      
        # count the number of divisors (excluding 1 * n)
        d = tau(n) - 1
        ds.append(d)
        if len(ds) < 4: continue
      
        # look for sequences with the same number of (1-digit) choices
        if len(set(ds)) == 1 and ds[0] < 10:
          # now consider divisors pairs that are both 2-digits
          rs = list()
          for m in irange(n - 3, n):
            for (a, b) in divisors_pairs(m):
              if 9 < a < 100 and 9 < b < 100:
                rs.append((m, a, b))
      
          if rs:
            # output solution
            printf("rolls = {ns}, choices = {ds}", ns=list(irange(n - 3, n)))
            for (m, a, b) in rs:
              printf("  avg = {m} = {a} * {b}")
            # we're done
            break
      
        ds.pop(0)
      

      Solution: The average sheets per roll number is 242.

      The four toilet rolls have 242, 243, 244, 245 sheets. (So the average number of sheets per roll in the pack is higher that the stated average sheets per roll).

      Each roll has 5 ways to lay out the sheets in piles:

      242 = 2×121, 11×22, 22×11, 121×2, 242×1
      243 = 3×81, 9×27, 27×9, 81×3, 243×1
      244 = 2×122, 4×61, 61×4, 122×2, 244×1
      245 = 5×49, 7×35, 35×7, 49×5, 245×1

      And the “average” roll (with 242 sheets) can be laid out as 11× 22 sheets, or 22× 11 sheets.

      This is the only solution with 3-digit values.

      I checked on a 4-pack of loo rolls we have in the house, and they had an average sheet count of 221, which is not too far from the answer.

      For 4-digit values for the number of sheets per roll there are 3 different sequences that work, but only one of these has a unique answer for the average sheet count.

      Like

  • Unknown's avatar

    Jim Randell 9:28 am on 2 April 2019 Permalink | Reply
    Tags: by: B A Hill   

    Brain-Teaser 468: [Football championship] 

    From The Sunday Times, 17th May 1970 [link]

    In a home association football championship, where each of the four countries plays the others once, the teams were very evenly matched. The result was that all four countries gained the same number of points and all had the same goal average.

    England were the highest scorers in any one match, scoring 6 when beating Northern Ireland, and this also proved to be the match with the greatest number of goals. Second highest scorers were Northern Ireland, scoring 5 when beating Scotland, but there were more goals in their match with Wales when they scored 4.

    In order to decide the champions the team scoring the highest number of goals in the championship were adjudged the winners. There was one outright winner with only 2 goals separating the top and bottom teams.

    What was the aggregate number of goals for each team?

    This puzzle was originally published with no title.

    [teaser468]

     
    • Jim Randell's avatar

      Jim Randell 9:30 am on 2 April 2019 Permalink | Reply

      Using the [[ Football() ]] helper class from the enigma.py library we can find a solution to this puzzle.

      I assumed that 2 points were awarded for a win, and 1 for a draw. (With 3 points for a win there is no solution).

      This Python program runs in 295ms.

      Run: [ @repl.it ]

      from itertools import product
      from enigma import (Football, seq_all_same, irange, printf)
      
      # the scoring system
      football = Football(games="wdl", points=dict(w=2, d=1))
      
      # the teams
      (E, N, S, W) = (0, 1, 2, 3)
      
      # the match outcomes we know: E beat N, N beat S
      ms = { (E, N): 'w', (N, S): 'w' }
      
      # outcomes for the remaining four matches
      for (ms[(E, S)], ms[(E, W)], ms[(N, W)], ms[(S, W)]) in football.games(repeat=4):
      
        # make the tables
        tE = football.table(*football.extract(ms, E))
        tN = football.table(*football.extract(ms, N))
        tS = football.table(*football.extract(ms, S))
        tW = football.table(*football.extract(ms, W))
      
        # all the points are the same
        if not seq_all_same(x.points for x in (tE, tN, tS, tW)): continue
      
        # E vs N was won 6 - x, and this match had the highest number of goals (t)
        ss = dict()
        for x in irange(0, 5):
          ss[(E, N)] = (6, x)
          t = 6 + x
      
          # N vs S was won 5 - y
          for y in irange(0, 4):
            if not (5 + y < t): continue
            ss[(N, S)] = (5, y)
      
            # but there were more goals in the N vs W match, 4 - z
            for z in irange(y + 2, x + 1):
              if not (football.outcomes([(4, z)], [0])[0] == ms[(N, W)]): continue
              ss[(N, W)] = (4, z)
      
              # possible scores with fewer than t total goals and no side scoring more than 4
              scores = dict()
              scores['w'] = list((x, y) for x in irange(1, 4) for y in irange(0, x - 1) if x + y < t)
              scores['l'] = list((y, x) for (x, y) in scores['w'])
              scores['d'] = list((x, x) for x in irange(0, min((t - 1) // 2, 4)))
      
              # goals for/against N
              (fN, aN) = football.goals(*football.extract(ss, N))
      
              # consider scores in the remaining matches
              for (ss[(E, S)], ss[(E, W)], ss[(S, W)]) in product(scores[ms[(E, S)]], scores[ms[(E, W)]], scores[ms[(S, W)]]):
      
                # goals for/against E, S, W
                (fE, aE) = football.goals(*football.extract(ss, E))
                (fS, aS) = football.goals(*football.extract(ss, S))
                (fW, aW) = football.goals(*football.extract(ss, W))
                # check all goal averages are the same
                if not all(fN * a == f * aN for (f, a) in [(fE, aE), (fS, aS), (fW, aW)]): continue
      
                # sort the goals scored list
                fs = sorted([fE, fN, fS, fW], reverse=1)
                # there is a single outright winner
                if not (fs[0] > fs[1]): continue
                # and only 2 goals between the top and bottom teams
                if not (fs[0] - fs[-1] == 2): continue
      
                # output the table
                printf("E: {tE} f={fE} a={aE}")
                printf("N: {tN} f={fN} a={aN}")
                printf("S: {tS} f={fS} a={aS}")
                printf("W: {tW} f={fW} a={aW}")
                printf()
      
                # output the scores in the matches
                football.output_matches(ms, ss, teams="ENSW")
      

      Solution: Northern Ireland scored 12 goals. Wales scored 11 goals. England and Scotland each scored 10 goals.

      There is only one set of match outcomes that gives the required result:

      E vs N = 6-3
      E vs S = 1-4
      E vs W = 3-3
      N vs S = 5-2
      N vs W = 4-4
      S vs W = 4-4

      Each team ends up with 3 points (E, N, S from 1w+1d, W from 3d), and with the same number of goals for and against (giving a goal average of exactly 1).

      Like

  • Unknown's avatar

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

    Teaser 2928: Golf balls 

    From The Sunday Times, 4th November 2018 [link] [link]

    Three friends play 18 holes of golf together every week. They have a large supply of golf balls numbered from 1 to 5. At the beginning of a year, they each start playing with a new ball, but all three ball numbers are different. Alf uses the same ball number for exactly 21 holes before changing to the next higher number (or to number 1 if he was using a number 5). He continues to use each number for exactly 21 holes. The same applies to Bert, except that he changes his ball number in the same way after every 22 holes, and to Charlie who changes his ball number after every 23 holes.

    Last year, there was just one occasion when they all used the same ball number on a hole.

    What was the number of the hole on that occasion?

    [teaser2928]

     
    • Jim Randell's avatar

      Jim Randell 8:59 am on 1 April 2019 Permalink | Reply

      This Python program finds the solution constructively in 79ms.

      Run: [ @replit ]

      from enigma import (irange, subsets, singleton, printf)
      
      # increment ball count, and ball if necessary
      def inc(i, x, X):
        i += 1
        if i == X:
          x = (1 if x == 5 else x + 1)
          i = 0
        return (i, x)
      
      # find (week, hole) pairs
      def solve(A, B, C, a, b, c, n):
        i = j = k = 0
        # consider number of weeks
        for w in irange(1, n):
          # and each hole
          for h in irange(1, 18):
            if a == b == c:
              yield (w, h, b)
            # increment ball counters
            (i, a) = inc(i, a, A)
            (j, b) = inc(j, b, B)
            (k, c) = inc(k, c, C)
      
      # choose starting balls for A, B, C
      # suppose A's ball is 1, we only have to choose B and C
      a = 1
      for (b, c) in subsets((2, 3, 4, 5), size=2, select='P'):
        # in 2017 there were 52 whole weeks, + 1 extra Sunday
        rs = singleton(solve(21, 22, 23, a, b, c, 53))
        if rs:
          (w, h, x) = rs
          printf("a={a} b={b} c={c}: week={w}, hole={h}, ball={x}")
      

      Solution: Hole number 10.

      It would happen on week number 53.

      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 7:10 am on 30 March 2019 Permalink | Reply
    Tags:   

    Brainteaser 1510: Sum puzzle 

    From The Sunday Times, 18th August 1991 [link]

    In this addition sum nine digits are each represented by a different letter and the remaining one digit it represented in various places by nine letters.

    When the 47-figure number:

    INTHISADDITIONSUMNINEDIGITSAREEACHREPRESENTEDBY

    is added to the 46-digit number:

    ONELETTERANDONEDIGITISREPRESENTEDBYNINELETTERS

    the answer is the 47-figure number:

    TDODRRITECIPADAABSDLOTRSORANOHMIAGSAOTUDAYDOEOE

    What is the SOLUTION?

    The text of this puzzle is taken from the book Brainteasers (2002), so may differ from the originally published puzzle.

    [teaser1510]

     
    • Jim Randell's avatar

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

      Potentially we could just feed the entire sum as a single expression to the [[ SubstitutedExpression() ]] solver from the enigma.py library, but generating and considering all the possibilities for the 15 digits in the terms of the sum is going to take some time.

      So to help it along I provided some additional expressions, which are the sums formed taking some of the columns (in pairs, to reduce the amount of typing), linked together by carries. After 9 pairs we have mentioned each letter at least once, and the solver finds the solution in less than 200ms.

      This run-file executes in 183ms.

      Run: [ @replit ]

      #! python -m enigma -rr
      
      SubstitutedExpression
      
      --distinct=""
      --answer="SOLUTION"
      
      # use lowercase symbols for carries
      --symbols="ABCDEGHILMNOPRSTUYabcdefghi"
      --invalid="0,IOT"
      --invalid="2-9,abcdefghi"
      
      # neaten up the output
      --template=""
      --solution="ABCDEGHILMNOPRSTUY"
      
      # the entire sum
      "INTHISADDITIONSUMNINEDIGITSAREEACHREPRESENTEDBY + ONELETTERANDONEDIGITISREPRESENTEDBYNINELETTERS = TDODRRITECIPADAABSDLOTRSORANOHMIAGSAOTUDAYDOEOE"
      
      # verify the digit count in the solution
      --code="v = lambda ds: sorted(ds.count(d) for d in irange(0, 9))"
      
      "v([A, B, C, D, E, G, H, I, L, M, N, O, P, R, S, T, U, Y]) == [1, 1, 1, 1, 1, 1, 1, 1, 1, 9]"
      
      # to speed things up we break down the sum in a sequence of partial
      # sums starting from the rightmost column (in groups of 2)
      "BY + RS + 0 = aOE"
      "ED + TE + a = bOE"
      "NT + ET + b = cYD"
      "SE + EL + c = dDA"
      "RE + IN + d = eTU"
      "EP + YN + e = fAO"
      "HR + DB + f = gGS"
      "AC + TE + g = hIA"
      "EE + EN + h = iHM"
      # by this stage we have used all the letters at least once
      

      Solution: SOLUTION = 78665482

      The assignment of letters to digits is:

      A=9 D=0 E=3 I=4 N=2 O=8 R=1 S=7 T=5; {BCGHLMPUY}=6

      so the sum is:

        42564790045482766242304645791339661361373253066
      +  8236355319208230464547136137325306624236355317
        -----------------------------------------------
      = 50801145364690996706851781928664967985609608383
        ===============================================
      

      This is the only solution, even if the 18 symbols are grouped together differently (i.e. not 9 symbols standing for 1 digit each, and 9 all standing for the same remaining digit).

      Like

      • Jim Randell's avatar

        Jim Randell 3:50 pm on 27 April 2023 Permalink | Reply

        Instead of splitting the sum manually we can use the [[ SubstitutedExpression.split_sum ]] solver from the enigma.py library to do it for us.

        The following run file executes in 83ms. (Internal runtime of the generated program is 6.7ms).

        Run: [ @replit ]

        #! python3 -m enigma -rr
        
        SubstitutedExpression.split_sum
        
        --distinct=""
        --invalid="0,IOT"
        --answer="SOLUTION"
        --split=4
        
        # the entire sum
        "INTHISADDITIONSUMNINEDIGITSAREEACHREPRESENTEDBY + ONELETTERANDONEDIGITISREPRESENTEDBYNINELETTERS = TDODRRITECIPADAABSDLOTRSORANOHMIAGSAOTUDAYDOEOE"
        
        # verify the digit count in the solution (9 digits have 1 symbol, 1 digit has 9 symbols)
        --code="check = lambda ds: multiset.from_seq(ds.count(d) for d in irange(0, 9)) == {1: 9, 9: 1}"
        --extra="check([A, B, C, D, E, G, H, I, L, M, N, O, P, R, S, T, U, Y])"
        
        # neaten up the output
        --template=""
        

        Like

  • Unknown's avatar

    Jim Randell 7:44 am on 29 March 2019 Permalink | Reply
    Tags:   

    Teaser 2929: My PIN numbers 

    From The Sunday Times, 11th November 2018 [link] [link]

    Using all but one of the digits 0 to 9, and systematically replacing them by a letter, my PIN numbers become ONE, TWO, FIVE and SEVEN.

    These numbers are such that:

    ONE is odd;
    TWO is even;
    FIVE is odd and divisible by 5;
    SEVEN is divisible by 7;
    ONE + TWO + TWO = FIVE

    If I told you which digit was not used, you should be able to work out my PIN numbers.

    What PIN number is represented by SEVEN?

    [teaser2929]

     
    • Jim Randell's avatar

      Jim Randell 7:45 am on 29 March 2019 Permalink | Reply

      This Python program links together a couple of routines from the enigma.py library. First we use the [[ SubstitutedExpression() ]] solver to find solutions to the alphametic expressions, then use use the [[ filter_unique() ]] function to select solutions that have a unique unused digit.

      It runs in 90ms.

      Run: [ @replit ]

      from enigma import (SubstitutedExpression, filter_unique, unpack, printf)
      
      # the conditions
      p = SubstitutedExpression(
        [
          "ONE % 2 = 1",
          "TWO % 2 = 0",
          "FIVE % 10 = 5",
          "SEVEN % 7 = 0",
          "ONE + TWO + TWO = FIVE",
        ],
        # X is the unused digit
        answer="(X, ONE, TWO, FIVE, SEVEN)",
        # leading zeros are allowed
        d2i={},
        # [optional] output the individual solutions to the conditions
        template="[X={X}, ONE={ONE} TWO={TWO} FIVE={FIVE} SEVEN={SEVEN}]",
        header="",
        solution="",
      )
      
      # find solutions unique by X
      rs = filter_unique(p.answers(), unpack(lambda x, p1, p2, p5, p7: x)).unique
      
      # output solutions
      for (x, p1, p2, p5, p7) in rs:
        printf("unused={x} -> ONE={p1:03d} TWO={p2:03d} FIVE={p5:04d} SEVEN={p7:05d}")
      

      Solution: SEVEN = 95452.

      Like

    • GeoffR's avatar

      GeoffR 4:11 pm on 29 March 2019 Permalink | Reply

      This programme finds four answers, three of which have the same unused digit 4, whilst the last answer has the unique unused digit 3, which gives the answer ie SEVEN = 95452

      
      % A Solution in MiniZinc
      include "globals.mzn";
      
      enum letters = {O, N, E, T, W, F, I, V, S};  
      array [letters] of var 0..9: v;
      
      constraint all_different(v);
      
      % ONE is odd
      constraint (100*v[O] + 10*v[N] + v[E]) mod 2 == 1;
      
      % TWO is even
      constraint (100*v[T]  + 10*v[W] + v[O] ) mod 2 == 0;
      
      % FIVE is odd and divisible by 5
      constraint (1000*v[F] + 100*v[I] + 10*v[V] + v[E]) mod 2 == 1 
      /\ (1000*v[F] + 100*v[I] + 10*v[V] + v[E]) mod 5 == 0;
      
      % ONE + TWO + TWO = FIVE
      constraint (100*v[O] + 10*v[N] + v[E]) + 2 * (100*v[T] + 10*v[W]
       + v[O] ) == (1000*v[F] + 100*v[I] + 10*v[V] + v[E]);
      
      % SEVEN is divisible by 7
      constraint (10000*v[S] + 1000*v[E] + 100*v[V] + 10*v[E]
       + v[N]) mod 7 == 0; 
      
      % Set of all ten digits
      var set of int: s1 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
      
      % Set of digits used in the solution
      var set of int: s2 = {v[O], v[N], v[E], v[T], v[W],
       v[F], v[I], v[V], v[S]};
       
      % The unused digit
      var set of int: s3 == s1 diff s2;  
      
      solve satisfy;
      
      output [" ONE = " ++ show(v[O]), show(v[N]), show(v[E])]
      ++ ["  TWO = " ++ show(v[T]), show(v[W]), show(v[O])]
      ++ ["  FIVE = " ++ show(v[F]), show(v[I]), show(v[V]), show(v[E])]
      ++ ["\n SEVEN = " ++ show(v[S]),show(v[E]),show(v[V]),show(v[E]),show(v[N]) 
      ++ " - unused digit set: " ++ show(s3) ];
      
      %  ONE = 035  TWO = 820  FIVE = 1675  
      %  SEVEN = 95753 - unused digit set: 4..4
      %-----------------------------------------
      %  ONE = 095  TWO = 820  FIVE = 1735  
      %  SEVEN = 65359 - unused digit set: 4..4
      % -----------------------------------------
      %  ONE = 065  TWO = 830  FIVE = 1725  
      %  SEVEN = 95256 - unused digit set: 4..4
      %  ----------------------------------------
      %  ONE = 025  TWO = 860  FIVE = 1745 
      %  SEVEN = 95452 - unused digit set: 3..3 <<< answer
      % ----------
      % ==========
      % Finished in 234msec
      
      

      Like

  • Unknown's avatar

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

    Brain-Teaser 467: [Registration numbers] 

    From The Sunday Times, 10th May 1970 [link]

    There was a christening at our house last Sunday and there were three visitors’ cars in the drive.

    The car registration numbers of these three cars (disregarding any letters) each a three-digit prime number and among these numbers each of the digits 1 to 9 was used once only.

    This in itself was quite remarkable, but the sum of there three three-digit primes gave the three digit registration number of my own car.

    What were the three registration numbers of the visitors’ cars?

    This puzzle was originally published with no title.

    [teaser467]

     
    • Jim Randell's avatar

      Jim Randell 7:49 am on 28 March 2019 Permalink | Reply

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

      This run-file executes in 82ms.

      #! python -m enigma -rr
      
      SubstitutedExpression
      
      --digits="1-9"
      --answer="(ABC, DEF, GHI)"
      
      # the three 3-digit primes
      "is_prime(ABC)"
      "is_prime(DEF)"
      "is_prime(GHI)"
      
      # their sum is also a 3-digit number
      "ABC + DEF + GHI < 1000"
      
      # put them in order
      "ABC < DEF < GHI"
      

      Solution: The registration numbers are: 149, 263, 587.

      So, the setters registration number is 999.

      Like

    • GeoffR's avatar

      GeoffR 4:00 pm on 28 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);
      
      predicate is_prime(var int: x) = 
      x > 1 /\ forall(i in 2..1 + ceil(sqrt(int2float(ub(x))))) ((i < x) -> (x mod i > 0));
      
      var 100..999: ABC = 100*v[A] + 10*v[B] + v[C];
      var 100..999: DEF = 100*v[D] + 10*v[E] + v[F];
      var 100..999: GHI = 100*v[G] + 10*v[H] + v[I];
      var 100..999: XYZ;    % my car registration number
      
      constraint ABC + DEF + GHI == XYZ /\ GHI > DEF /\ DEF > ABC;
      
      constraint is_prime(ABC) /\ is_prime(DEF) /\ is_prime(GHI);
      
      solve satisfy;
      
      output[ "The three registration numbers of the visitors’ cars were " ++ show(ABC) 
      ++ ", " ++ show(DEF) ++ " and " ++ show(GHI) ]; 
      
      % The three registration numbers of the visitors’ cars were 149, 263 and 587
      
      
      

      Like

  • Unknown's avatar

    Jim Randell 7:04 am on 27 March 2019 Permalink | Reply
    Tags:   

    Teaser 2905: Trackword 

    From The Sunday Times, 27th May 2018 [link]

    George and Martha are tackling a Trackword problem which appears in magazines. Nine letters are placed in a 3×3 grid and you have to work from one square to a neighbour, proceeding up, down, left, right or diagonally until all nine squares have been visited to form a nine-letter word. You must start in the top-left corner. As an example, you can get the word EIGHTFOLD from the following grid:

    George and Martha thought that would be interesting to work out how many possible routes there are which start in the top-left corner.

    How many routes are there?

    [teaser2905]

     
    • Jim Randell's avatar

      Jim Randell 7:05 am on 27 March 2019 Permalink | Reply

      (See also: Grid Puzzle)

      There’s a handy [[ grid_adjacency() ]] function in the enigma.py library to compute the adjacency matrix on a square grid.

      This Python program can be used to calculate the number of paths on an m×n grid. For the 3×3 grid it runs in 81ms.

      Run: [ @repl.it ]

      from enigma import (grid_adjacency, icount, arg, printf)
      
      # consider an m x n grid
      m = arg(3, 0, int)
      n = arg(m, 1, int)
      
      # adjacency matrix
      adj = grid_adjacency(m, n, include_diagonal=1)
      
      # generate paths with k additional steps, prefix p, visiting different squares
      def paths(k, p):
        # are we done?
        if k == 0:
          yield p
        else:
          # extend the path
          for x in adj[p[-1]]:
            if x not in p:
              yield from paths(k - 1, p + [x])
      
      # count maximal length paths that start at square 0
      k = m * n - 1
      t = icount(paths(k, [0]))
      printf("[{m}x{n}] total paths = {t}")
      

      Solution: There are 138 different possible routes.

      From square 0 we can go to to the central square (4) or to an edge square (1 or 3), so we can just count the paths with prefix [0, 4] and [0, 1]. There will be the same number of paths with prefix [0, 3] as there are with prefix [0, 1].

      >>> icount(paths(7, [0, 4])) + 2 * icount(paths(7, [0, 1]))
      138
      

      Like

  • Unknown's avatar

    Jim Randell 7:01 am on 26 March 2019 Permalink | Reply
    Tags:   

    Brainteaser 1505: Waste not … 

    From The Sunday Times, 14th July 1991 [link]

    The “tangram” is an ancient Chinese puzzle. It consists of seven pieces which can be formed into a square (as shown) and into many other artistic shapes.

    The middle-sized triangle, the square and the parallelogram are all twice the area of the smaller triangles, and half the area of the larger ones. All the angles are 45, 90 or 135 degrees. And in my version the lengths of the shorter sides of the largest triangles are 7 cm.

    I have a thin rectangular sheet of card 70 cm by 91 cm from which I wish to cut as many such sets of tangrams as possible with the minimum amount of wastage.

    How many complete sets can I make?

    The text of this puzzle is taken from the book Brainteasers (2002), so may differ from the puzzle originally published in the newspaper.

    [teaser1505]

     
    • Jim Randell's avatar

      Jim Randell 7:03 am on 26 March 2019 Permalink | Reply

      The Tangram square shown, has sides measuring 7√2 cm. Which gives it an area of 98 cm².

      The 70 cm × 91 cm piece of card has an area of 6370 cm².

      So there is potentially enough card to make 65 complete sets with no wastage.

      However the square shown does will not fit into the length or width of the card an exact number of times.

      My solution is cut the card into 7 cm × 7 cm squares. This divides the card into 10 × 13 = 130 squares.

      We then rearrange the Tangram into two squares:

      These squares also measure 7 cm × 7cm.

      So, we then cut 65 of the squares using pattern A, and the remaining 65 sets using pattern B, giving us 65 complete Tangram sets.

      Solution: We can make 65 sets, with no wastage.

      Like

    • Lise Andreasen's avatar

      Lise Andreasen 7:28 am on 19 April 2024 Permalink | Reply

      Neat.

      Like

  • Unknown's avatar

    Jim Randell 8:40 am on 25 March 2019 Permalink | Reply
    Tags:   

    Teaser 2930: Odd socks 

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

    I had a drawer containing some black socks and some white socks. If I drew out two socks at random the chance of getting a black pair was 1 in __.

    After many washes all the socks looked grey. So I added some red socks to the drawer. Then if I drew out two at random the chance of getting a grey pair was 1 in __.

    After many washes all the socks looked pink. So I added some green socks to the drawer. Then if I drew out two the chance of getting a pink pair was 1 in __.

    After many washes all the socks looked brown. So I have now added some yellow socks to the drawer giving me a total of fewer than fifty socks. Now if I draw out two the chance of getting a brown pair is 1 in __.

    The gaps above consist of four different prime numbers.

    If I draw out two socks at random, what is the chance of getting a yellow pair?

    [teaser2930]

     
    • Jim Randell's avatar

      Jim Randell 8:41 am on 25 March 2019 Permalink | Reply

      This Python 3 program works by finding possible (prime, X, Y) tuples for choosing a pair of X socks from X+Y, and then links together the appropriate number of tuples to solve the puzzle.

      It runs in 75ms.

      Run: [ @replit ]

      from enigma import (irange, is_prime, fraction, printf)
      
      # min and max
      (m, M) = (2, 49)
      
      # find primes of the form (X + Y)(X + Y - 1) / X(X - 1)
      # where X + Y =< M and X >= m, Y >= m
      rs = list()
      for X in irange(max(m, 2), M - m):
        for Y in irange(m, M - X):
          (p, r) = divmod((X + Y) * (X + Y - 1), X * (X - 1))
          if not (r == 0 and is_prime(p)): continue
          rs.append((p, X, Y))
      
      # solve for k steps
      def solve(k, ns=None, ps=None):
        # are we done?
        if k == 0:
          yield (ns, ps)
        else:
          if not ns:
            # first step, use both X and Y
            for (p, X, Y) in rs:
              yield from solve(k - 1, [X, Y], [p])
          else:
            # subsequent steps match sum on X
            T = sum(ns)
            for (p, X, Y) in rs:
              if X == T and p not in ps:
                yield from solve(k - 1,  ns + [Y], ps + [p])
      
      # find a sequence of 4 primes
      for ((B, W, R, G, Y), (p1, p2, p3, p4)) in solve(4):
        # calculate the probability of a yellow pair
        T = B + W + R + G + Y
        (a, b) = fraction(Y * (Y - 1), T * (T - 1))
        # output solution
        printf("P(yellow) = {a}/{b} [B={B} W={W}, p1={p1}; R={R} p2={p2}; G={G} p3={p3}; Y={Y} p4={p4}; T={T}]")
      

      Solution: There is a 1 in 6 chance of getting a yellow pair.

      There are two scenarios which give the answer:

      From 3 black and 3 white, the probability a black pair is 1/5.
      From 6 grey and 9 red, the probability of a grey pair is 1/7.
      From 15 pink and 6 green, the probability of a pink pair is 1/2.
      From 21 brown and 15 yellow, the probability of a brown pair is 1/3.

      From 3 black and 4 white, the probability a black pair is 1/7.
      From 7 grey and 8 red, the probability of a grey pair is 1/5.
      From 15 pink and 6 green, the probability of a pink pair is 1/2.
      From 21 brown and 15 yellow, the probability of a brown pair is 1/3.

      But in both cases the probability of a yellow pair (from 21 brown and 15 yellow) is 1/6.

      In the puzzle I interpreted “some” to mean “at least 2”, and this gives the solution above. However, if we interpret it as “at least 1” then you get 2 further solutions, which give an answer of 1/14. (You can change the value of [[ m ]] to [[ 1 ]] in the program to see this).

      Interestingly there are no solutions (even with the relaxation of “some”) where all the numbers of different coloured socks are all even. Which certainly is an “odd” way to acquire socks.

      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 7:21 am on 23 March 2019 Permalink | Reply
    Tags:   

    Brain-Teaser 466: [Ferry fare] 

    From The Sunday Times, 3rd May 1970 [link]

    The ferryman collected 5s. when he took six horses and two prams across the river, and 5s. 9d. when he brought six bicycles and three wheel-barrows back. He is at present collecting 4s. for two wheel-barrows, three prams and a horse.

    His idiosyncratic tariff of charges is for vehicles and animals only, and not for people.

    How much will he collect for his next cargo, which awaits him on the far bank and consists of one wheel-barrow, one horse, one bicycle and one pram?

    This puzzle was originally published with no title.

    [teaser466]

     
    • Jim Randell's avatar

      Jim Randell 7:32 am on 23 March 2019 Permalink | Reply

      We note that 1 shilling (s) = 12 pence (d).

      So we have the following 3 equations (expression amounts in pence):

      [1]: 6h + 2p = 60
      [2]: 3w + 6b = 69
      [3]: 2w + 1h + 3p = 48

      There are 3 equations in 4 variables, so we cannot work out the actual prices. But we don’t need to, we are looking for the price of a particular combination.

      So, we can consider looking for multipliers t, u, v for the equations that give the required combination:

      [*]: t × [1] + u × [2] + v × [3] = 1w + 1h + 1b + 1p

      Then the amount to be collected (in pence) is then:

      t × 60 + u × 69 + v × 48

      Equating the coefficients of w, h, b, p we get the following 4 equations:

      [w]: 3u + 2v = 1
      [h]: 6t + v = 1
      [b]: 6u = 1
      [p]: 2t + 3v = 1

      which is 4 equations in 3 variables, so we try to solve them:

      From [b]:

      u = 1/6

      Then from [w]:

      v = 1/4

      and from [h]:

      t = 1/8

      And we can check [p] gives the right value (which it does).

      So the equations are consistent, and the solution is:

      60/8 + 69/6 + 48/4 = 31 (pence)

      Solution: He will collect 2s 7d.


      Here’s a Python program that does the same thing using the Gaussian elimination solver for linear equations from the enigma.py library. (Originally written for Enigma 287).

      It runs in 87ms.

      from enigma import (Matrix, printf)
      
      # solve the equations
      (t, u, v) = Matrix.linear([[0, 3, 2], [6, 0, 1], [0, 6, 0], [2, 0, 3]], [1, 1, 1, 1])
      
      # determine the answer in pence
      x = t * 60 + u * 69 + v * 48
      # ... in shillings and pence
      (s, d) = divmod(x, 12)
      
      printf("fare = {s}s {d}d [t={t} u={u} v={v}]")
      

      Like

  • Unknown's avatar

    Jim Randell 7:58 am on 22 March 2019 Permalink | Reply
    Tags:   

    Teaser 2931: Unfortunate 57 

    From The Sunday Times, 25th November 2018 [link] [link]

    In the early days of the internet, I used a secret shorthand for my important passwords:

    Bank=1/7, Credit Card=2/7, ISP=3/7, etc.

    Like all fractions, the decimal expansions:

    1/7 = 0.142857142857142…
    2/7 = 0.285714285714285…

    eventually repeat themselves, in this case in sequences of six digits. In each case, my password was the set of digits that repeat (“Unfortunate 57” is a mnemonic for 142857). As password requirements became stricter, I changed my system to base 11, using an X for the extra digit for “ten”; so for instance in base 11:

    234 (= 1 × 11^2 + 10 × 11^1 + 3 × 11^0) is 1X3 [base 11], and;
    1/2 = 0.5555… [base 11] = 5 / (11^1) + 5 / (11^2) + 5 / (11^3) + …

    In the sequence 1/2, 1/3, …, what is the first password of length greater than six that my base-11 system produces?

    The setter is probably conflating “the internet” with “the world wide web”.

    [teaser2931]

     
    • Jim Randell's avatar

      Jim Randell 7:58 am on 22 March 2019 Permalink | Reply

      For Enigma 1247 I wrote the [[ recurring() ]] function, which will calculate the recurring representation of a fraction in a given base.

      We can use this routine in a short Python program to solve this puzzle. It runs in 74ms.

      Run: [ @replit ]

      from enigma import (irange, inf, recurring, format_recurring, printf)
      
      for x in irange(2, inf):
        (i, nr, rr) = recurring(1, x, base=11, digits='0123456789X')
        printf("1 / {x} = {f} [period = {n}]", f=format_recurring(i, nr, rr), n=len(rr))
        if len(rr) > 6: break
      

      Solution: The first password with length greater than 6 is: 093425X17685.

      It is produced by the fraction 1/13 (in decimal notation).

      Like

    • Lise Andreasen's avatar

      Lise Andreasen 7:17 am on 19 April 2024 Permalink | Reply

      In the early days of the internet, we had SMTP (email), FTP etc.

      Like

  • Unknown's avatar

    Jim Randell 7:08 am on 21 March 2019 Permalink | Reply
    Tags:   

    Teaser 1986: Protracted calculation 

    From The Sunday Times, 8th October 2000 [link]

    In the circle illustrated the numbers represent the sizes of the sectors:

    By combining adjacent ones it is possible to find sectors in this circle of sizes 1, 2, 3, … all the way up to 13 (13 being the whole circle). For example:

    7 = 4 + 1 + 2.

    In a similar fashion, given a circle divided into five sectors in a particular way, it is possible to combine adjacent sectors to give sizes 1, 2, 3, … up to the biggest possible in the circumstances.

    What, in increasing order, are the sizes of the five sectors?

    The text of this puzzle is taken from the book Brainteasers (2002), the wording differs only slightly from the puzzle originally published in the newspaper.

    [teaser1986]

     
    • Jim Randell's avatar

      Jim Randell 7:09 am on 21 March 2019 Permalink | Reply

      If the circle is divided into k sectors, then for each starting sector (and there are k of them) we can make a contiguous region consisting of 1, 2, 3, …, (k − 1) sectors. We don’t make a region of k sectors because that is the whole circle, so we add that in separately giving a total number of arrangements of:

      n(k) = k(k − 1) + 1 = k² − k + 1

      To make the arrangements correspond to the numbers 1, 2, 3, … n(k), the whole circle needs to correspond to the value n(k), and there needs to be a single sector corresponding to the number 1. So we place the number 1 in the first sector, and then distribute the remaining (n(k) − 1) between the remaining (k − 1) sectors.

      This Python 3 program finds the solution in 83ms.

      Run: [ @replit ]

      from itertools import permutations
      from enigma import (irange, arg, printf)
      
      # generate (non-empty) tuples of adjacent sectors
      def sectors(k):
        # consider n consecutive sectors
        for n in irange(1, k - 1):
          # possible start sector
          for i in irange(0, k - 1):
            yield tuple((i + j) % k for j in irange(0, n - 1))
        # the whole circle
        yield tuple(irange(0, k - 1))
      
      # decompose <t> into <n> different numbers, min <m>
      def decompose(t, n, m, s=[]):
        if n == 1:
          if not (t < m):
            yield s + [t]
        else:
          for x in irange(m, t - n):
            yield from decompose(t - x, n - 1, x + 1, s + [x])
      
      # number of sectors to divide the circle into
      k = arg(5, 0, int, prompt="number of sectors")
      assert k > 1
      
      # make a list of adjacent sectors
      ss = list(sectors(k))
      t = len(ss)
      printf("[k={k}: {t} arrangements]")
      
      # put 1 at sector 0, and decompose the remainder
      for d in decompose(t - 1, k - 1, 2):
        for p in permutations(d):
          if p[0] > p[-1]: continue
          s = (1,) + p
          # calculate the values of adjacent sectors
          vs = set(sum(s[i] for i in x) for x in ss)
          if len(vs) == t:
            printf("{s}")
      

      Solution: The five sectors have values: 1, 2, 3, 5, 10 (in numerical order).

      They can be arranged like this:

      As well as the example given it is also possible to make a circle with 4 sectors using the values: 1, 3, 2, 7.

      The program is suitable for experimenting with small values of k. (One simple way to improve the program is to note that as well as a 1 sector, we will also need a 2 sector in the remaining decomposition).

      Here are the number of solutions for various values of k:

       k  n(k)  solutions
       1     1    1
       2     3    1
       3     7    1
       4    13    2
       5    21    1
       6    31    5
       7    43    0
       8    57    6
       9    73    4
      10    91    6
      11   111    0
      12   133   18
      13   157    0
      14   183   20
      ...

      (See: OEIS A058241 [ link ]).

      We’ve come across the following formula before:

      n(k) = k^2 − k + 1

      Specifically in the exploration of Teaser 2907, where it is the number of elements in a finite projective plane of order (k − 1).

      The fact that there is no solution for (k = 7, n = 43), (k = 11, n = 111) and (k = 13, n = 157) makes me wonder if there is a link with projective planes, as finite projective planes of order 6, 10, and 12 (probably) do not exist.


      For a more efficient way to generate “magic circles” see my comment on Enigma 985.

      Like

      • Frits's avatar

        Frits 11:47 am on 13 June 2022 Permalink | Reply

        @Jim,

        You might use (and in Enigma 985):

           
        for x in irange(m, t - n * (n - 1) // 2):
        

        in decompose() as we need different numbers. It doesn’t seem to make much of a difference in the performance.

        Like

        • Jim Randell's avatar

          Jim Randell 11:29 am on 14 June 2022 Permalink | Reply

          @Frits: If I were to re-write the code now I would probably just use [[ decompose() ]] from enigma.py (and [[ tuples() ]] to generate the adjacent sectors). [See: @replit]

          from enigma import (irange, tuples, decompose, arg, printf)
          
          # generate (non-empty) tuples of adjacent sectors
          def sectors(k):
            # the whole circle
            t = tuple(irange(k))
            # consider n consecutive sectors
            for n in irange(1, k - 1):
              yield from tuples(t, n, circular=1)
            # and the whole circle
            yield t
          
          # number of sectors to divide the circle into
          k = arg(5, 0, int)
          assert k > 1
          
          # make a list of adjacent sectors
          ss = list(sectors(k))
          t = len(ss)
          printf("[k={k}: {t} arrangements]")
          
          # put 1 at sector 0, and 2 somewhere, and decompose the remainder
          for d in decompose(t - 3, k - 2, increasing=0, sep=1, min_v=3, fn=list):
            # insert 2 somewhere
            for i in irange(0, (0 if k == 2 else k - 3)):
              s = list(d)
              s.insert(i, 2)
              if s[0] > s[-1]: continue
              # insert 1 at sector 0
              s.insert(0, 1)
              # calculate the value for adjacent sectors
              vs = set(sum(s[i] for i in x) for x in ss)
              if len(vs) == t:
                printf("{s}", s=tuple(s))
          

          But using magic_circles.py gives a much shorter and faster program:

          from enigma import (arg, printf)
          from magic_circles import magic_circle
          
          # number of sectors to divide the circle into
          k = arg(5, 0, int, prompt="number of sectors")
          assert k > 1
          
          # find magic k-circles
          for s in magic_circle(k):
            # output solution
            printf("{s}")
          

          Like

  • Unknown's avatar

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

    Teaser 2932: Triangulation 

    From The Sunday Times, 2nd December 2018 [link] [link]

    Liam plans to make a set of dominoes. They will be triangular, and one face of each domino will have a number at each corner. The numbers run from 0 up to a maximum digit (9 or less), and the set is to include all possible distinguishable dominoes.

    With the maximum digit he has chosen the set would contain a triangular number of dominoes. [A triangular number is one where that number of balls can fit snugly in an equilateral triangle, for example the 15 red balls on a snooker table].

    How many dominoes will he need to make?

    [teaser2932]

     
    • Jim Randell's avatar

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

      For each maximum digit, this Python program constructs all possible dominoes that are unique by rotation. It runs in 75ms.

      Run: [ @repl.it ]

      from itertools import product
      from enigma import (irange, is_triangular, printf)
      
      for d in irange(0, 9):
        s = set()
        # choose three numbers for the corners
        for (a, b, c) in product(irange(0, d), repeat=3):
          # record the domino by it's minimal rotation
          s.add(min((a, b, c), (b, c, a), (c, a, b)))
      
        # count the number of different dominoes
        n = len(s)
        t = ('[triangular]' if is_triangular(n) else '')
        printf("d={d}: {n} dominoes {t}")
      

      Solution: He will need to make 45 dominoes.

      There is a degenerate solution where only the digit 0 is used. There is only one domino (0, 0, 0), and 1 is a triangular number T(1) = 1.

      Running the program we see the number dominoes is given by the following sequence:

      1, 4, 11, 24, 45, 76, 119, 176, 249, 340

      which is OEIS A006527 [ link ] the general formula is:

      a(n) = n (n² + 2) / 3

      so we don’t have to count the dominoes.

      from enigma import (irange, is_triangular, printf)
      
      for d in irange(1, 10):
        n = (d**3 + 2 * d) // 3
        t = ('[triangular]' if is_triangular(n) else '')
        printf("d={d}: {n} dominoes {t}", d=d - 1)
      

      If we consider d > 9 there are larger solutions at d = 12 (741 dominoes) and d = 35 (15576 dominoes).

      Like

  • Unknown's avatar

    Jim Randell 7:04 am on 19 March 2019 Permalink | Reply
    Tags: ,   

    Brain-Teaser 465: [Lifts] 

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

    Near my house is an impressive block of flats. It stands 16 storeys high, and each story is a lofty 15 feet from floor to floor. My old friends Bob and Horace operate the two lifts, and both start their shift each morning leaving the ground floor at 8 a.m. precisely.

    The two lifts make automatic compulsory stops at the ground level (there is no basement), the 12th and top floors. But below the 12th, Bob serves only the odd-numbered floors, and Horace the even numbers; these stops are also compulsory (up and down). All stops take just 10 seconds, except at ground level where both lifts wait for 20 seconds.

    Above the 12th both Bob and Horace stop as desired, going up and coming down. Both lifts travel between floors at identical speeds.

    Every morning the two attendants make a rendezvous to exchange newspapers and collect their coffee when their arrivals at a certain floor coincide exactly at two minutes after 11 a.m.

    In feet per second what the speed of each lift between stops?

    Note: In the UK the floors in buildings are: ground floor, first floor, second floor, etc.

    Also, as stated this puzzle does not appear to have a unique solution.

    An answer was published (with Teaser 467) stating:

    “This clever trap, with its nice reasoning, outweighed the slight mathematical bias and kept down the entry to a mixed handful.”

    But later, with Teaser 471 the following statement was made:

    “[465: Regretfully a wrong transposition led to a false calculation of time.]”

    In the comments I give a variation on the puzzle that does have a unique answer.

    This puzzle was originally published with no title.

    [teaser465]

     
    • Jim Randell's avatar

      Jim Randell 7:05 am on 19 March 2019 Permalink | Reply

      Replacing the third paragraph (“Above the 12th floor…”) with the following gives a puzzle that does have a unique solution, and it is the same as the published answer.

      The 13th floor is considered to be unlucky, so at the beginning of each day the attendants toss a coin to decide who should service it that day. The loser has to stop at the 13th floor each time they pass it, and the winner stops at the 14th floor each time they pass it. Both lifts take the same amount of time to travel between adjacent floors.

      This Python program can be used to investigate situations where the attendants follow a fixed schedule of stops. And it solves this variation puzzle in 412ms.

      Run: [ @repl.it ]

      from fractions import Fraction as F
      from enigma import printf
      
      # number of seconds between 08:00:00 and 11:02:00
      S = (3 * 60 + 2) * 60
      
      # wait at each floor (seconds)
      wait = [20] + [10] * 15
      
      # generate (<floor>, <seconds>, <n floors>)
      def stops(fs, wait=wait):
        s = n = f = 0
        while True:
          # going up
          for (i, x) in enumerate(fs):
            if i == 0: continue
            s += wait[f]
            n += (x - f)
            f = x
            yield (f, s, n)
          # going down
          for (i, x) in enumerate(reversed(fs)):
            if i == 0: continue
            s += wait[f]
            n += (f - x)
            f = x
            yield (f, s, n)
      
      # collect possible (f, s, n) tuples
      def collect(fs, xs):
        for (f, s, n) in stops(fs):
          if not (s < S): break
          if f in xs: yield (f, s, n)
      
      # solve for specific floors visited by B and H
      def solve(B, H):
        # find common floors
        xs = set(B).intersection(H)
        # collect (<floor>, <seconds>, <n floor>) tuples for each
        Bs = list(collect(B, xs))
        Hs = list(collect(H, xs))
      
        # consider possible meeting stops for B (at time S)
        for (fB, sB, nB) in Bs:
          # calculate time between floors
          t = F(S - sB, nB)
          # look for matching stops for H
          for (fH, sH, nH) in Hs:
            if fH == fB and sH + t * nH == S:
              printf("t={t}s [floor={fB}, B=(wait={sB}s, floors={nB}), H=(wait={sH}s, floors={nH})]")
      
      # send B to floor 13, H to floor 14
      solve(
        [0, 1, 3, 5, 7, 9, 11, 12, 13, 15], # floors for B
        [0, 2, 4, 6, 8, 10, 12, 14, 15], # floors for H
      )
      

      Solution: The time between floors is 3s, giving an average speed of 5 ft/s.

      By 11:02 am, Bob has spent 7410s waiting and travelled 1170 floors. Horace has has waited for 7140s and travelled 1260 floors.

      Like

  • Unknown's avatar

    Jim Randell 7:41 am on 18 March 2019 Permalink | Reply
    Tags:   

    Teaser 2933: Sunday Teaser 

    From The Sunday Times, 9th December 2018 [link] [link]

    I wrote down two three-figure numbers and worked out their product by long multiplication. Systematically replacing digits by letters, my workings became:

    I then wrote down two numbers which were represented by SUNDAY TEASER.

    What were these two numbers?

    [teaser2933]

     
    • Jim Randell's avatar

      Jim Randell 7:42 am on 18 March 2019 Permalink | Reply

      This alphametic problem can be solved directly using the [[ SubstitutedExpression() ]] solver in the enigma.py library.

      The following run file executes in 123ms.

      Run: [ @repl.it ]

      #! python3 -m enigma -rr
      
      SubstitutedExpression
      
      --answer="(SUNDAY, TEASER)"
      
      "NTS * EDS = ARRATS"
      
      "NTS * S = DURS"
      "NTS * D = YRD"
      "NTS * E = ANDU"
      

      Solution: SUNDAY = 684219; TEASER = 731635.

      Like

    • GeoffR's avatar

      GeoffR 9:48 am on 2 December 2020 Permalink | Reply

      
      from itertools import permutations
      digits = set('1234567890')
      
      for P1 in permutations(digits, 7):
        n, t, s, e, d, a, r = P1
        if '0' in (n, e, d, a, t, s):
          continue
        nts, eds = int(n + t + s), int(e + d + s)
        arrats = int(a + r + r + a + t + s)
        if nts * eds == arrats:
      
          # find remaining digits
          Q1 = digits.difference(P1)
          for P2 in permutations(Q1, 2):
            u, y = P2
            durs, yrd = int(d + u + r + s), int(y + r + d)
            andu = int(a + n + d + u)
            if int(s) * nts == durs:
              if int(d) * nts == yrd:
                if int(e) * nts == andu:
                  if durs + yrd * 10 + andu * 100 == arrats:
                    SUNDAY = int(s + u + n + d + a + y)
                    TEASER = int(t + e + a + s + e + r)
                    print(f"SUNDAY = {SUNDAY}, TEASER = {TEASER}")
                    print(f"Main sum: {nts} x {eds} = {arrats}")
      
      # SUNDAY = 684219, TEASER = 731635
      # Main sum: 476 x 326 = 155176
      
      
      

      Like

    • Frits's avatar

      Frits 9:31 pm on 2 December 2020 Permalink | Reply

      A different approach, not very efficient.

      from enigma import nconcat
      
      # get integer value for string <s>
      getvar = lambda vals, template, s: nconcat(vals[template.index(x)] for x in s)
      
      LETTERS = "SDNTURYAE" 
      VARLIST = ["NTS", "DURS", "S", "D", "YRD", "E", "ARRATS", "EDS", "ANDU"]
      
      # minimum values of letters
      RNGMIN = [1, 1, 1, 1, 0, 1, 1, 1, 1]
      
      def solve(t, ns=[]):
        if t == 0:  # we have set all letters
          # calculate variables (we need to store results in a dictionary)
          ex = ""
          d = dict()
          for v in VARLIST:
            ex += "d['" + v + "'] = getvar(ns, LETTERS, '" + v + "');\n"  
          exec(ex)
        
          # perform final checks  
          if d["NTS"] * d["EDS"] != d["ARRATS"]: return
          if d["NTS"] * d["S"] != d["DURS"]: return
          if d["NTS"] * d["D"] != d["YRD"]: return
          if d["NTS"] * d["E"] != d["ANDU"]: return
          
          yield ns
        else:
          if t == 8:       # variable S read, check (S*S) % 10 = S
            if ns[0]**2 % 10 != ns[0]:
              return
          if t == 7:       # variable S and D read, check (S*D) % 10 = D
            if (ns[0] * ns[1]) % 10 != ns[1]:
              return    
          if t == 3:       # variable S,D,N,T,U,R read
            ex = ""
            d = dict()
            for v in VARLIST[:3]:
              ex += "d['" + v + "'] = getvar(ns, LETTERS, '" + v + "');\n" 
            exec(ex)
            if d["NTS"] * d["S"] != d["DURS"]: 
              return
            
          for n in range(RNGMIN[len(LETTERS) - t], len(LETTERS) + 1):
            if n not in ns:   # variables all diffferent
              yield from solve(t - 1, ns + [n])
      
      res = solve(len(LETTERS))
      for r in res: 
        print(f"SUNDAY = {getvar(r, LETTERS, 'SUNDAY')} "
              f"TEASER = {getvar(r, LETTERS, 'TEASER')}")
      
      
      # SUNDAY = 684219 TEASER = 731635
      

      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