Updates from Jim Randell Toggle Comment Threads | Keyboard Shortcuts

  • Unknown's avatar

    Jim Randell 8:43 pm on 15 August 2019 Permalink | Reply
    Tags:   

    Teaser 2969: Slide rules 

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

    Using her ordinary 15cm ruler and Zak’s left-handed version (numbers 1 to 15 reading right to left) Kaz could display various fractions. For instance, putting 5 on one ruler above 1 on the other ruler, the following set of fractions would be displayed: 5/1, 4/2, 3/3, 2/4 and 1/5. Zak listed the fifteen sets starting from “1 above 1” up to “15 above 1”.

    Kaz chose some fractions with values less than one from Zak’s sets (using just the digits 1 to 9, each once only in her selection). Of these, two were in simplest form, one of which had consecutive numerator and denominator. Zak correctly totalled Kaz’s selection, giving the answer as a fraction in simplest form. Curiously, the answer’s numerator and denominator were both palindromic.

    Give Zak’s answer.

    [teaser2969]

     
    • Jim Randell's avatar

      Jim Randell 10:45 pm on 15 August 2019 Permalink | Reply

      This Python program collects possible fractions, and then uses a recursive function to select viable sets that Kaz could have chosen. These sets are then examined to find candidates where the sum is expressed as a fraction consisting of two palindromes.

      Run: [ @repl.it ]

      from fractions import Fraction as F
      from enigma import (irange, nsplit, gcd, join, printf)
      
      # collect fractions less than 1
      fs = list()
      
      # consider overlaps from 1 to 15
      for n in irange(1, 15):
        for (a, b) in zip(irange(n, 1, step=-1), irange(1, n, step=1)):
          if a < b:
            fs.append((a, b))
      
      # generate sets of fractions, using the digits in ds, and:
      # one of the fractions consists of consecutive numbers
      # two of the fractions are in lowest terms
      def choose(fs, ds=set(), ss=[]):
        # are we done?
        if not ds:
          # find fractions in their lowest terms
          rs = list((a, b) for (a, b) in ss if gcd(a, b) == 1)
          # there should be exactly 2 of them
          if len(rs) != 2: return
          # and exactly one of them must consist of consecutive numbers
          if sum(b == a + 1 for (a, b) in rs) != 1: return
          yield ss
        else:
          for (i, (a, b)) in enumerate(fs):
            d = nsplit(a) + nsplit(b)
            if len(set(d)) < len(d) or not ds.issuperset(d): continue
            yield from choose(fs[i + 1:], ds.difference(d), ss + [(a, b)])
      
      # check for palindromes
      def is_palindromic(n):
        ds = nsplit(n)
        return ds == ds[::-1]
      
      # choose the set of fractions
      for ss in choose(fs, set(irange(1, 9))):
        # calculate the sum of the fractions
        t = sum(F(a, b) for (a, b) in ss)
        if is_palindromic(t.numerator) and is_palindromic(t.denominator):
          printf("{ss} = {t}", ss=join((join((a, "/", b)) for (a, b) in ss), sep=" + "))
      

      Solution: Zak’s answer is 545/252.

      The fractions Kaz has chosen are:

      3/12 + 4/8 + 5/9 + 6/7 = 545/252

      There are 10 sets of fractions that Kaz could have chosen, but only one of these sets has a total consisting of palindromic numerator and denominator when expressed in lowest terms.

      3/5 + 7/8 + 6/9 + 4/12 = 99/40
      3/5 + 7/8 + 6/9 + 2/14 = 1919/840
      4/5 + 6/8 + 3/12 + 7/9 = 116/45
      3/6 + 5/9 + 7/8 + 4/12 = 163/72
      3/6 + 5/9 + 7/8 + 2/14 = 1045/504
      4/6 + 5/9 + 7/8 + 3/12 = 169/72
      5/6 + 4/8 + 3/12 + 7/9 = 85/36
      4/8 + 6/7 + 5/9 + 3/12 = 545/252 [*** SOLUTION ***]
      3/9 + 6/7 + 5/8 + 4/12 = 361/168
      3/9 + 6/7 + 5/8 + 2/14 = 47/24

      Like

  • Unknown's avatar

    Jim Randell 10:03 am on 15 August 2019 Permalink | Reply
    Tags: by: Ben Tarlow   

    Brainteaser 1657: Not a black and white case 

    From The Sunday Times, 12th June 1994 [link]

    Marvo has been up to his tricks again. He shuffled a normal pack of 52 cards and then looked at each one in turn without letting Alice see them. In each case she had to predict whether the card was red or black and Marvo gave no indication of whether Alice’s guesses were right or wrong. But after 51 guesses Alice had guessed “black” 26 times and “red” 25 times and Marvo announced that Alice had exactly 10 predictions wrong so far.

    (1) Which colour (if either) is more likely for Alice’s last card?

    Marvo repeated the game with Bob. After 51 guesses Bob too had guessed “black” 26 times and “red” 25 times and Marvo announced that Bob had exactly 11 predictions wrong so far.

    (2) Which colour (if either) is more likely for Bob’s last card?

    Marvo then repeated the game once more with Carol. After 51 guesses Carol too had guessed “black” 26 times and “red” 25 times and Marvo announced that Carol had got at least 10 predictions wrong so far.

    (3) Which colour (if either) is more likely for Carol’s last card?

    This puzzle is included in the book Brainteasers (2002). The puzzle text was, and the answers required were changed slightly, but the idea of the puzzle remains the same.

    [teaser1657]

     
    • Jim Randell's avatar

      Jim Randell 10:04 am on 15 August 2019 Permalink | Reply

      Alice has guessed “black” 26 times and “red” 25 times.

      If she has got n guesses wrong, then we can suppose b of the “black” guesses were wrong (i.e. they were actually red cards), and so (n − b) of the “red” guesses were wrong (i.e. they were actually black cards).

      So at this point the total number of actual black cards is:

      the (26 − b) cards that Alice correctly guessed as black; plus
      the (n − b) cards that were guessed as red, but were actually black.

      And similarly for red, giving:

      black = 26 + n − 2b
      red = 25 − n + 2b

      There can’t be more than 26 actual black cards, so:

      26 + n − 2b ≤ 26
      n ≤ 2b
      b ≥ n/2

      And there can’t be more than 26 actual red cards:

      25 − n + 2b ≤ 26
      2b ≤ n + 1
      b ≤ (n + 1)/2

      So:

      n/2 ≤ b ≤ (n + 1)/2

      Which fixes the value of b, depending on whether n is odd or even.

      In Alice’s case n = 10, so b = 5. Hence there have actually been 26 black cards and 25 red cards, so the remaining card has to be red.

      In Bob’s case n = 11, so b = 6. And there have actually been 25 black cards and 26 red cards, so the remaining card has to be black.

      And we see that if n is even then the remaining card must be red, and if it is odd the remaining card must be black.

      Solution: (1) Alice’s final card is certainly red. (2) Bob’s final card is certainly black.

      Carol has made at least 10 incorrect predictions. So she has made 10, 11, 12, …, 51, and depending on the exact number the remaining card is red, black, red, … black. There are 24 cases where the card must be red and 24 cases where the card must be black.

      We need to count the number of scenarios for each outcome.

      When n = 10 then b = 5 and there have been 26 black guesses (5 are guessed incorrectly) and 25 red guesses (5 are guessed incorrectly). So the number of ways of choosing the incorrect guesses are:

      C(26, 5) × C(25, 5)

      each one giving rise to the remaining card being red.

      When n = 11 and b = 6 we get:

      C(26, 6) × C(25, 5)

      each one giving rise to the remaining card being black.

      (I think if we are counting the total number of possible scenarios each of these numbers would be multiplied by an additional factor to account for the order of the cards and the guesses, but we don’t need to do that to compare the relative likelihood of red and black outcomes for the final card).

      This Python program counts up the number of possibilities. It runs in 85ms.

      Run: [ @repl.it ]

      from enigma import irange, C, fdiv, compare, printf
      
      r = b = 0
      for n in irange(10, 51):
        (k, p) = divmod(n, 2)
        if p == 0:
          r += C(26, k) * C(25, k)
        else:
          b += C(26, k + 1) * C(25, k)
      
      f = lambda x: fdiv(x, r + b)
      x = compare(r, b, ("black", "equal", "red"))
      printf("{x} [red = {r} ({fr:.4%}), black = {b} ({fb:.4%})]", fr=f(r), fb=f(b))
      

      Solution: (3) It is slightly more likely that Carol’s final card is red.

      The calculated figures give that Carol’s final card is red 50.0001% of the time and black 49.9999% of the time. So it is close.


      The puzzle as originally published in The Sunday Times asked for the outcome with the following numbers of wrong predictions: (a) exactly 10; (b) least 10; (c) at least 15.

      We have already covered (a) and (b), and for (c) the program can easily be modified to start counting from 15, rather than 10. The result is that it is slightly more likely that the card is black (50.02%) than red (49.98%).

      Liked by 1 person

  • Unknown's avatar

    Jim Randell 8:14 am on 13 August 2019 Permalink | Reply
    Tags:   

    Brain-Teaser 493: Absorbers 

    From The Sunday Times, 8th November 1970 [link]

    Three men from the Absorbers’ Association, three from Bacchante’s Bank and three from the Convivial Corporation, took a drink together.

    From each concern, one man drank sherry, one gin and one whisky. Of the three choosing sherry, one chose medium, one dry and one extra dry. With gin, one took tonic, one lemon and one vermouth. With whisky, one plain water, one soda water and one dry ginger.

    The dry sherry drinker did not belong to the same concern as the plain water man, nor to the same concern as the vermouth man. The drinkers of dry ginger, lemon and medium sherry were from three different concerns.

    Either the tonic man or plain water man (but not both) was from the Absorbers’ Association. The selectors of soda and vermouth were not colleagues and neither represented Bacchante’s Bank.

    The tonic man belonged either to the same concern as the dry sherry drinker or to the same concern as the medium sherry man.

    Which type of sherry was chosen by a Convivial Corporation man and what did [the] other men from that same concern take with gin and take with whisky?

    This puzzle is included in the book Sunday Times Brain Teasers (1974).

    [teaser493]

     
    • Jim Randell's avatar

      Jim Randell 8:14 am on 13 August 2019 Permalink | Reply

      The solution space is quite small (there are (3!)³ = 216 possible arrangements), so we can just examine them all and eliminate those which don’t satisfy the conditions.

      This Python program runs in 83ms.

      Run: [ @repl.it ]

      from itertools import product
      from enigma import (subsets, printf)
      
      for ((M, D, X), (T, L, V), (W, S, G)) in product(subsets("ABC", size=len, select='P'), repeat=3):
      
        # "The dry sherry drinker did not belong to the same concern as the
        # plain water man, nor to the same concern as the vermouth man"
        if D == W or D == V: continue
      
        # "The drinkers of dry ginger, lemon and medium sherry were from
        # three different concerns"
        if len(set([G, L, M])) != 3: continue
      
        # "Either the tonic man or plain water man (but not both) was from
        # the Absorbers' Association"
        if not ((T == 'A') ^ (W == 'A')): continue
      
        # "The selectors of soda and vermouth were not colleagues and
        # neither represented Bacchante's Bank"
        if S == V or S == 'B' or V == 'B': continue
      
        # "The tonic man belonged either to the same concern as the dry
        # sherry drinker or to the same concern as the medium sherry man"
        if not (T == D or T == M): continue
        
        printf("Sherry: M={M} D={D} X={X}; Gin: T={T} L={L} V={V}; Whisky: W={W} S={S} G={G}")
      

      Solution: The CC men drank extra dry sherry, gin and lemon, whisky and soda.

      The other drinks are:

      AA = medium sherry, gin and vermouth, whisky and water
      BB = dry sherry, gin and tonic, whisky and ginger

      Like

  • Unknown's avatar

    Jim Randell 11:28 am on 12 August 2019 Permalink | Reply
    Tags:   

    Teaser 2885: Croquet mallet 

    From The Sunday Times, 7th January 2018 [link] [link]

    My croquet mallet is less than a metre high and consists of a cylindrical shaft attached to a heavier cuboid head, both of uniform density. Knowing the total weight of the mallet, I wanted to work out the weight of the shaft. I found the point of balance along the shaft and measured the distances from there to each end of the shaft, the smaller of which was less than the height of the head. Each of these three distances was a whole prime number of cm, and taking the three distances together with the height of the mallet, no digit was repeated. I worked out that the weight of the head was a single digit multiple of the weight of the shaft.

    What was the height of my mallet?

    [teaser2885]

     
    • Jim Randell's avatar

      Jim Randell 11:29 am on 12 August 2019 Permalink | Reply

      When the mallet is balanced we have:

      where a, b, c are all primes and b < c < a.

      The total length of the mallet t = a + b + c < 100.

      And between them, the numbers a, b, c, t have no repeated digits.

      The shaft has a weight w acting at a distance of (a + b)/2 − b = (a − b)/2 from the balance point.

      The head has a weight kw acting at a distance of b + c/2.

      So for these to balance we have:

      w(a − b)/2 = kw(b + c/2)
      (a − b) = k(2b + c)
      k = (a − b) / (2b + c)

      where k is a single digit integer.

      This Python program finds the solution in 78ms.

      Run: [ @replit ]

      from enigma import (primes, subsets, is_duplicate, div, printf)
      
      for (b, c, a) in subsets(primes.between(1, 99), size=3, select='C'):
        t = a + b + c
        if not (t < 100): continue
        if is_duplicate(a, b, c, t): continue
      
        k = div(a - b, 2 * b + c)
        if k is None or k < 2 or k > 9: continue
      
        printf("t={t} [a={a} b={b} c={c}, k={k}]")
      

      Solution: The mallet is 90cm high.

      The values are: t=90, a=83 b=2 c=5, k=9.

      Like

  • Unknown's avatar

    Jim Randell 8:08 am on 11 August 2019 Permalink | Reply
    Tags:   

    Brainteaser 1649: Ages and ages! 

    From The Sunday Times, 17th April 1994 [link]

    Today is the birthday of both Mary and Nelly, so it is a good time to have a conundrum about their ages.

    When Mary was one third of the age she is today, Nelly was half the age that Mary was when Nelly was the age that Mary was when Nelly was the age that Mary was when Nelly was a quarter of the age she is today.

    If neither of them is yet eligible for an old-age pension, how old are they both today?

    This puzzle is included in the book Brainteasers (2002).

    [teaser1649]

     
    • Jim Randell's avatar

      Jim Randell 8:09 am on 11 August 2019 Permalink | Reply

      A lot of the puzzle text is concerned with the difference between the ages, so if we suppose N’s current age is n and M’s current age is (n + d), and then look at the expression:

      When Mary was one third of the age she is today, Nelly was half the age that Mary was when Nelly was the age that Mary was when Nelly was the age that Mary was when Nelly was a quarter of the age she is today

      We can successively refine it:

      → When Mary was (1/3)n + (1/3)d, Nelly was half the age that Mary was when Nelly was the age that Mary was when Nelly was the age that Mary was when Nelly was (1/4)n
      → When Mary was (1/3)n + (1/3)d, Nelly was half the age that Mary was when Nelly was the age that Mary was when Nelly was (1/4)n + d
      → When Mary was (1/3)n + (1/3)d, Nelly was half the age that Mary was when Nelly was (1/4)n + 2d
      → When Mary was (1/3)n + (1/3)d, Nelly was half (1/4)n + 3d
      → When Mary was (1/3)n + (1/3)d, Nelly was (1/8)n + (3/2)d
      → (1/3)n + (1/3)d = (1/8)n + (3/2)d + d
      → (5/24)n = (13/6)d
      → 5n = 52d

      So d must be a multiple of 5, and n must be a multiple of 52.

      For (n + d) < 65 we must have n = 52, d = 5.

      Solution: Nelly is 52. Mary is 57.

      Liked by 1 person

  • Unknown's avatar

    Jim Randell 8:13 pm on 9 August 2019 Permalink | Reply
    Tags:   

    Teaser 2968: Gardening division 

    From The Sunday Times, 11th August 2019 [link] [link]

    George and Martha’s garden is a perfect square of length (whole number of metres) a two-digit number AB. The area is a three-digit number CDE. In the middle, they have planted a square flowerbed of a length which is a single-digit number F and area a two-digit number GH.

    They have called in a gardener, who works for a single-digit I hours. He works for a whole number of minutes on the flowerbed and the remainder on the surrounding lawn. Each square metre of the flowerbed requires N (a single digit) times the time spent on each square metre of the surrounding lawn. I have mentioned nine letters, A-I inclusive, and each stands for a different positive digit.

    How many minutes does the gardener work on the lawn?

    [teaser2968]

     
    • Jim Randell's avatar

      Jim Randell 8:29 pm on 9 August 2019 Permalink | Reply

      We can express the puzzle as a set of alphametic constraints and then use the general alphametic solver [[ SubstitutedExpression() ]] from the enigma.py library to find the solution.

      The following run file executes in 140ms.

      #! python -m enigma -rr
      
      SubstitutedExpression
      
      --distinct="ABCDEFGHI"
      --digits="1-9"
      
      "AB**2 = CDE"
      "F**2 = GH"
      
      "div(CDE - GH + N * GH, I * 60)"
      
      --answer="div((CDE - GH) * I * 60, CDE - GH + N * GH)"
      

      Solution: The gardener worked on the lawn for 99 minutes.

      The garden is a square of side 24m, giving a total area of 576m².

      The flowerbed has sides of 9m, so has an area of 81m², leaving an area of 495m² of lawn.

      The gardener works on the flowerbed for 81 minutes, at a rate of 1 minute per square metre of flowerbed. He then works on the lawn 5 times faster, at a rate of 1 minute per 5 square metres of lawn, so the 495m² of lawn takes 99 minutes. The total time is therefore 180 minutes, or 3 hours.

      Like

  • Unknown's avatar

    Jim Randell 10:09 am on 9 August 2019 Permalink | Reply
    Tags:   

    Teaser 2888: Two sums 

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

    Digits have been systematically replaced by letters to give:

    ONE + ONE = TWO
    ONE + FOUR = FIVE

    No number consists of a consecutive set of digits.

    What number is represented by FIFTEEN?

    [teaser2888]

     
    • Jim Randell's avatar

      Jim Randell 10:10 am on 9 August 2019 Permalink | Reply

      We can easily use the [[ SubstitutedExpression() ]] solver from the enigma.py library to solve the alphametic sums, and we can use [[ --code ]] parameters to provide the additional check that none of the numbers consist of a set of consecutive digits. The numbers are all composed of different digits, so that makes things a bit simpler.

      This run file executes in 139ms.

      Run: [ @repl.it ]

      #! python -m enigma -rr
      
      SubstitutedExpression
      
      --answer="FIFTEEN"
      
      "ONE + ONE = TWO"
      "ONE + FOUR = FIVE"
      
      # check the words in each sum do not consist of consecutive digits
      "check(ONE) and check(TWO)"
      "check(FOUR) and check(FIVE)"
      
      # function to check a sorted sequence of distinct numbers is increasing consecutive 
      --code="is_consecutive = lambda s: s[-1] - s[0] == len(s) - 1"
      
      # function to check a word does not consist of consecutive digits
      --code="check = lambda w: not is_consecutive(sorted(nsplit(w)))"
      

      Solution: FIFTEEN = 9594663.

      We have:

      ONE = 236, TWO = 472, FOUR = 9280, FIVE = 9516

      There is one other solution to the alphametic sums that is eliminated because FOUR is composed from a set of (numerically) consecutive digits:

      ONE = 286, TWO = 572, FOUR = 3210, FIVE = 3496

      So we could just generate both solutions to the alphametic sums, and remove the non-viable solution by inspection.

      Like

    • GeoffR's avatar

      GeoffR 3:05 pm on 11 August 2019 Permalink | Reply

      % A Solution in MiniZinc
      include "globals.mzn";
       
      var 1..9: O; var 0..9: N; var 1..9: F; var 0..9: R;
      var 0..9: E; var 1..9: T; var 0..9: W; var 0..9: I; 
      var 0..9: V; var 0..9: U;   
      
      constraint all_different([U, O, N, E, F, R, T, W, I, V]); 
      
      % check ONE for non-consecutive digits
      var set of int : s1 = {O,N,E};
      constraint max ([O,N,E]) - min([O,N,E]) != card(s1) - 1;
      var 100..999: ONE = 100*O + 10*N + E; 
      
      % check TWO for non-consecutive digits
      var set of int : s2 = {T,W,O};
      constraint max ([T,W,O]) - min([T,W,O]) != card(s2) - 1;
      var 100..999: TWO = 100*T + 10*W + O;
      
      % check FOUR for non-consecutive digits
      var set of int : s3 = {F,O,U,R};
      constraint max ([F,O,U,R]) - min([F,O,U,R]) != card(s3) - 1;
      var 1000..9999: FOUR = 1000*F + 100*O + 10*U + R;
      
      % check FIVE for non-consecutive digits
      var set of int : s4 = {F,I,V,E};
      constraint max ([F,I,V,E]) - min([F,I,V,E]) != card(s4) - 1;
      var 1000..9999: FIVE = 1000*F + 100*I + 10*V + E;
      
      constraint ONE + ONE == TWO;
      constraint ONE + FOUR == FIVE;
      
      solve  satisfy;
      
      output [ "ONE = " ++  show(ONE) ] ++ [ ", TWO = " ++  show(TWO) ]  
      ++ [ ", FOUR = " ++  show(FOUR) ] ++ [ ", FIVE = " ++  show(FIVE) ]
      ++ [ "\nFIFTEEEN = " ++ show(F),show(I),show(F),show(T),show(E),show(E),show(N)];   
      
      % ONE = 236, TWO = 472, FOUR = 9280, FIVE = 9516
      % FIFTEEEN = 9594663
      % time elapsed: 0.02 s
      % ----------
      % ==========
      % Finished in 231msec
      
      

      Like

  • Unknown's avatar

    Jim Randell 2:25 pm on 8 August 2019 Permalink | Reply
    Tags:   

    Brain-Teaser 492: Light on the matches 

    From The Sunday Times, 1st November 1970 [link]

    Six football sides, A, B, C, D, E and F are all to play each other once, with 2 points for a win, 1 point for a draw.

    After some of the matches have been played a battered piece of paper is discovered on which has obviously been written particulars of the results so far.

    All that can be read is shown below:

    What were the details (opponents and scores) of E’s matches? (Example: EvP = 4-3, EvQ = 0-2, etc. E’s score first).

    This puzzle is included in the book Sunday Times Brain Teasers (1974).

    [teaser492]

     
    • Jim Randell's avatar

      Jim Randell 2:26 pm on 8 August 2019 Permalink | Reply

      F has 7 points and has played 5 games, but they only have 2 goals for, so cannot have won more than 2 games. Their 7 points must be made by 2w + 3d, which must be 1-0, 1-0, 0-0, 0-0, 0-0, so their goals against is 0. Hence the total number of goals scored is 25, and between them C and E have scored 17 goals.

      This Python program chooses values for C and E’s “goals for” values and then uses the [[ Football() ]] helper class from the enigma.py library to determine the outcomes and scorelines of each match.

      It runs in 550ms.

      Run: [ @repl.it ]

      from enigma import Football, digit_map, irange, int2base, sprintf
      
      # scoring system
      football = Football(points=dict(w=2, d=1))
      
      # labels for the teams
      (A, B, C, D, E, F) = (0, 1, 2, 3, 4, 5)
      
      # digits stand for themselves, and could go up to 17
      M = 17
      d = digit_map(0, M)
      
      # columns of the table (without goals against)
      (table, gf, ga) = (dict(played="24?3?5", w="1????2", l="??1??0", d='?????3', points="?373?7"), "41{C}1{E}2", "247570")
      
      # find possible match outcomes from the table
      for (ms, _) in football.substituted_table(table, teams=[F, A, B, C, D, E], d=d):
      
        # consider possible goals for C and E
        for (fC, fE) in zip(irange(0, M), irange(M, 0, step=-1)):
          gf1 = sprintf(gf, C=int2base(fC, M + 1), E=int2base(fE, M + 1))
      
          # find possible scorelines
          for ss in football.substituted_table_goals(gf1, ga, ms, d=d):
      
            # output solution
            football.output_matches(ms, ss, teams="ABCDEF")
      

      Solution: The outcomes of E’s matches are: E vs A = not yet played; E vs B = 0-1; E vs C = 3-5; E vs D = not yet played; E vs F = 0-1.

      There is only one scenario that works, which is when C has 14 goals for, and E has 3.

      The full scores are:

      A vs B = —
      A vs C = 4-1
      A vs D = —
      A vs E = —
      A vs F = 0-1
      B vs C = 0-3
      B vs D = 0-1
      B vs E = 1-0
      B vs F = 0-0
      C vs D = 5-0
      C vs E = 5-3
      C vs F = 0-0
      D vs E = —
      D vs F = 0-0
      E vs F = 0-1

      Like

      • John Crabtree's avatar

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

        This teaser has a logical solution which leads directly to the answer, with no other paths.

        Like

        • John Crabtree's avatar

          John Crabtree 2:36 pm on 13 August 2019 Permalink | Reply

          F has 7 points, but only scores 2 goals, and so F’s line reads 5 2 0 3 2 0 7
          C has 7 points, but loses a game, and so C’s line reads 5 3 1 1 ? 7 7
          As A plays 2 games, E must play 3 games, not 5.
          The total of the Played column = 22 = the total of the Points column.
          A has a minimum of 2 points and so the minimum Points total = 22
          And so A has 2 points and so A’s line reads 2 1 1 0 4 2 2
          And so E has 0 points and so B’s line reads 3 0 3 0 ? 7 0
          B can only draw one game not three, and so B’s line reads 4 1 2 1 1 4 3
          D can only draw one game,not three, and so D’s line reads 3 1 1 1 1 5 3

          By inspection A v F 0-1, B v F 0-0, C v F 0-0, D v F 0-0, E v F 0-1.
          Then A beats C. C beats B, D and E. B loses to D and beats E.
          From A’s GF and GA, A v C 4-1.
          From D”s GF = 1, , B v D 0-1
          From D’s GF and GA, C v D 5-0
          From B’s GF = 1, B v E 1-0
          From B’s GF and GA, C v B 3-0
          From C’s GA and E’s GA, C v E 5 -3

          And so E played 3 matches: E v B 0-1, E v C 3-5 and E v F 0-1

          Like

  • Unknown's avatar

    Jim Randell 9:14 am on 7 August 2019 Permalink | Reply
    Tags: ,   

    Teaser 2894: Time duality 

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

    After a good breakfast, Seb decided on 40 winks. He noted the time on his digital clock as he dozed off. When he woke up a little later that day, not fully alert, he saw the display reflected in a mirror and was amazed by how long he seemed to have slept. This was in fact 10 times the length of his nap. Next day, a similar thing happened: he fell asleep at the same time and slept a little less, but when he woke, the mirror led him to believe he had slept for 20 times as long as he had. (All times were whole numbers of minutes after midnight).

    At what time did he fall asleep?

    [teaser2894]

     
    • Jim Randell's avatar

      Jim Randell 9:16 am on 7 August 2019 Permalink | Reply

      We can find multiple solutions to this puzzle, depending on how the clock works.

      The program examines the following three scenarios for a digital clock consisting of standard 7-segment digits, where the digits 0, 1 and 8 appear the same when mirrored, and the digits 2 and 5 appear as each other when mirrored.

      Scenario 1: 24 hour clock, always displays 4 digits, reads from 00:00 – 23:59.

      Scenario 2: 24 hour clock, leading zeros are suppressed on the hours, and no clear hour/minute separator, reads from 0:00 – 23:59.

      Scenario 3: 12 hour clock, leading zeros are suppressed on the hours, and no clear hour/minute separator, reads from 12:00 – 11:59.

      It runs in 125ms.

      Run: [ @replit ]

      from enigma import (defaultdict, cproduct, arg, irange, nsplit, div, sprintf, printf)
      
      # digit reflections
      X = None
      #           0  1  2  3  4  5  6  7  8  9
      reflect = [ 0, 1, 5, X, X, 2, X, X, 8, X ] 
      
      # format time t as hh:mm
      def fmt(t, hours=24):
        k = 0
        while t < 0:
          k -= 1
          t += hours * 60
        while t > hours * 60:
          k += 1
          t -= hours * 60
        (h, m) = divmod(t, 60)
        return sprintf("{h:02d}:{m:02d} [{k:+d}]")
      
      # solve using digits function <digits>
      def solve(digits, hours=24):
        # record results by start time (in minutes), 10x or 20x
        rs = defaultdict(lambda: defaultdict(list))
      
        # map display digits to possible times
        m = defaultdict(list)
        for t in irange(0, 24 * 60 - 1):
          m[digits(t)].append(t)
      
        # find sequences that have a reverse sequence
        for (s, t1s) in m.items():
          r = tuple(reflect[d] for d in s[::-1])    
          if None in r or r == s: continue
          if r in m:
            t2s = m[r]
      
            for (t1, t2) in cproduct([t1s, t2s]):
              if t1 == t2: continue
              while t2 < t1: t2 += 24 * 60
              d = t2 - t1
      
              # find differences that give 9x or 19y
              x = div(d, 9)
              if x:
                t0 = t1 - x
                printf("[{t1} | {t2} = {d} min (9x {x}m), t0={t0}]", t1=fmt(t1, hours), t2=fmt(t2, hours), t0=fmt(t0, hours))
                rs[t0][10].append((t1, t2))
              y = div(d, 19)
              if y:
                t0 = t1 - y
                printf("[{t1} | {t2} = {d} min (19x {y}m), t0={t0}]", t1=fmt(t1, hours), t2=fmt(t2, hours), t0=fmt(t0, hours))
                rs[t0][20].append((t1, t2))
      
        # output solutions
        for (t0, d) in rs.items():
          for ((t1a, t2a), (t1b, t2b)) in cproduct([d[10], d[20]]):
            if t1b < t1a:
              (ft0, ft1a, ft2a, ft1b, ft2b) = (fmt(x, hours) for x in (t0, t1a, t2a, t1b, t2b))
              printf("10x = {ft0} - {ft1a} | {ft2a} / 20x = {ft0} - {ft1b} | {ft2b}")
      
      # digits displayed for time t in the different scenarios:
      
      # [1] four digits, 24 hours: 00:00 - 23:59
      def digits1(t):
        (h, m) = divmod(t, 60)
        return nsplit(h % 24, 2) + nsplit(m, 2)
      
      # [2] three or four digits, 24 hours: 0:00 - 23:59, no clear separator
      def digits2(t):
        (h, m) = divmod(t, 60)
        return nsplit(h % 24) + nsplit(m, 2)
      
      # [3] three or four digits, 12 hours: 0:00 - 11:59, no clear separator
      def digits3(t):
        (h, m) = divmod(t, 60)
        return nsplit(h % 12 or 12) + nsplit(m, 2)
      
      
      types = {
        '1': [ digits1, "[type 1] 00:00 - 23:59", 24 ],
        '2': [ digits2, "[type 2] 0:00 - 23:59", 24 ],
        '3': [ digits3, "[type 3] 12:00 - 11:59", 12 ],
      }
      
      cmd = arg("123", 0)
      
      for k in sorted(types.keys()):
        if k not in cmd: continue
        (fn, t, h) = types[k]
        printf("{t}")
        solve(fn, hours=h)
        printf()
      

      We find the following solutions:

      Scenario 1: 24 hour clock, always displays 4 digits, reads from 00:00 – 23:59.

      This is probably the most reasonable expectation of the clock’s behaviour without further explanation.

      Day 1: The nap starts at 09:41 and finishes after 74m at 10:55. The mirrored display reads 22:01 corresponding to a nap of 740m (= 10×74m).
      Day 2: The nap starts at 09:41 and finishes after 34m at 10:15. The mirrored display reads 21:01 corresponding to a nap of 680m (= 20×34m).

      Day 1: The nap starts at 09:21 and finishes after 119m at 11:20. The mirrored display reads 05:11 corresponding to a nap of 1190m (= 10×119m).
      Day 2: The nap starts at 09:21 and finishes after 59m at 10:20. The mirrored display reads 05:01 corresponding to a nap of 1180m (= 20×59m).

      But in both these solutions the second nap is less than half the length of the first nap, so it is a bit odd to say he slept “a little less” than the previous day.

      Scenario 2: 24 hour clock, leading zeros are suppressed on the hours, and no clear hour/minute separator, reads from 0:00 – 23:59.

      The 09:41 nap works the same, but the 09:21 nap does not as 10:20 when mirrored does not correspond to a displayable time.

      Day 1: The nap starts at 09:41 and finishes after 74m at 10:55. The mirrored display reads 22:01 corresponding to a nap of 740m (= 10×74m).
      Day 2: The nap starts at 09:41 and finishes after 34m at 10:15. The mirrored display reads 21:01 corresponding to a nap of 680m (= 20×34m).

      This scenario has a unique solution, but the problem remains that the second nap is less than half the length of the first nap.

      Scenario 3: 12 hour clock, leading zeros are suppressed on the hours, and no clear hour/minute separator, reads from 12:00 – 11:59.

      Day 1: The nap starts at 07:18 and finishes after 64m at 08:22. The mirrored display reads “558” corresponding to 17:58 and a nap of 640m (= 10×64m).
      Day 2: The nap starts at 07:18 and finished after 57m at 08:15. The mirrored display reads “218” corresponding to 02:18 and a nap of 1140m (= 20×57m).

      And as it is a 12 hour clock this all works shifted on 12 hours, although perhaps 7:18pm is a little late to be having breakfast.

      The problem here is that on day two when seeing the clock reading 2:18 Seb would probably think he had slept for 7 hours, not for 19 hours. However this is the best solution for sleeping “a little less” on the second day, and the puzzle text does say Seb was not fully alert when he read the clock.


      Out of all these scenarios the one that best fits the puzzle text is Scenario 3:

      On the first day, Seb has an early breakfast, and starts his snooze at 7:18am, and wakes up at 8:22am, having slept for 64m, but reads the time as 5:58, and believes he has slept until 5:58pm, which is 640m.

      On the second day, Seb again starts his snooze at 7:18am, and wakes at 8:15am, having slept for 57m (which is only 7m shorter than the previous day). He reads the time as 2:18, and believes he has slept until 2:18am the following day, which is 1140m.

      This gives us a solution to the puzzle that Seb fell asleep on both days at 7:18am.

      It is possible that the phrase “all times were whole numbers of minutes after midnight”, is meant to indicate that all the times mentioned (including the false mirrored times) are all supposed to fall within the same 24 hour day, in which case the 9:41am solution in Scenario 1 or Scenario 2 remain, and give a unique solution of 9:41am. This may be the setters intended solution.

      But as there are multiple possible answers I have marked this puzzle as “flawed“.


      The published solution is: “09:41am”.

      Liked by 1 person

  • Unknown's avatar

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

    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

  • Unknown's avatar

    Jim Randell 8:42 am on 5 August 2019 Permalink | Reply
    Tags:   

    Teaser 2893: Win some, lose some 

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

    The six teams in our local league play each other once in the season. Last season no two teams tied on points.

    Above is part of the table from the end of that season, with the teams in alphabetical order.

    However, digits have been consistently replaced by letters.

    Find the value of the number of LEMONS.

    [teaser2893]

     
    • Jim Randell's avatar

      Jim Randell 8:43 am on 5 August 2019 Permalink | Reply

      When I first looked at this puzzle I assumed the scoring regime was “2 points for a win, 1 point to each side for a draw” (which is a common scenario in Enigma puzzles [ link ]), but that gave me two possible solutions (the values for L and N are interchangeable). But using “3 points for a win, 1 point to each side for a draw” give a unique solution, and is probably what the setter had in mind. (This was later confirmed).

      I derived a set of constraints from the table and then used the general alphametic solver [[ SubstitutedExpression() ]] from the enigma.py library to solve the puzzle.

      The following run file executes in 73ms. (Internal runtime of the generated program is 94µs).

      Run: [ @replit ]

      #! python3 -m enigma -rr
      
      SubstitutedExpression
      
      --answer="LEMONS"
      
      # each team has played 5 matches
      "W = 5"
      
      # won + lost + drawn = 5
      "O + N <= 5"
      "S + O + M = 5"
      "L + O <= 5"
      "S <= 5"
      
      # goals for >= won, goals against >= lost
      "E >= S"
      "S >= 5 - L - O"
      "T >= L"
      "O >= (E - S) // 3" "(E - S) % 3 = 0"
      
      # points (= 3 * won + drawn) are all different
      --code="pts = lambda w, d: 3 * w + d"
      "all_different(pts(O, 5 - O - N), pts(S, M), pts(5 - L - O, O), E)"
      

      Solution: LEMONS = 370124.

      We could provide additional constraints in the run file (e.g. assign W=5; and L, M, N, O, S are 0, 1, 2, 3, 4 (in some order)) but it doesn’t make much difference to the run time if we do:

      # [optional] w, l, d can only contain digits 0-5 (and W is 5)
      --assign="W,5"
      --invalid="6|7|8|9,LMNOS"
      

      If we change the definition of [[ pts() ]] to use the “2 points for a win …” scenario, and we find there is an additional solution of:

      LEMONS = 270134

      Like

  • Unknown's avatar

    Jim Randell 9:10 am on 4 August 2019 Permalink | Reply
    Tags: by: Angela Humphreys,   

    Brain-Teaser 491: [Family names] 

    From The Sunday Times, 25th October 1970 [link]

    Each of the five families in Admirals Walk comprised three boys; one of the boys in each family had the same christian name as the surname of one of his neighbours, and no boy had the same christian and surname.

    The three christian names of Mr. Arnold’s three sons all had the same initial as the surname of Lawrence, who lived opposite to Benjamin Thomas.

    Mr. Gordon’s oldest son had a christian name with the same initial as Clement’s surname. Clement’s father played chess with Jasper Lawrence’s father.

    Mr. Oliver was Arnold’s father’s business partner. Godfrey had measles. Mr. Oliver’s oldest son had the same christian name as Crispin’s surname, and also the same initial to his christian name as Arnold’s surname. Arnold lived next door to the man whose son Oswald played truant from school with his cousin Hector Lawrence, until Oswald’s brother Walter, a school prefect, caught them.

    Gilbert and Oscar had red hair.

    Oliver was in Borstal. What was his surname?

    When originally published the condition relating to Mr. Oliver’s sons was given as:

    Mr. Oliver’s oldest son had the same christian name as Crispin’s surname, and Mr. Oliver’s youngest son had the same initial to his christian name as Arnold’s surname.

    However a correction was published with Brain-Teaser 493 stating:

    It is regretted that in para. 3, line 7, “youngest” should have read “eldest”. However, as the correct initials of these boys can be proved independently and most solvers gave the correct answer, this answer will stand.”

    I have made the correction in the puzzle text above, although instead of just changing “youngest” to “eldest”, as we are already talking about Mr. Oliver’s oldest son, I used “and also”.

    This puzzle was originally published with no title.

    [teaser491]

     
    • Jim Randell's avatar

      Jim Randell 9:11 am on 4 August 2019 Permalink | Reply

      There are 15 first names mentioned, so each boy must have a different first name.

      This Python 3 program starts by filling out the full names we are given. Then it looks for three first names with the same initial for the Arnold family (which also gives us Lawrence’s surname). It then allocates the remaining names, and checks the remaining conditions.

      It runs in 271ms.

      Run: [ @repl.it ]

      from collections import defaultdict
      from enigma import subsets, update, diff, multiset, Accumulator, join, printf
      
      # names we know (map: firstname -> lastname)
      names = { "Benjamin": "Thomas", "Hector": "Lawrence", "Jasper": "Lawrence" }
      
      # the surnames are all distinct by initial
      lastnames = dict((x[0], x) for x in ("Arnold", "Gordon", "Lawrence", "Oliver", "Thomas"))
      
      # the remaining first names
      firstnames = ["Clement", "Crispin", "Gilbert", "Godfrey", "Oscar", "Oswald", "Walter" ]
      firstnames.extend(lastnames.values())
      
      # group firstnames by initial
      initial = defaultdict(list)
      for f in firstnames:
        initial[f[0]].append(f)
      
      # complete the families, ensuring no-one has the same first/last name
      def complete(ns, fs):
        # are we done?
        if not fs:
          yield ns
        else:
          # find an incomplete family to fill out
          s = multiset(ns.values())
          r = Accumulator(fn=min)
          for v in lastnames.values():
            n = 3 - s.get(v, 0)
            if n > 0: r.accumulate_data(n, v)
          (n, v) = (r.value, r.data)
          # choose names
          for ts in subsets(diff(fs, [v]), size=n):
            yield from complete(update(ns, ts, [v] * n), diff(fs, ts))
      
      # collect results
      r = multiset()
      
      # the Arnold children share the same first initial
      for (k, vs) in initial.items():
        if k == 'L': continue
        for fs in subsets(vs, size=3):
          if "Arnold" in fs: continue
          ns1 = update(names, fs, ["Arnold"] * 3)
      
          # Lawrence has one of these names as a surname
          ns1["Lawrence"] = lastnames[k]
      
          # complete the allocations
          for ns in complete(ns1, diff(firstnames, ns1.keys())):
      
            # "Clement's father played chess with Jasper Lawrence's father"
            # so Clement's surname is not Lawrence
            if ns["Clement"] == "Lawrence": continue
      
            # "Mr. Oliver was Arnold's father's business partner"
            # so Arnold's surname is not Oliver
            if ns["Arnold"] == "Oliver": continue
      
            # "Oswald played truant from school with his cousin Hector Lawrence"
            # so Oswald's surname is not Lawrence
            if ns["Oswald"] == "Lawrence": continue
      
            # "Arnold lived next door to ... Oswald"
            # so Arnold and Oswald have different surnames
            if ns["Arnold"] == ns["Oswald"]: continue
      
            # "... Oswald's brother Walter ..."
            # so Oswald and Walter have the same surname
            if ns["Oswald"] != ns["Walter"]: continue
      
            # "Mr. Oliver's oldest son had the same christian name as Crispin's surname ..."
            oliver_maj = ns["Crispin"]
            if ns[oliver_maj] != "Oliver": continue
      
            # "...and the same initial to his christian name as Arnold's surname"
            if oliver_maj[0] != ns["Arnold"][0]: continue
      
            # "Mr. Gordon's oldest son had a christian name with the same initial as Clement's surname"
            gordon_maj = list(k for (k, v) in ns.items() if v == "Gordon" and k[0] == ns["Clement"][0])
            if not gordon_maj: continue
      
            # each family has a child whose name is the surname of one of the other families
            ss = sorted(lastnames.values())
            fss = list()
            for v in ss:
              fss.append(set(x for (x, s) in ns.items() if s == v))
            if not all(fs.intersection(ss) for fs in fss): continue
      
            # output families
            fmt = lambda s: join(sorted(s), sep=", ")
            for (s, fs) in zip(ss, fss):
              printf("{s}: {fs}", fs=fmt(fs))
            printf("Oliver maj = {oliver_maj}; Gordon maj = {gordon_maj}", gordon_maj=fmt(gordon_maj))
            printf()
      
            # record the answer (Oliver's surname)
            r.add(ns["Oliver"])
      
      
      # output the answer
      for (s, n) in r.most_common():
        printf("Oliver {s} [{n} solutions]")
      

      Solution: Oliver’s surname is Lawrence.

      The families are:

      Arnold: Gilbert, Godfrey, Gordon
      Gordon: Lawrence, Oswald, Walter
      Lawrence: Hector, Jasper, Oliver
      Oliver: Clement, Oscar, Thomas
      Thomas: Arnold, Benjamin, Crispin

      Oswald Gordon and Oliver Thomas are the eldest sons in their respective families.

      The originally published puzzle said that “Mr. Oliver’s youngest son had the same initial to his christian name as Arnold’s surname”, which cannot be satisfied with the rest of the conditions. The youngest of the Oliver children must be Clement or Oscar, and Arnold’s surname is Lawrence or Thomas.

      With the change of the puzzle text to refer to the oldest son (who is Thomas Oliver), he shares the same initial (and indeed the same name) as Arnold, as Arnold and Crispin are brothers (both Thomases).

      Like

  • Unknown's avatar

    Jim Randell 5:47 pm on 2 August 2019 Permalink | Reply
    Tags:   

    Teaser 2967: Odds and evens 

    From The Sunday Times, 4th August 2019 [link] [link]

    I have done a “long multiplication”, which is reproduced above. [If the multiplication was ABC × DE, then the third line shows the result of ABC × E and the fourth line shows the result of ABC × D]. However instead of writing the actual digits involved, I have written “O” where there is an odd digit and “E” where there is an even digit.

    What is the result of the multiplication?

    [teaser2967]

     
    • Jim Randell's avatar

      Jim Randell 5:59 pm on 2 August 2019 Permalink | Reply

      (See also: Enigma 1242, Enigma 1721, Enigma 109, Enigma 1503).

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

      The following run file executes in 140ms.

      Run: [ @repl.it ]

      #! python -m enigma -rr
      
      #     A B C
      #  *    D E
      #   -------
      #   J K L M (= ABC * E)
      #   N P Q   (= ABC * D)
      #   -------
      #   F G H I
      #   =======
      
      SubstitutedExpression
      
      --distinct=""
      --invalid="1|3|5|7|9,BCDEHIJLMNQ" # even digits
      --invalid="2|4|6|8,AFGKP" # odd digits
      --invalid="0,ADFGJKNP" # odd digits + leading even digits
      
      "ABC * DE = FGHI"
      
      "ABC * E = JKLM"
      "ABC * D = NPQ"
      

      Solution: The result of the multiplication sum is 9744.

      The full sum is:

      348 × 28 = 2784 + 696×10 = 9744

      Like

    • GeoffR's avatar

      GeoffR 8:45 am on 5 August 2019 Permalink | Reply

      % A Solution in MiniZinc
      include "globals.mzn";
      
      var 0..9:A; var 0..9:B; var 1..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:L; var 0..9:M; 
      var 0..9:N; var 0..9:P; var 0..9:Q;
      
      constraint A > 0 /\ D > 0 /\ J > 0 /\ N > 0 
      /\ K > 0/\ F > 0 /\ G > 0 /\ P > 0;
      
      % Allocate parity to the digits
      constraint A mod 2 == 1 /\ B mod 2 == 0 /\ C mod 2 == 0;
      constraint D mod 2 == 0 /\ E mod 2 == 0;
      constraint F mod 2 == 1 /\ G mod 2 == 1 /\ H mod 2 == 0
       /\ I mod 2 == 0;
      
      constraint J mod 2 == 0 /\ K mod 2 == 1 /\ L mod 2 == 0
       /\ M mod 2 == 0;
      constraint N mod 2 == 0 /\ P mod 2 == 1 /\ Q mod 2 == 0;
      
      % Components of multiplication sum
      var 100..999: ABC = 100*A + 10*B + C;
      var 10..99: DE = 10*D + E;
      var 1000..9999: JKLM = 1000*J + 100*K +10*L + M;
      var 1000..9999: NPQ = 1000*N + 100*P + 10*Q;
      var 1000..9999: FGHI = 1000*F + 100*G + 10*H + I;
      
      constraint ABC * DE == FGHI;
      constraint ABC * D * 10 == NPQ;
      constraint ABC * E == JKLM;
      
      solve satisfy;
      
      output ["Multiplication sum is " ++ show(ABC) ++ " * " 
      ++ show(DE) ++ " = " ++ show(JKLM) ++ " + " ++ show(NPQ)
       ++ " = " ++ show(FGHI) ];
      
      
      

      Like

  • Unknown's avatar

    Jim Randell 10:28 am on 2 August 2019 Permalink | Reply
    Tags:   

    Teaser 2892: Political pairings 

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

    A debating society arranged for a series of eight political debates between different Labour and Conservative politicians, each time with a different presenter.

    The presenters were:

    MARR, NEIL, NEWMAN, PARKINSON, PAXMAN, POPPLEWELL, ROBINSON and SNOW.

    The Labour politicians were:

    ABBOTT, ABRAHAMS, CHAKRABARTI, CORBYN, EAGLE, LEWIS, STARMER and WATSON.

    The Conservative politicians were:

    BRADLEY, GRAYLING, GREEN, HAMMOND, LEADSOM, LIDINGTON, MCLOUGHLIN and MUNDELL.

    For each debate there were 2 letters in common for any pairing from presenter, Labour politician and Conservative politician. The Labour politicians are listed alphabetically.

    What is the corresponding order for the Conservative politicians?

    [teaser2892]

     
    • Jim Randell's avatar

      Jim Randell 10:29 am on 2 August 2019 Permalink | Reply

      This puzzle can be solved using the [[ grouping ]] functionality in the enigma.py library (originally written to solve Teaser 2816, and a number of previous Teasers).

      This Python program runs in 87ms.

      Run: [ @repl.it ]

      from enigma import grouping
      
      # categories for this puzzle
      presenters = ( 'MARR', 'NEIL', 'NEWMAN', 'PARKINSON', 'PAXMAN', 'POPPLEWELL', 'ROBINSON', 'SNOW' )
      labs = ( 'ABBOTT', 'ABRAHAMS', 'CHAKRABARTI', 'CORBYN', 'EAGLE', 'LEWIS', 'STARMER', 'WATSON' )
      cons = ( 'BRADLEY', 'GRAYLING', 'GREEN', 'HAMMOND', 'LEADSOM', 'LIDINGTON', 'MCLOUGHLIN', 'MUNDELL' )
      
      # match the categories into groups such that each pair in each group shares exactly 2 letters
      grouping.solve([presenters, labs, cons], grouping.share_letters(2))
      

      Solution: LEADSOM, GRAYLING, HAMMOND, LIDINGTON, GREEN, BRADLEY, MUNDELL, MCLOUGHLIN.

      The groupings are:

      MARR, CHAKRABARTI, HAMMOND
      NEIL, EAGLE, GREEN
      NEWMAN, ABRAHAMS, GRAYLING
      PARKINSON, LEWIS, BRADLEY
      PAXMAN, STARMER, MUNDELL
      POPPLEWELL, WATSON, MCLOUGHLIN
      ROBINSON, ABBOTT, LEADSOM
      SNOW, CORBYN, LIDINGTON

      Like

  • Unknown's avatar

    Jim Randell 8:36 am on 31 July 2019 Permalink | Reply
    Tags:   

    Teaser 2895: Spanish and Latin 

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

    I have ten cards. For each card there is a number in Spanish on one side and a number in Latin on the other.

    The Spanish numbers are CINCO, CUATRO, DIEZ, DOS, NUEVE, OCHO, SEIS, SIETE, TRES and UNO. The Latin numbers are DECEM, DUO, NOVEM, OCTO, QUATTUOR, QUINQUE, SEPTEM, SEX, TRES and UNUS. For each of the ten pairs of numbers, there are two letters in common. If I told you on how many cards the two numbers were consecutive, you should be able to work out all ten pairings. The Spanish numbers are written alphabetically.

    What is the corresponding order for the Latin numbers?

    [teaser2895]

     
    • Jim Randell's avatar

      Jim Randell 8:37 am on 31 July 2019 Permalink | Reply

      This Python program make use of a couple of the routines from the enigma.py library to solve this puzzle in a few lines of code. It runs in 80ms.

      Run: [ @repl.it ]

      from enigma import (grouping, filter_unique, unpack)
      
      # the words and corresponding numbers
      spanish = dict(CINCO=5, CUATRO=4, DIEZ=10, DOS=2, NUEVE=9, OCHO=8, SEIS=6, SIETE=7, TRES=3, UNO=1)
      latin = dict(DECEM=10, DUO=2, NOVEM=9, OCTO=8, QUATTUOR=4, QUINQUE=5, SEPTEM=7, SEX=6, TRES=3, UNUS=1)
      
      # find solutions unique by the number of pairs with consecutive values
      (ss, _) = filter_unique(
        # find all solution groups
        grouping.groups([list(spanish.keys()), list(latin.keys())], grouping.share_letters(2)),
        # count pairs with numerically consecutive values
        lambda s: sum(abs(spanish[es] - latin[la]) == 1 for (es, la) in s),
        tuple
      )
      
      # output solutions
      for s in ss:
        # sort the solution by the spanish numbers alphabetically
        grouping.output_groups(sorted(s, key=unpack(lambda es, la: es)))
      

      Solution: The corresponding Latin numbers are: NOVEM, TRES, DECEM, DUO, UNUS, OCTO, SEPTEM, QUINQUE, SEX, QUATTUOR.

      So the pairs are:

      CINCO, NOVEM (NO)
      CUATRO, TRES (RT) [consecutive]
      DIEZ, DECEM (DE)
      DOS, DUO (DO)
      NUEVE, UNUS (NU)
      OCHO, OCTO (CO)
      SEIS, SEPTEM (ES) [consecutive]
      SIETE, QUINQUE (EI)
      TRES, SEX (ES)
      UNO, QUATTUOR (OU)

      There are also two sets of cards that have 4 cards with consecutive numbers:

      CINCO, NOVEM (NO)
      CUATRO, TRES (RT) [consecutive]
      DIEZ, DECEM (DE)
      DOS, DUO (DO)
      NUEVE, UNUS (NU)
      OCHO, OCTO (CO)
      SEIS, SEPTEM (ES) [consecutive]
      SIETE, SEX (ES) [consecutive]
      TRES, QUATTUOR (RT) [consecutive]
      UNO, QUINQUE (NU)

      CINCO, QUINQUE (IN)
      CUATRO, TRES (RT) [consecutive]
      DIEZ, DECEM (DE)
      DOS, DUO (DO)
      NUEVE, UNUS (NU)
      OCHO, OCTO (CO)
      SEIS, SEPTEM (ES) [consecutive]
      SIETE, SEX (ES) [consecutive]
      TRES, QUATTUOR (RT) [consecutive]
      UNO, NOVEM (NO)

      And these are the only sets of cards that can be made.

      Like

  • Unknown's avatar

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

    Brain-Teaser 490: Equal marks 

    From The Sunday Times, 18th October 1970 [link]

    Tom, Dick and Harry took a test in each of five subjects. Each test was marked out of a total of 40. In grand total each boy obtained half-marks, and no boy scored the same mark in two or more tests.

    Each boy’s best and third-best marking totalled one-fifth more than the total of his best and fourth-best, and each boy’s worst mark exceeded 10.

    The aggregate of the three boys’ marks in each of four subjects was the same, the highest single mark going to Tom. The second-highest was scored by Dick in the remaining subject.

    How many marks did Harry get in that subject?

    This puzzle is included in the book Sunday Times Brain Teasers (1974).

    [teaser490]

     
    • Jim Randell's avatar

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

      This Python program runs in 410ms.

      Run: [ @repl.it ]

      from enigma import (irange, subsets, multiset, cproduct, printf)
      
      # find sets of 5 scores that sum to 100
      ss = list()
      for s in subsets(irange(11, 40), size=5, select='C'):
        # total score is 100
        if not (sum(s) == 100): continue
        # (best + 3rd best) = (6/5)(best + 4th best)
        if not (5 * (s[-1] + s[-3]) == 6 * (s[-1] + s[-4])): continue
        ss.append(s)
      
      # choose scores for the 3 students
      for (s1, x2, x3) in subsets(ss, size=3, select='C'):
        # choose orders for s2 and s3
        permute = lambda x: subsets(x, size=len, select='P')
        for (s2, s3) in cproduct([permute(x2), permute(x3)]):
          scores = (s1, s2, s3)
          # accumulate the total scores in each test
          ts = list(sum(s) for s in zip(*scores))
          m = multiset(ts)
          if not (sorted(m.values()) == [1, 4]): continue
          # find the highest and second highest marks
          ms = sorted(s1 + s2 + s3)
          (m1, m2, m3) = (ms[-1], ms[-2], ms[-3])
          if not (m1 > m2 > m3): continue
      
          # determine which is Tom, Dick
          T = D = H = -1
          for (i, s) in enumerate(scores):
            if m1 in s: T = i
            if m2 in s: D = i
          # Harry is the other one
          H = 3 - (T + D)
          if not (sorted([T, D, H]) == [0, 1, 2]): continue
          # check the 2nd highest score is in the test with the unique total
          d = scores[D].index(m2)
          if not (m[ts[d]] == 1): continue
      
          # output solution
          printf("T = {T}", T=scores[T])
          printf("D = {D}", D=scores[D])
          printf("H = {H}", H=scores[H])
          printf("+ = {ts}")
          printf("answer = {x}", x=scores[H][d])
          printf()
      

      Solution: 15 marks.

      The scores in each test are shown below:

      The highest single mark is highlighted red. The second highest mark is orange. And the answer (Harry’s mark in the same subject as the second highest mark) is yellow.

      There is a “near miss” scenario, where the scores are as follows:

      T = (11, 12, 21, 23, 33)
      D = (25, 26, 22, 14, 13)
      H = (25, 23, 13, 24, 15)

      The sum of the scores for each test are 61, apart from the third one where they are 56.

      Tom has the highest score (33) and Dick has the second highest (26), but the score of 26 is not in the subject with a sum of 56.

      The scores are a rearrangement of the scores in the actual solution because there are only three possible sequences of 5 scores between 11 and 40 that sum to 100 and have best and third best scores summing to one fifth more than the sum of the best and fourth best scores.

      Like

  • Unknown's avatar

    Jim Randell 12:40 pm on 28 July 2019 Permalink | Reply
    Tags:   

    Brainteaser 1633: New Year’s resolution 

    From The Sunday Times, 26th December 1993 [link]

    My New Year’s resolution is that this year I will remember my father’s birthday. To remind me I devised this formula: if I take the factorial of the number on the calendar representing the month in which he was born (1 for January to 12 for December) and multiply this by the square of the day of the month of his birth (1 to 31), the four digit result is the year when he was born.

    [Note, for example, that “6 factorial” is 6×5×4×3×2×1 = 720.]

    I then realised that this is no use for determining his birthday as even my own date of birth fits the formula.

    Can you tell me what is my father’s date of birth?

    This puzzle is included in the book Brainteasers (2002) under the title of “Birthday resolution”. The text was changed slightly, but the puzzle remains the same.

    [teaser1633]

     
    • Jim Randell's avatar

      Jim Randell 12:41 pm on 28 July 2019 Permalink | Reply

      This Python program finds day/month/year combinations that satisfy the formula, where the year is in the range [1850, 1993].

      It runs in 84ms.

      Run: [ @repl.it ]

      from enigma import irange, factorial, printf
      
      # number of possible days in each month
      days = (31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
      
      # consider day, month, formula values
      for (m, dm) in enumerate(days, start=1):
        f = factorial(m)
        for d in irange(1, dm):
          y = f * d * d
          if y < 1850: continue
          if y > 1993: break
          printf("d={d} m={m} -> y={y}")
      

      Solution: The father’s birthdate is 4th May 1920.

      There are 3 day/month combinations that give a reasonable value for the year.

      These are:

      day=18, month=3 → year=1944
      day=9, month=4 → year=1944
      day=4, month=5 → year=1920

      So the setters birthdate must be one of the 1944 dates (18th March 1944, 9th April 1944) and his fathers birthdate must be 4th May 1920.

      But it seems to me that the setter would probably be able to remember that his father was not born in 1944, so he can use the formula to determine his fathers birthday.

      The setter is obviously not a fan of Star Wars, otherwise he would find it easy to remember his father’s birthday.

      Like

  • Unknown's avatar

    Jim Randell 6:52 pm on 26 July 2019 Permalink | Reply
    Tags:   

    Teaser 2966: On track 

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

    Sarah and Jenny are runners who train together on a circular track, and Sarah can run up to 20 per cent faster than Jenny. They both run at a constant speed, with Sarah running an exact percentage faster than Jenny. To reduce competition they start at the same point, but run round the track in different directions, with Sarah running clockwise.

    On one day they passed each other for the seventh time at a point which is an exact number of degrees clockwise from the start. Sarah immediately changed her pace, again an exact percentage faster then Jenny. After a few [additional] passes both runners reached the exit, at a point on the track an exact number of degrees clockwise from the start, at the same time.

    How fast, relative to Jenny, did Sarah run the final section?

    [teaser2966]

     
    • Jim Randell's avatar

      Jim Randell 8:20 pm on 26 July 2019 Permalink | Reply

      If S is going p percent faster than J, she is going at rate of (1 + p/100) times as fast as J.

      If they meet after J has travelled through d degrees of the circle, then S has travelled through d(1 + p/100) degrees of the circle, and together these must make up the full circle. So:

      d + d(1 + p/100) = 360
      d = 36000 / (200 + p)

      And if they meet at an exact number of degrees after k passings:

      kd = 36000k / (200 + p)

      must be an integer.

      This Python program finds possible percentage increases for S where she meets J at an exact number of degrees for up to 7 passings. It runs in 81ms.

      Run: [ @repl.it ]

      from enigma import (irange, cproduct, printf)
      
      # suppose they meet after k passings and S runs p percent faster than J
      for (k, p) in cproduct([irange(1, 7), irange(1, 20)]):
        # do they meet at an exact number of degrees?
        if (36000 * k) % (200 + p) == 0:
          printf("k={k} p=+{p}% [{s}]", s=('initial' if k == 7 else 'final'))
      

      Solution: Sarah ran the final section 16% faster than Jenny.

      For the first section Sarah was running 10% faster than Jenny.

      And the final section lasted for some multiple of 3 crossings. Probably 3 or 6, as there are only “a few” additional passes, but we don’t need to know that to get the answer to the puzzle.

      Further solutions appear if we allow higher values of k. For example, at k = 11 we get a solution where S is 20% faster than J, but from the wording of the puzzle it seems likely that the number of passings in the final section is fewer than 7, so we get a unique answer.

      Like

    • John Crabtree's avatar

      John Crabtree 2:19 am on 27 July 2019 Permalink | Reply

      You could calculate the minimum k for any p. In Excel format:
      k = +(200 + p) / GCD(36000, 200 + p)
      Then if k < 8, print k and p

      I am not a Python programmer, but understand that Python does have a gcd function.

      Like

      • Jim Randell's avatar

        Jim Randell 8:07 am on 27 July 2019 Permalink | Reply

        @John: Python does indeed have [[ gcd() ]].

        We can generate the list of first k for each p, and then output them in k order:

        from enigma import (irange, gcd, div, printf)
        
        # find first k for each p
        kps = ((div(200 + p, gcd(36000, 200 + p)), p) for p in irange(1, 20))
        
        # output (k, p) pairs, ordered by k
        for (k, p) in sorted(kps):
          printf("k={k} p=+{p}%")
        

        Like

      • Jim Randell's avatar

        Jim Randell 2:19 pm on 1 August 2019 Permalink | Reply

        Here’s a program that uses a similar approach to generate the solutions in a given range (in this case p = 1..20, k = 1..7, like my first program):

        from enigma import (irange, fraction, printf)
        
        # consider values for p
        for p in irange(1, 20):
          (a, b) = fraction(36000, 200 + p)
          # consider values for k
          for k in irange(b, 7, step=b):
            printf("k={k} p=+{p}% [{s}]", s=('initial' if k == 7 else 'final'))
        

        Like

    • Robert Brown's avatar

      Robert Brown 11:35 am on 1 August 2019 Permalink | Reply

      For each p value, you found equivalent k value. I reversed this, leading to an easy manual solution.
      At k passings, J has travelled 180k+x and S has travelled 180k–x giving J/S = (180k+x)/(180k–x).
      (x = integer, k is prime to avoid duplication). This gives the following rapid 3 line solution:

      k = 7 J/S = 1260+x / 1260-x By inspection, x = 60 giving J/S = 1.10
      k = 2 J/S = 360+x / 360-x By inspection, x = 60 giving J/S = 1.40 (too large)
      k = 3 J/S = 540+x / 540-x By inspection, x = 40 giving J/S = 1.16 (the answer)

      Like

  • Unknown's avatar

    Jim Randell 11:30 am on 26 July 2019 Permalink | Reply
    Tags:   

    Teaser 2816: Chat shows 

    From The Sunday Times, 11th September 2016 [link] [link]

    Each day next week there will be a chat show on television and in each show the host will appear with an actress and an actor.

    The hosts will be (in order) Dimbleby, Evans, Mack, Marr, NortonPeschardt and Ross. In no particular order, the actresses will be Arterton, Blunt, Carter, Jones, Knightley, Margolyes and Watson. Again in no particular order, the actors will be Bean, Caine, Cleese, Craig, De Niro, Neeson and Oldman.

    For any two people in the same show there are just two different letters of the alphabet that occur (perhaps more than once) in both their surnames.

    List the actresses in the order in which they appear.

    [teaser2816]

     
    • Jim Randell's avatar

      Jim Randell 11:30 am on 26 July 2019 Permalink | Reply

      This kind of grouping problem is a favourite of Graham Smithers. By the time this puzzle was published in September 2016 I had already solved several of this type of problem, writing a custom Python program for each one.

      So for this puzzle I wrote some generic code that could be used to solve this puzzle and the other similar puzzles I had encountered.

      The code is available in the enigma.py library by importing the [[ grouping ]] namespace.

      This Python program runs in 42ms.

      from enigma import grouping
      
      # categories for this puzzle
      hosts = ["Dimbleby", "Evans", "Mack", "Marr", "Norton", "Peschardt", "Ross"]
      actresses = ["Arterton", "Blunt", "Carter", "Jones", "Knightley", "Margolyes", "Watson"]
      actors = ["Bean", "Caine", "Cleese", "Craig", "De Niro", "Neeson", "Oldman"]
      
      # match the categories into groups such that each pair in each group shares exactly two letters
      grouping.solve([hosts, actresses, actors], grouping.share_letters(2))
      

      Solution: The order of the actresses is: Blunt, Carter, Margolyes, Arterton, Knightley, Jones, Watson.

      The full solution is:

      Dimbleby, Blunt, Bean
      Evans, Carter, Cleese
      Mack, Margolyes, Caine
      Marr, Arterton, Craig
      Norton, Knightley, Neeson
      Peschardt, Jones, Oldman
      Ross, Watson, De Niro

      Like

  • Unknown's avatar

    Jim Randell 12:15 pm on 25 July 2019 Permalink | Reply
    Tags:   

    Brain-Teaser 489: [Railway journeys] 

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

    The All-Go railway runs from Alby to Goby over 20 miles away. Let us say it goes from A to G, and on the way you stop at B, C, D, E and F in that order.

    All the distances between stops are different from one another and all are less than 8 miles, yet it is possible to make journeys of 1 mile, 2 miles, 3 miles and so on up to 18 miles by picking the right stations.

    The distance from A to B is less than the distance from F to G.

    How many miles from A are B, C, D, E, F and G?

    This puzzle was originally published with no title.

    [teaser489]

     
    • Jim Randell's avatar

      Jim Randell 12:15 pm on 25 July 2019 Permalink | Reply

      (See also: Teaser 1986).

      This Python program runs in 220ms.

      Run: [ @replit ]

      from enigma import (subsets, irange, tuples, csum, join, sprintf as f, printf)
      
      # required distances
      rs = set(irange(1, 18))
      
      # choose the lengths of the 6 segments, AB BC CD DE EF FG
      for ss in subsets(irange(1, 7), size=6, select='P'):
        (AB, BC, CD, DE, EF, FG) = ss
        if not (AB < FG): continue
      
        # collect together adjacent segments from 1 to 6
        ds = set(sum(t) for k in irange(1, 6) for t in tuples(ss, k))
        if not rs.issubset(ds): continue
      
        printf("{cs} [ss={ss}]", cs=join((f("A{x}={d}") for (x, d) in zip("BCDEFG", csum(ss))), sep=" "))
      

      Solution: The distances (in miles) are: A→B=2, A→C=7, A→D=14, A→E=15, A→F=18, A→G=24.

      The distances between stations are:

      [A] 2 [B] 5 [C] 7 [D] 1 [E] 3 [F] 6 [G]

      So as well as being able to make all the distances from 1 to 18, we can also make distances of 22 (B to G) and 24 (A to G).

      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