Tagged: by: Rex Gooch Toggle Comment Threads | Keyboard Shortcuts

  • Unknown's avatar

    Jim Randell 11:29 am on 24 January 2023 Permalink | Reply
    Tags: by: Rex Gooch   

    Teaser 1850: Linear town 

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

    The new transcontinental road across Eastern Europe into Asia was to outshine the Pan-American Highway, in that the old concept of a linear town had been revived. It was to have houses on each side of its entire length. Even the contract for the house numbers was huge. They started at 1 and ran to a neatly bureaucratic 1 followed by a number of noughts. One manufacturer’s representative delayed by her sick child, arrived just before the deadline to submit a bid to provide all the digits required. Unfortunately her computer had been programmed to calculate the sum of all the digits required, rather than the number of digits. This incorrect answer started with some digits that formed a number equal to the cube of her daughter’s age. Luckily, from this total she was able to work out the number of digits actually needed.

    How many digits were needed?

    [teaser1850]

     
    • Jim Randell's avatar

      Jim Randell 11:30 am on 24 January 2023 Permalink | Reply

      Let N(k) be the number of digits used when expressing the numbers [0, …, (10^k) − 1] in decimal.

      We can start with:

      N(1) = len([0, …, 9]) = 10

      And if we think about moving from N(k) to N(k + 1) then we need to add in the (k + 1) digit numbers.

      These come in 9 groups, each consisting of 10^k numbers each with (k + 1) digits.

      N(1) = 10
      N(k + 1) = N(k) + 9(k + 1)10^k

      At each stage the number of digits required for the house numbers [1, …, 10^k] is:

      N'(k) = N(k) − 1 + k + 1
      N'(k) = N(k) + k

      Similarly we can calculate S(k), the sum of the digits in the numbers [0, …, 10^(k − 1)].

      We start with:

      S(1) = sum([0, …, 9]) = 45

      And if we think about moving from N(k) to N(k + 1), then we add in the (k + 1) digit numbers.

      There are 9 groups, each of which considers of 10^k numbers, that start with digits 1 .. 9, and the non-leading digits of each group sum to S(k)

      S(k + 1) = S(k) + 45.10^k + 9.S(k) = 10.S(k) + 45.10^k

      Hence:

      S(1) = 45
      S(k + 1) = 10.S(k) + 45.10^k

      And the required sum of the digits for the houses numbered [1, …, 10^k] is:

      S'(k) = S(k) + 1

      The following Python program calculates increasing (k, N(k), S(k)) values, until we find appropriate values to solve the puzzle.

      It runs in 50ms. (Internal runtime is 109µs).

      Run: [ @replit ]

      from enigma import (irange, cb, join, printf)
      
      # generate: (k, N(k), S(k)) values
      def generate():
        k = 1
        m = 10
        N = 10
        S = 45
        while k < 10:
          yield (k, N, S)
          N += 9 * (k + 1) * m
          S *= 10
          S += 45 * m
          k += 1
          m *= 10
      
      # suppose the child is aged between 3 and 16
      cubes = set(str(cb(x)) for x in irange(3, 16))
      
      # consider increasing values
      for (k, N, S) in generate():
        # adjust for numbers [1 ... 10^k]
        N += k
        S += 1
        # look for matching prefixes
        S = str(S)
        xs = list(x for x in cubes if S.startswith(x))
        if xs:
          printf("N(10^{k}) = {N}; S(10^{k}) = {S}; prefix = {xs}", xs=join(xs, sep=", "))
          break
      

      Solution: The number of digits required is: 5,888,896.

      The houses are numbered from 1 to 1,000,000.

      The sum of the digits required is: 27,000,001.

      Which has a prefix of 27, so the child is aged 3.

      Like

  • Unknown's avatar

    Jim Randell 9:29 am on 27 December 2022 Permalink | Reply
    Tags: by: Rex Gooch   

    Teaser 1882: Multiple solutions 

    From The Sunday Times, 11th October 1998 [link]

    One of the neatest problems ever published appeared on this page as Brainteaser 1040, on July 4, 1982. It asked for a number consisting of one each of the digits 1 to 9, so that the first digit of the number was divisible by 1, the first two (taken as a two-digit integer) by 2, and so on to 9. The answer was: 381654729.

    The reverse of this problem is to use one of each digit to form a number of which the last digit is divisible by 1, the last two (taken as a two-digit integer) by 2, and so on, to 9 or 10, according to whether we use the digits 1 to 9 or 0 to 9.

    There are, sadly, many answers. If you examined the last three digits of all the answers, and regarded them as three-digit numbers, it would strike you that they all had a large (highest) common factor.

    Curiously, only one multiple of that factor (consisting of three different digits) fails to occur as the last three digits of an answer.

    Which number is it that fails to occur?

    [teaser1882]

     
    • Jim Randell's avatar

      Jim Randell 9:31 am on 27 December 2022 Permalink | Reply

      See also: Teaser 1040, Teaser 3053.

      This Python program uses the [[ SubstitutedExpression ]] solver from the enigma.py library to find answers to the embedded puzzle. It then calculates the GCD of the answers, and looks for 3-digit multiples of this value that do not occur.

      It runs in 62ms.

      Run: [ @replit ]

      from enigma import (SubstitutedExpression, mgcd, irange, nsplit, printf)
      
      # suppose the number is: ABCDEFGHIJ
      p = SubstitutedExpression(
        [
          "IJ % 2 = 0",
          "HIJ % 3 = 0",
          "GHIJ % 4 = 0",
          "FGHIJ % 5 = 0",
          "EFGHIJ % 6 = 0",
          "DEFGHIJ % 7 = 0",
          "CDEFGHIJ % 8 = 0",
          "BCDEFGHIJ % 9 = 0",
          "ABCDEFGHIJ % 10 = 0", # or: "0 = J"
        ],
        d2i=dict(),
        answer="HIJ",
      )
      
      # solve the puzzle and accumulate the answers
      ns = set(p.answers(verbose=0))
      # calculate the gcd of the answers
      g = mgcd(*ns)
      
      # look for 3-digit multiples of g
      for m in irange.round(100, 999, step=g, rnd='I'):
        # does not occur in an answer
        if m in ns: continue
        # has 3 different digits
        if len(set(nsplit(m, 3))) != 3: continue
        # output solution
        printf("multiple = {m} [gcd = {g}]")
      

      Solution: The 3-digit multiple that does not occur is: 960.

      There are 202 answers to the embedded puzzle. And the final 3 digits of each answer form a multiple of 120.

      Like

    • GeoffR's avatar

      GeoffR 9:41 am on 28 December 2022 Permalink | Reply

      This program finds the maximum number of solutions and sets of digits for HIJ values.

      From the output values in the HIJ set, it can be readily seen that the gcd is 120 and the missing multiples of this gcd are 600 and 960. 600 can be ruled out as a solution as it contains repeating digits, so the missing gcd multiple is 960 (8 x 120).

      from functools import reduce
      
      # convert digit sequence to number
      d2n = lambda s: reduce(lambda x,  y: 10 * x + y, s)
      
      J = 0   # 10th last digit
      cnt = 0  # counter for number of solutions
      dig3 = set()  # set for all different values of HIJ
      
      for I in range(1, 10):
        IJ = d2n([I, J])
        if IJ % 2 != 0:continue
        
        for H in range(1, 10):
          if H in (I, J): continue
          HIJ = d2n([H, I, J])
          if HIJ % 3 != 0: continue
          
          for G in range(1, 10):
            GHIJ = d2n([G, H, I, J])
            if G in (H, I, J): continue
            if GHIJ % 4 != 0:continue
             
            for F in range(1, 10):
              if F in (G, H, I, J): continue
              FGHIJ = d2n([F, G, H, I, J])
              if FGHIJ % 5 != 0: continue
              
              for E in range(1, 10):
                if E in (F, G, H, I, J):continue
                EFGHIJ = d2n([E, F, G, H, I, J])
                if EFGHIJ % 6 != 0:continue
                
                for D in range(1, 10):
                  if D in (E, F, G, H, I, J):continue
                  DEFGHIJ = d2n([D, E, F, G, H, I, J])
                  if DEFGHIJ % 7 != 0:continue
                  
                  for C in range(1, 10):
                    if C in (D, E, F, G, H, I, J):continue
                    CDEFGHIJ = d2n([C, D, E, F, G, H, I, J])
                    if CDEFGHIJ % 8 != 0: continue
                    
                    for B in range(1, 10):
                      if B in (C, D, E, F, G, H, I, J):continue
                      BCDEFGHIJ = d2n([B, C, D, E, F, G, H, I, J])
                      if BCDEFGHIJ % 9 != 0:continue
                      
                      for A in range(1, 10):
                        if A in (B, C, D, E, F, G, H, I, J):continue
                        ABCDEFGHIJ = d2n([A, B, C, D, E, F, G, H, I, J])
                        if ABCDEFGHIJ % 10 != 0:continue
                        # update HIJ digit set and number of solutions
                        dig3.add(HIJ)
                        cnt += 1
      
      print('Number of solutions = ', cnt)  
      print('HIJ set = ', dig3)  
      
      # Number of solutions =  202
      # HIJ set =  {480, 840, 360, 240, 720, 120}
      
      
      
      
      

      Like

  • Unknown's avatar

    Jim Randell 8:36 am on 6 August 2019 Permalink | Reply
    Tags: by: Rex Gooch   

    Brainteaser 1635: Double anagram 

    From The Sunday Times, 9th January 1994 [link]

    In the woodwork class the ABLEST students made STABLE TABLES.

    In the arithmetic class the cleverest students took those three six-letter words which were anagrams of each other, and they then assigned a different digit to each of the six letters involved. Substituting letters for digits then gave them three six-figure numbers.

    They found that one of the numbers was the sum of the other two. Furthermore, no matter what alternative substitution of digits they had used, they could never have achieved this coincidence with a lower sum.

    (a) Which word was the sum?
    (b) What was its numerical value?

    This puzzle is included in the book Brainteasers (2002). The text was changed slightly, but the puzzle remains the same.

    [teaser1635]

     
    • Jim Randell's avatar

      Jim Randell 8:37 am on 6 August 2019 Permalink | Reply

      This program uses the [[ SubstitutedExpression() ]] solver from the enigma.py library to solve the alphametic problem, and an [[ Accumulator() ]] object to find the smallest solution. It runs in 299ms.

      Run: [ @replit ]

      from enigma import (SubstitutedExpression, Accumulator, sprintf as f, join, printf)
      
      # the three words
      words = ("ABLEST", "STABLE", "TABLES")
      
      # the alphametic puzzle
      ws = join(words, sep=",", enc="()")
      p = SubstitutedExpression(f("sum({ws}) == 2 * max({ws})"), answer=ws)
      
      # look for a minimal solution
      r = Accumulator(fn=min)
      
      # solve the alphametic
      for ans in p.answers(verbose=0):
        # find the result of the sum
        s = max(ans)
        # and which word is the result
        i = ans.index(s)
        r.accumulate_data(s, i)
      
      # output the minimal solution
      printf("{word} = {r.value} [of {r.count} possible sums]", word=words[r.data])
      

      Solution: TABLES = 417582.

      The corresponding alphametic sum is: ABLEST + STABLE = TABLES.

      There are 18 possible solutions to this alphametic.

      Like

    • GeoffR's avatar

      GeoffR 1:29 pm on 6 August 2019 Permalink | Reply

      I tried the three possible addition sums, looking for the smallest total. Two of these sums proved unsatisfiable. The third addition sum gave two possible values for TABLES, the smallest of which agreed with Jim’s solution.

      % A Solution in MiniZinc
      include "globals.mzn";
      
      var 1..9: A; var 0..9: B; var 0..9: L;
      var 0..9: E; var 1..9: S; var 1..9: T;
      
      constraint all_different([A, B, L, E, S, T]);
      
      var 100000..999999: ABLEST = 100000*A + 10000*B + 1000*L + 100*E + 10*S + T;
      var 100000..999999: STABLE = 100000*S + 10000*T + 1000*A + 100*B + 10*L + E;
      var 100000..999999: TABLES = 100000*T + 10000*A + 1000*B + 100*L + 10*E + S;
      
      %constraint ABLEST == STABLE + TABLES;
      %solve minimize(ABLEST);
      %output ["ABLEST = " ++ show(ABLEST) ];  % =====UNSATISFIABLE=====
      
      %constraint STABLE == ABLEST + TABLES;
      %solve minimize(STABLE);
      %output ["STABLE = " ++ show(STABLE) ];  % =====UNSATISFIABLE=====
      
      constraint TABLES == ABLEST + STABLE;
      solve minimize(TABLES);
      output ["TABLES = " ++ show(TABLES)  ++ " = " ++ show(ABLEST) ++ " + " ++ show(STABLE)];
      
      % TABLES = 428571 = 285714 + 142857
      % ----------
      % TABLES = 417582 = 175824 + 241758  << smallest answer for value of TABLES
      % ----------
      % ==========
      
      
      

      Like

      • John Crabtree's avatar

        John Crabtree 6:21 pm on 8 August 2019 Permalink | Reply

        With TABLES as the sum, ABLE = 999(T-S) – 100S – 10T. This enables the desired solution, as well as all of the possible 18 found by Jim, to be easily found.

        Like

    • Frits's avatar

      Frits 2:36 pm on 27 July 2020 Permalink | Reply

      Substituted expression which returns only one solution (minimized on first part of answer):

      # The following function has been manually added to enigma.py
      #
      # def substituted_expression_minimum(*args, **kw):
      #   if 'verbose' not in kw: kw['verbose'] = 0
      #   answs = []
      #   for r in SubstitutedExpression(*args, **kw).solve():
      #     answs.append(r)
      #   answs.sort(key=lambda x: x[1])  
      #   if len(answs) > 0:
      #       yield answs[0]
      
      
      from enigma import substituted_expression_minimum, printf, irange
      
      # the alphametic puzzle
      p = substituted_expression_minimum(\
          [\
          # if one element in (X,Y,Z) is sum of 2 others then sum(X,Y,Z) = 2*max(X,Y,Z)
          # in this way we don't have to specify it is Z=X+Y, Y=X+Z or X=Y+Z 
          "TABLES + ABLEST + STABLE == 2 * max(TABLES, ABLEST, STABLE)",\
          "max(TABLES, ABLEST, STABLE) = HIGNUM",\
          "not(is_duplicate(TABLES))",\
          "not(is_duplicate(ABLEST))",\
          "not(is_duplicate(STABLE))"],\
          distinct="",   # needed for HIGNUM \   
          answer="HIGNUM, ABLEST, STABLE, TABLES",\
          verbose=0)      
                                
      for (_, ans) in p: 
        if ans[1] == ans[0]: printf("ABLEST is the sum with value {ans[1]}")
        if ans[2] == ans[0]: printf("STABLE is the sum with value {ans[2]}")
        if ans[3] == ans[0]: printf("TABLES is the sum with value {ans[3]}")
      

      Like

      • Frits's avatar

        Frits 3:12 pm on 27 July 2020 Permalink | Reply

        @Jim:

        Any idea why I needed the HIGNUM field?

        p = substituted_expression_minimum(\
            [\
            "TABLES + ABLEST + STABLE == 2 * max(TABLES, ABLEST, STABLE)"],\
            answer="TABLES + ABLEST + STABLE, ABLEST, STABLE, TABLES",\
            verbose=0)   
        

        Using this setup I got no results (even with distinct=””).

        Like

        • Jim Randell's avatar

          Jim Randell 3:33 pm on 27 July 2020 Permalink | Reply

          @Frits: I think you get no answers because you are checking to see when one of the summands is equal to the sum total (which is never).

          Try using:

          answer="(max(TABLES, ABLEST, STABLE), ABLEST, STABLE, TABLES)"
          

          BTW: You don’t need to modify the enigma.py library, you can just define the [[ substituted_expression_minimum ]] function in your own program.

          Like

    • Frits's avatar

      Frits 2:41 pm on 29 July 2020 Permalink | Reply

      @Jim: Thanks for the internal accumulate function

      from enigma import SubstitutedExpression, printf
      
      # the alphametic puzzle
      p = SubstitutedExpression(
        [
          # if one element in (X,Y,Z) is sum of 2 others then sum(X,Y,Z) = 2*max(X,Y,Z)
          # in this way we don't have to specify it is Z=X+Y, Y=X+Z or X=Y+Z 
          "TABLES + ABLEST + STABLE == 2 * max(TABLES, ABLEST, STABLE)",
          "not(is_duplicate(TABLES))",
          "not(is_duplicate(ABLEST))",
          "not(is_duplicate(STABLE))"
        ],
        answer="(TABLES + ABLEST + STABLE)/2, ABLEST, STABLE, TABLES",
        accumulate=min,
        verbose=0)      
          
      # solve the puzzle
      r = p.run()
      
      # Print answer
      lst = ["ABLEST", "STABLE", "TABLES"]
      cnt = 0
      for ans in r.accumulate:
          if cnt == 0: hghnum = ans
          else:  
            if ans == hghnum: printf("{lst[cnt-1]} is the sum with value {ans}")
          cnt += 1 
      

      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