Tagged: by: G H Dickson Toggle Comment Threads | Keyboard Shortcuts

  • Unknown's avatar

    Jim Randell 12:29 pm on 5 May 2024 Permalink | Reply
    Tags: by: G H Dickson,   

    Brain-Teaser 748: [Cutting corners] 

    From The Sunday Times, 16th November 1975 [link]

    Young Bob had been given a carpentry set and with it a rectangular board (whose diagonal measured less than 1½ metres) on which to practise using his saw.

    With straight cuts of successively greater length and aggregating to an exact number of metres, he first proceeded to saw dissimilar triangular pieces off each corner of the board in turn, the remaining quadrilateral piece being put aside for another day.

    All the 12 sides of the sawn-off pieces measured exact and different numbers of centimetres.

    What were the length and width of the board? (in cms).

    As set this puzzle has multiple solutions, however if we interpret “less than 1½ meters” to mean “less than 150 cm, but more than 149 cm”, then we get a unique solution that is the same as that published in the newspaper.

    This puzzle was originally published with no title.

    [teaser748]

     
    • Jim Randell's avatar

      Jim Randell 12:30 pm on 5 May 2024 Permalink | Reply

      Perhaps the puzzle originally said “just less than 1½ metres”, but the “just” got lost somewhere.

      The following program assembles pairs of Pythagorean triangles point-to-point. This gives us candidate widths and heights for the board. We then find two pairs with the same width that fit together to make a rectangle as specified.

      By “dissimilar” triangles I am assuming that no pair of triangles is mathematically similar (i.e. none of them are multiples of the same primitive Pythagorean triangle).

      The program runs in 108ms. (Internal runtime is 40ms).

      Run: [ @replit ]

      from enigma import (
        defaultdict, pythagorean_triples, subsets, cproduct,
        seq_all_different, hypot, rev, ordered, ratio, cached, printf
      )
      
      # diagonal limit
      D = 150
      
      # possible triangles (x, y) -> z
      tris = dict(((x, y), z) for (x, y, z) in pythagorean_triples(D - 1))
      
      # primitive triangle
      primitive = cached(lambda t: ratio(*t))
      
      # assemble pairs of triangles: <combined-width> -> (<h1>, <h2>) -> (<w1>, <w2>)
      pairs = defaultdict(lambda: defaultdict(set))
      for (k1, k2) in subsets(tris.keys(), size=2):
        for ((w1, h1), (w2, h2)) in cproduct((k, rev(k)) for k in (k1, k2)):
          w = w1 + w2
          if w < D:
            (k, v) = ((h1, h2), (w1, w2)) if h1 < h2 else ((h2, h1), (w2, w1))
            pairs[w][k].add(v)
      
      # choose a width and height for the initial rectangle
      for (w, h) in subsets(pairs.keys(), size=2):
        z = hypot(w, h)
        if not (D - 1 < z < D): continue
      
        # choose a pair of triangles for the base
        for k1 in pairs[w]:
          (h1, h2) = k1
          # calculate the corresponding matched pair
          k2 = (h4, h3) = (h - h2, h - h1)
          if not (k2 > k1 and k2 in pairs[w]): continue
          for ((w1, w2), (w4, w3)) in cproduct(pairs[w][k] for k in (k1, k2)):
            # assemble the triangles
            (x1, y1, x2, y2, x3, y3, x4, y4) = (h1, w1, w2, h2, h4, w4, w3, h3)
            (z1, z2, z3, z4) = (tris[ordered(x, y)] for (x, y) in [(x1, y1), (x2, y2), (x3, y3), (x4, y4)])
            # sum of cuts is a multiple of 100
            T = z1 + z2 + z3 + z4
            if T % 100 != 0: continue
            # sides are all different
            ts = (t1, t2, t3, t4) = ((x1, y1, z1), (x2, y2, z2), (x3, y3, z3), (x4, y4, z4))
            if not seq_all_different(t1, t2, t3, t4): continue
            # triangle are dissimilar
            if not seq_all_different(primitive(ordered(*t)) for t in ts): continue
            # output solution
            printf("{w} x {h} -> {z:.2f}; {t1} {t2} {t3} {t4} T={T}")
      

      Solution: The board was: 28 cm × 147 cm.

      And here is how the triangles fit together:


      If we just look for any diagonal that is less than 150cm (which is a direct interpretation of the published puzzle text), then we find the following 23 solutions (ordered by length of diagonal):

      # Z = diagonal; T = total length of cuts
       28 × 147: Z=149.64 (12, 35, 37) (15, 112, 113) (16, 63, 65) (13, 84, 85) T=300
       51 × 140: Z=149.00 (15, 20, 25) (35, 120, 125) (36, 77, 85) (16, 63, 65) T=300
       87 × 120: Z=148.22 (7, 24, 25) (72, 96, 120) (80, 84, 116) (15, 36, 39) T=300
       48 × 140: Z=148.00 (15, 20, 25) (35, 120, 125) (33, 56, 65) (13, 84, 85) T=300
       60 × 135: Z=147.73 (9, 12, 15) (90, 48, 102) (126, 32, 130) (45, 28, 53) T=300
      103 × 105: Z=147.09 (5, 12, 13) (60, 91, 109) (100, 75, 125) (45, 28, 53) T=300
       95 × 112: Z=146.86 (20, 21, 29) (60, 91, 109) (75, 100, 125) (35, 12, 37) T=300
       83 × 120: Z=145.91 (18, 24, 30) (28, 96, 100) (65, 72, 97) (55, 48, 73) T=300
      100 × 105: Z=145.00 (9, 40, 41) (72, 65, 97) (91, 60, 109) (28, 45, 53) T=300
       90 × 112: Z=143.68 (20, 48, 52) (40, 42, 58) (92, 69, 115) (72, 21, 75) T=300
       60 × 129: Z=142.27 (3, 4, 5) (33, 56, 65) (126, 32, 130) (96, 28, 100) T=300
       69 × 124: Z=141.90 (9, 40, 41) (13, 84, 85) (60, 91, 109) (56, 33, 65) T=300
       85 × 111: Z=139.81 (5, 12, 13) (20, 99, 101) (80, 39, 89) (65, 72, 97) T=300
       93 × 104: Z=139.52 (20, 21, 29) (65, 72, 97) (84, 13, 85) (39, 80, 89) T=300
       92 × 104: Z=138.85 (5, 12, 13) (39, 80, 89) (99, 20, 101) (65, 72, 97) T=300
       59 × 124: Z=137.32 (7, 24, 25) (12, 35, 37) (117, 44, 125) (112, 15, 113) T=300
       76 × 114: Z=137.01 (15, 36, 39) (9, 40, 41) (99, 20, 101) (105, 56, 119) T=300
       80 × 111: Z=136.82 (5, 12, 13) (20, 99, 101) (75, 100, 125) (60, 11, 61) T=300
       84 × 108: Z=136.82 (3, 4, 5) (18, 80, 82) (105, 36, 111) (90, 48, 102) T=300
       95 ×  96: Z=135.06 (16, 63, 65) (60, 32, 68) (80, 18, 82) (36, 77, 85) T=300
       93 ×  95: Z=132.94 (11, 60, 61) (56, 33, 65) (84, 13, 85) (39, 80, 89) T=300
       67 ×  72: Z= 98.35 (9, 12, 15) (48, 55, 73) (63, 60, 87) (24, 7, 25) T=200
       56 ×  78: Z= 96.02 (8, 15, 17) (16, 63, 65) (48, 36, 60) (40, 42, 58) T=200
      

      and we see the published solution is the first of these (longest diagonal).

      Like

    • Hugo's avatar

      Hugo 3:36 pm on 5 May 2024 Permalink | Reply

      His saw cuts (each of which became the hypotenuse of a triangle) were progressively longer as he moved round the board to each corner in turn. Did you take that into account?

      Like

      • Jim Randell's avatar

        Jim Randell 4:45 pm on 5 May 2024 Permalink | Reply

        I didn’t check that the cut lengths can form an increasing sequence (going clockwise or anticlockwise around the board), as I decided he could just make the four cuts in ascending order, however they are arranged.

        But if you do require this there are still 9 different solutions with diagonals <150 cm (including the published one).

        Like

    • Hugo's avatar

      Hugo 7:43 am on 6 May 2024 Permalink | Reply

      I think we can reduce it to a single solution if we add the words
      “The board had the smallest possible area, consistent with what has been said.”

      Like

  • Unknown's avatar

    Jim Randell 2:38 pm on 18 June 2023 Permalink | Reply
    Tags: by: G H Dickson   

    Brain-Teaser 433: Hymn numbers 

    From The Sunday Times, 24th August 1969 [link]

    The hymn-board in church was electrically operated and made provision for any four hymn numbers of up to three digits in each (from 0 to 9), but did not provide blanks so that Hymn No. 7 for example would appear on the board as 007, and No. 77 as 077.

    One Sunday a parishioner noticed with surprise that not only was each of the four hymn numbers for that service a perfect square, but moreover each of the three numbers produced in the vertical columns was a 4-digit perfect square.

    When, back home, he told his son Tom of this unique occurrence, the latter exclaimed: “I can’t believe it! What were the numbers then?”, to which the father replied: “You already know enough to work that out for yourself, but it will be of help to you to learn that I also noticed that the totals of the digits of each hymn number were perfect squares too, and that, coincidentally, one of these squares would result from dividing the final hymn number into the number formed by the middle column”.

    But Tom still couldn’t puzzle it out and demanded to be told at any rate one of the hymn numbers, to which the father responded, “All I can remember now is that the third hymn number ended in two noughts”.

    What was the opening hymn number?

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

    [teaser433]

     
    • Jim Randell's avatar

      Jim Randell 2:39 pm on 18 June 2023 Permalink | Reply

      I used the [[ SubstitutedExpression ]] solver from the enigma.py library to solve this puzzle.

      The following run file executes in 80ms. (Internal runtime of the generated code is 8ms).

      Run: [ @replit ]

      #! python3 -m enigma -rr
      
      SubstitutedExpression
      
      #  A B C
      #  D E F
      #  G H I
      #  J K L
      
      --distinct=""
      --invalid="0,ABC" # columns form 4-digit squares
      
      # hymns are different
      "all_different(ABC, DEF, GHI, JKL)"
      
      # rows form squares
      "is_square(ABC)"
      "is_square(DEF)"
      "is_square(GHI)"
      "is_square(JKL)"
      
      # columns form squares
      "is_square(ADGJ)"
      "is_square(BEHK)"
      "is_square(CFIL)"
      
      # row sums form squares
      "is_square(A + B + C)"
      "is_square(D + E + F)"
      "is_square(G + H + I)"
      "is_square(J + K + L)"
      
      # 3rd row is x00
      --assign="H,0"
      --assign="I,0"
      
      # 4th row divides into middle column, to give one of the row sums
      "div(BEHK, JKL) in {A + B + C, D + E + F, G + H + I, J + K + L}"
      
      # [optional] just show the hymn numbers
      --template="ABC DEF GHI JKL"
      --solution=""
      

      Solution: The opening hymn number was: 529.

      The hymns are: 529, 36, 400, 144.

      We have:

      rows
      529 = 23²; 5 + 2 + 9 = 16 = 4²
      036 = 6²; 0 + 3 + 6 = 9 = 3²
      400 = 20²; 4 + 0 + 0 = 4 = 2²
      144 = 12² ; 1 + 4 + 4 = 9 = 3²

      columns
      5041 = 71²
      2304 = 48²
      9604 = 98²

      2304 / 144 = 16 = 4² = 5 + 2 + 9

      And we do indeed get a single solution if we just keep the requirements that the rows and columns form squares (lines 16 – 25).

      Like

  • Unknown's avatar

    Jim Randell 8:01 am on 6 June 2023 Permalink | Reply
    Tags: by: G H Dickson   

    Brain-Teaser 973: Square-rigger 

    From The Sunday Times, 15th March 1981 [link]

    Young Mary, who is good at manipulating figures, was playing with her standard set of dominoes and seeing what numerical structures she could form with them, treating each half-domino as a digit according to its number of spots (“blank” being 0).

    Starting with double-6/double-5/double-4 laid end-to-end in a row, she built forwards and downwards from that beginning, placing dominoes across and apparently at  random, until she had completed a solid rectangle by slotting into the only remaining gaps, in its farther half, her last two dominoes which were 4-&-blank and 2-&-blank.

    Whereupon she called out to me: “Uncle, do come and look! I’ve managed to arrange all my dominoes in a rectangle so that the numbers formed by the four halves in each column are all dissimilar 4-digit squares”.

    “Are you quite sure about that?” I temporised.

    “Certain,” she replied. “And they’re pretty well in correct order of magnitude too!”.

    When I protested that this was quite impossible with dominoes, she said reproachfully: “But Uncle, I never said that ALL the squares appear in the right order, did I?  Actually there are just two of them — both among the seven smallest present — which do not; but every single square except those two is definitely just where it would be if all those appearing were strictly in order of magnitude”.

    She was perfectly correct. And you don’t need dominoes to figure out …

    Which four of Mary’s together formed columns 7 and 8 of her rectangle? (Use figures, e.g. 4-0 = four-&-blank).

    This was the final puzzle to use the title Brain-Teaser. The next puzzle was Brain teaser 974.

    [teaser973]

     
    • Jim Randell's avatar

      Jim Randell 8:04 am on 6 June 2023 Permalink | Reply

      A standard set of dominoes has 28 dominoes, each with 2 numbers on, so there are 56 numbers in total, consisting of 8 copies of each of the digits from 0 to 6.

      The program starts by constructing a list of square numbers that can be constructed using only the digits available on dominoes (i.e. the digits 0-6). It then constructs a viable sequence of squares that use the required 56 digits between them, and we consider swapping a pair of the numbers in the second half of the list to give Mary’s list of squares.

      We then turn the numbers into a 14×4 grid and use the [[ DominoGrid() ]] solver from the enigma.py library to find viable arrangements of dominoes.

      The program runs in 558ms. (Internal runtime is 412ms).

      Run: [ @replit ]

      from enigma import (
        DominoGrid, irange, subsets, multiset, flatten, unzip, union, group,
        update, seq_ordered as ordered, seq_get as get, join, printf
      )
      
      # available digits on dominoes
      digits = set("0123456")
      
      # find 4-digit squares that can be represented by dominoes
      sqs = list()
      for i in irange(32, 81):
        s = str(i * i)
        if not digits.issuperset(s): continue
        sqs.insert(0, s)
      
      # construct viable sequences of squares (in descending order)
      # - each of the digits 0-6 must be used exactly 8 times
      # - the sequence must start: 6xxx, 6xxx, 5xxx, 5xxx, 4xxx, 4xxx
      def squares(sqs, ds=None, ss=[]):
        # ds counts the digits remaining to be used
        if ds is None: ds = multiset.from_seq('0123456', count=8)
        # are we done?
        n = len(ss)
        if n == 14:
          yield ss
        elif not (n + len(sqs) < 14):
          # choose the next square to include
          for (i, sq) in enumerate(sqs):
            # 0, 1 must be 6xxx
            if n < 2:
              if sq[0] < '6': break
            # 2, 3 must be 5xxx
            elif n < 4:
              if sq[0] > '5': continue
              if sq[0] < '5': break
            # 4, 5 must be 4xxx
            elif n < 6:
              if sq[0] > '4': continue
              if sq[0] < '4': break
            # can we add sq to the sequence?
            if ds.issuperset(sq):
              # solve for the remaining squares in the list
              yield from squares(sqs[i + 1:], ds.difference(sq), ss + [sq])
      
      # domino ordering
      order = lambda xs: ordered(xs, reverse=1)
      
      # find dominoes used in specified columns (1-indexed)
      def dominoes(p, grid, cols):
        # indices of columns
        ks = union(irange(x - 1, 55, step=14) for x in cols)
        # find the dominoes at the specified indices
        g = group(ks, by=get(grid), f=get(p.grid))
        # extract dominoes that are entirely in selected columns
        for v in g.values():
          if len(v) == 2:
            yield order(v)
      
      # collect solutions
      rs = set()
      
      # consider possible sequences of squares
      for ss in squares(sqs):
        # choose two squares from index 7-13 to swap
        for (i, j) in subsets(irange(7, 13), size=2):
          ss_ = update(ss, [(i, ss[j]), (j, ss[i])])
          # construct the grid
          p = DominoGrid(14, 4, list(int(x) for x in flatten(unzip(ss_))))
          # and solve it
          for (grid, used) in p.solve(fixed=[(0, 1), (2, 3), (4, 5)]):
            # check that (4, 0) and (2, 0) occur in columns 8 - 14
            ds = set(dominoes(p, grid, irange(8, 14)))
            if not ((4, 0) in ds and (2, 0) in ds): continue
      
            # find the 4 dominoes in columns 7 and 8
            ds = order(dominoes(p, grid, [7, 8]))
            if len(ds) != 4: continue
            rs.add(ds)
      
            printf("squares = {ss_}", ss_=join(ss_, sep=" "))
            printf()
            p.output_solution((grid, used))
            printf("cols 7/8 = {ds}", ds=join(ds, sep=" "))
            printf("--")
      
      # output solution
      for ds in rs:
        printf("answer = {ds}", ds=join(ds, sep=" "))
      

      Solution: The dominoes making up columns 7 and 8 are: [6-0] [5-0] [3-3] [2-0].

      There is only one arrangement of square numbers that use each of the digits 0-6 exactly 8 times:

      6400, 6241, 5625, 5041, 4356, 4225, 3600, 3025, 3136, 3364, 2401, 2304, 1521, 1156

      And there are 2 (slightly) different ways the required grid can be constructed from a set of dominoes, here is one way:

      The [6-3] and [6-4] dominoes can be placed either horizontally or vertically to give the two layouts.

      If the indicated columns were swapped the squares would be in strict descending numerical order.

      The [2-0] and [4-0] dominoes (highlighted) were placed last in the right-hand half of the layout. If this condition is removed more arrangements are viable (16 in total), but the sequence of squares (and answer to the puzzle) remains the same.

      Like

  • Unknown's avatar

    Jim Randell 9:23 am on 21 May 2023 Permalink | Reply
    Tags: by: G H Dickson   

    Brain-Teaser 386: South Pacific 

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

    Among those innumerable South Pacific islands in which the vicinity of longitude 180° abounds, there are three neighbouring ones between which an ancient ferryboat maintains each week a regular schedule. This schedule, which is strictly adhered to except when ordered otherwise, is:

    ALOHA: dep. Monday 9 a.m.
    BALI-HAI: arr. Tuesday 7.p.m.
    BALI-HAI: dep. Tuesday 10 p.m.
    CRACKATOEA: arr. Friday 9 p.m.
    CRACKATOEA: dep. Saturday 7 a.m.
    ALOHA: arr. Sunday 7 p.m.

    The ferry maintains the same leisurely speed throughout each leg of the triangular circuit.

    To Port Authority at the home port of Aloha, one Thursday at 9 p.m, radioed to the ferry on its course between the other two islands that a hurricane in the area was imminent, and ordered it to proceed at once to the nearest of the three for shelter.

    Without altering speed, the captain immediately complied.

    Which island did he accordingly reach, and what were the day and hour of his arrival there?

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

    [teaser386]

     
    • Jim Randell's avatar

      Jim Randell 9:23 am on 21 May 2023 Permalink | Reply

      The boat travels at a steady speed, so we can equate journey times with distances, and I think we are to assume it travels directly between the islands in straight line distances.

      So the first problem is that the apparent distances between islands (34h, 71h, 36h) do not form a triangle.

      But as we are “in the vicinity of longitude 180°”, it could be the case that the islands straddle the International Date Line, and so some of them could have local times that are 24 hours ahead of the others, and the times mentioned are local to the corresponding islands.

      (I suppose potentially there could be more than 2 timezones involved, and the timezones do not necessarily differ by 24 hours, but I think that would not lead to a unique solution. And I also suppose that the puzzle doesn’t mention that all times are local times so that it doesn’t give away any clues to the solution).

      This Python program considers possible collections of the 3 islands that are 24 hours ahead of the remaining islands, and looks to see if the actual elapsed journey times can form a triangle. If so, we check that a call made at 93 hours after midnight on Monday (local to A), would be received by the boat while it is on the B→C journey, and if so calculates which of the islands it is closest to, and the time it would arrive.

      Run: [ @replit ]

      from enigma import (empty, call, subsets, fdiv, sq, sqrt, divf, sprintf, seq2str, map2str, printf)
      
      # check the side lengths form a triangle
      def is_triangle(a, b, c):
        return all([0 < a < b + c, 0 < b < a + c, 0 < c < a + b])
      
      # adjust a time = what time is it in <x> when in <y> it is <t>?
      def adjust(x, y, t, ahead):
        if x not in ahead and y in ahead: return t - 24
        if x in ahead and y not in ahead: return t + 24
        return t
      
      # local time, Mon 12am + <h> hours
      days = "Mon Tue Wed Thu Fri Sat Sun".split()
      def time(h):
        d = divf(h, 24)
        h -= d * 24
        return sprintf("{d} {h:.4g}h", d=days[d % 7])
      
      # calculate time direct to A from BC leg, given time out from B
      def timeA(elapsed, tB):
        (AB, BC, CA) = (elapsed[k] for k in ('AB', 'BC', 'CA'))
        # cosine rule
        return sqrt(sq(tB) + sq(AB) - tB * fdiv(sq(AB) + sq(BC) - sq(CA), BC))
      
      # solve the puzzle where specified ports are +24 hours ahead of the others
      def solve(times, ahead=empty):
        # calculate the actual elapsed times
        elapsed = dict()
        for (k, t) in times.items():
          (x, y) = k
          elapsed[k] = adjust(x, y, t, ahead)
        # check the elapsed times form a triangle
        if not call(is_triangle, elapsed.values()): return
      
        # the call is made at 93h/A
        # at which time the boat is on the BC leg (46h/B -> 117h/C)
        depB = adjust('A', 'B', 46, ahead)
        arrC = adjust('A', 'C', 117, ahead)
        (tB, tC) = (93 - depB, arrC - 93)
        if not (tB > 0 and tC > 0): return
        # calculate direct route to A
        tA = timeA(elapsed, tC)
        # make the shortest journey
        printf("[ahead = {ahead}, elapsed = {elapsed}]", ahead=seq2str(ahead), elapsed=map2str(elapsed))
        t = min(tA, tB, tC)
        ans = lambda x, t=t: ('= NEAREST' if x == t else '')
        # divert to A
        arr = 93 + tA
        printf("-> A = {tA:.4g}h, arrive {arr} (local) {x}", arr=time(arr), x=ans(tA))
        # return to B
        arr = adjust('B', 'A', 93, ahead) + tB
        printf("-> B = {tB:.4g}h, arrive {arr} (local) {x}", arr=time(arr), x=ans(tB))
        # continue to C as planned
        printf("-> C = {tC:.4g}h, arrive {arr} (local) {x}", arr=time(117), x=ans(tC))
        printf()
      
      # the apparent journey times (from the schedule)
      times = dict(AB=34, BC=71, CA=36)
      
      # consider possible islands with local time 24h ahead
      for ahead in subsets('ABC', min_size=0, max_size=2):
        solve(times, ahead)
      

      Solution: The boat reached Bali-Hai on Thursday, 8pm (local time).


      A and C are 24h ahead of B.

      So the corresponding elapsed journey times are: A→B = 58h; B→C = 47h; C→A = 36h.

      The call is made from A at 9pm on Thursday (A/C time), and received on the boat at at 9pm on Wednesday (B time).

      At this point it is 23 hours into the 47 hour journey, so B is 23 hours away and C is 24 hours away. (And A is about 42 hours away).

      The boat returns to B, and arrives at 8pm on Thursday (B time).

      If it continues to C, it would arrive 1 hour later at 9pm on Friday (C time) (as scheduled).

      Like

    • Hugo's avatar

      Hugo 2:22 pm on 21 May 2023 Permalink | Reply

      Not local times (which differ by 4 minutes for each degree of longitude) but zone times.
      We also have to assume that all the zone times are a whole number of hours fast or slow of GMT;
      Chatham Island (for example) is on GMT + 12:45.

      Like

    • Frits's avatar

      Frits 3:54 pm on 23 May 2023 Permalink | Reply

      Also calculating the distance to Aloha.

         
      from enigma import SubstitutedExpression
      
      # check the side lengths form a triangle
      def is_triangle(a, b, c):
        return all([0 < a < b + c, 0 < b < a + c, 0 < c < a + b])
        
      # distance to A to point (p, 0) on line BC 
      def dista(ab, bc, ac, p):  
        x = (ab**2 - ac**2 - bc**2) / (-2 * bc)
        y = (ac**2 - x**2)**.5
        
        # return distance between (x, y) and (p, 0)
        return ((x - p)**2 + (y - 0)**2)**.5
      
      # return local time, Mon 0am + <h> hours
      def time(h):
        weekdays = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
                    "Saturday", "Sunday"]
      
        (d, h) = divmod(h, 24)
        return weekdays[d % 7] + " " + str(h % 12) + ('am' if h < 12 else 'pm')
      
      # the alphametic puzzle
      p = SubstitutedExpression(
        [
         # (K, L, M) = ahead bits for (A, B, C)
         "K + L + M < 3",
         
         # check that the adjusted times/distances form a triangle
         "is_triangle(((depb := 46 + 24 * (K - L)) - 3) - 9, \
                       (arrc := 117 + 24 * (K - M)) - depb, \
                       163 - (arrc + 10))",
                       
         # at time of the radio call the boat is still at sea (between B and C)
         "(93 - depb) and (arrc - 93)",
        ],
        answer="(da := dista((depb - 3) - 9, \
                             arrc - depb, \
                             163 - (arrc + 10), \
                             93 - depb), \
                93 - depb, arrc - 93), \
                (93 + da, 186 - depb + 24 * (L - K), arrc)",
        d2i=dict([(k, "KLM") for k in range(2, 10)]),
        distinct="",
        env=dict(is_triangle=is_triangle, dista=dista),
        reorder=0,
        verbose=0,    # use 256 to see the generated code
      )
      
      islands = ("Aloha", "Bali-Hai", "Crackatoea")
      # print answers
      for (_, ans) in p.solve():
         # determine shortest route
        for ind in [i for i, x in enumerate(ans[0]) if x == min(ans[0])]:
          print(f"reached island: {islands[ind]}, arrival: {time(ans[1][ind])}")
      

      Like

      • Jim Randell's avatar

        Jim Randell 9:39 pm on 23 May 2023 Permalink | Reply

        Yes, it does say the boat should proceed to the “nearest of the three islands”, so I’ve added in code to calculate the distance to A (using the cosine rule), and also to give a bit more information with the solution.

        Like

  • Unknown's avatar

    Jim Randell 7:46 am on 19 March 2023 Permalink | Reply
    Tags: by: G H Dickson   

    Brainteaser 1057: Palindromic primes 

    From The Sunday Times, 31st October 1982 [link]

    Teacher was introducing his class to the binary system of notation (wherein the unit values attaching to successive digits from right to left of any integer are 1, 2, 4, 8, 16, etc., as against 1, 10, 100, 1000, etc., in the decimal system).

    He went on to explain that many arithmetical relationships are equally valid in both the binary and decimal systems. And gave as the simplest example:

    10 × 11 = 110

    which in the binary system represents 2 × 3 = 6, pointing out this difference however – that while both factors 10 and 11 are primes in the binary system, only 11 is prime in the decimal system.

    Developing this theme he observed that very often such relationships could be described as “pan-palindromic”, in the sense that both of the factors, as well as their product, are numerical palindromes (i.e. each of the three integers reads the same forwards as backwards). His first example was:

    1001 × 10101 = 10111101

    (which in the binary system represents 9 × 21 = 189), and he pointed out how this time neither factor was a prime using either the binary or decimal system (being patently divisible by 11 and 3 respectively).

    He contrasted this with another example:

    111 × 1001001 = 111111111

    which in the binary system represents: 7 × 73 = 511, where both factors are primes in the binary system, but neither of them are in the decimal system (both being divisible by 3).

    To test how well his pupils were taking in all this, he told them to proceed on their own and write down any binary palindromes they could find, of less than twelve digits, which simultaneously, in both binary and decimal systems, factorised into just two different palindromic primes.

    What should they have written down?

    [teaser1057]

     
    • Jim Randell's avatar

      Jim Randell 7:47 am on 19 March 2023 Permalink | Reply

      This Python program considers numbers that are binary palindromes (with < 12 digits), and that have exactly 2 different prime factors, which are themselves binary palindromes. It then checks that if the multiplication sum is interpreted in decimal, instead of binary, that it still works, and the decimal factors are also prime.

      Total runtime is 64ms. (Internal runtime is 713µs).

      Run: [ @replit ]

      from enigma import (irange, inf, nsplit, rev, nconcat, factor, is_npalindrome, is_prime, printf)
      
      # generate numbers that are binary palindromes < 12 digits
      def generate():
        for n in irange(1, inf):
          # split n into digits
          ds = nsplit(n, base=2, fn=list)
          k = len(ds)
          if k > 6: break
          # mirror the digits to make a palindrome
          ds.extend(rev(ds))
          if k < 6: yield nconcat(ds, base=2)
          ds.pop(k)
          yield nconcat(ds, base=2)
      
      # start with a number that is a binary palindrome
      for n in generate():
        # find the prime factorisation
        fs = factor(n)
        if not (len(fs) == 2 and len(set(fs)) == 2): continue
        (a, b) = fs
        # check the factors are themselves binary palindromes
        if not (is_npalindrome(a, base=2) and is_npalindrome(b, base=2)): continue
        # check the multiplication works if the binary factorisation is interpreted as decimal
        (nx, ax, bx) = (nconcat(nsplit(x, base=2), base=10) for x in (n, a, b))
        if not (ax * bx == nx): continue
        # check the factors are prime if interpreted as decimal
        if not (is_prime(ax) and is_prime(bx)): continue
        # output solution
        printf("{a:b} * {b:b} = {n:b} [base 2] -> {a} * {b} = {n} [base 10]")
      

      Solution: The sum is: 11 × 101 = 1111.

      In decimal both 11 and 101 are prime.

      In binary this corresponds to: 3 × 5 = 15, and both 3 and 5 are prime.

      Like

  • Unknown's avatar

    Jim Randell 9:37 am on 15 November 2022 Permalink | Reply
    Tags: by: G H Dickson   

    Brain-Teaser 670: A shared legacy 

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

    When my neighbour Giles found he could no longer look after his prize herds of cattle and sheep, he planned to divide the lot among his four sons in equal shares.

    But when he started by counting up the cattle he soon found that their total was not exactly divisible by four, so he decided he would juggle with the numbers of beasts and achieve the four shares of equal value by making to the respective recipients quite arbitrary allocations of both cattle and sheep, taking into account that the value per head of the former was four times that of the latter.

    The outcome was that:

    (i) one son received 80% more beasts than another;
    (ii) two sons each received a total of beasts which equalled the aggregate total of two of the other three sons;
    (iii) one son received twice as many of one type of beast as of the other;
    (iv) only one son received over 100 beasts in all.

    How many cattle were included in this last total of over 100 beasts?

    This puzzle is included in the book The Sunday Times Book of Brain-Teasers: Book 2 (1981). The puzzle text above is taken from the book.

    [teaser670]

     
    • Jim Randell's avatar

      Jim Randell 9:37 am on 15 November 2022 Permalink | Reply

      If the total number of animals received by each brother is: A, B, C, D (in descending order), then (from (iv)) A is the only one to receive more than 100.

      And from (ii) two of the brothers totals are equal to the sum of the totals of two of the remaining three brothers. These two must be A and B, and so B = C + D, and A = C + 2D or 2C + D.

      This Python program starts by finding possible A, B, C, D values, and then tries to split these totals into numbers of cattle and sheep such that the remaining conditions hold.

      It runs in 62ms. (Internal runtime is 11.2ms).

      Run: [ @replit ]

      from enigma import (irange, subsets, ediv, as_int, printf)
      
      # split total <t> into (<cattle>, <sheep>) with value <v>
      def split(t, v):
        c = ediv(v - t, 3)
        return (as_int(c, "0+"), as_int(t - c, "0+"))
      
      # solve puzzle for given totals: A, B, C, D
      def solve(A, B, C, D):
        # consider number of cattle for A
        for Ac in irange(0, A):
          As = A - Ac
          # total value for A (cattle = 4, sheep = 1)
          v = 4 * Ac + As
          # find splits for B, C, D
          try:
            (Bc, Bs) = split(B, v)
            (Cc, Cs) = split(C, v)
            (Dc, Ds) = split(D, v)
          except ValueError:
            continue
      
          # total number of cattle is not divisible by 4
          if (Ac + Bc + Cc + Dc) % 4 == 0: continue
          # someone has twice as many of one type of animal as the other
          if all(2 * x != y and x != 2 * y for (x, y) in [(Ac, As), (Bc, Bs), (Cc, Cs), (Dc, Ds)]): continue
      
          # output scenario
          printf("[v={v}] A: {Ac}c+{As}s = {A}; B: {Bc}c+{Bs}s = {B}; C: {Cc}c+{Cs}s = {C}; D: {Dc}c+{Ds}s = {D}")
      
      # total number of animals for C (not more than 100)
      for C in irange(1, 100):
        # total number of animals for D (not more than C)
        for D in irange(0, C):
          # B = C + D (not more than 100)
          B = C + D
          if B > 100: break
          # A = C + 2D or 2C + D (more than 100)
          for A in (B + D, B + C):
            if not (A > 100): continue
            # one of these values must be 1.8x a lower value
            if not any(5 * x == 9 * y for (x, y) in subsets((A, B, C, D), size=2)): continue
            # solve the puzzle
            solve(A, B, C, D)
      

      Solution: The son receiving over 100 animals received 6 cattle.

      The full solution is:

      A: 6 cattle + 111 sheep = 117 animals; 117 = 81 (B) + 36 (D)
      B: 18 cattle + 63 sheep = 81 animals; 81 = 45 (C) + 36 (D) = 1.8 × 45 (C)
      C: 30 cattle + 15 sheep = 45 animals; 30 is twice 15
      D: 33 cattle + 3 sheep = 36 animals

      Assigning values of cattle = 4, sheep = 1, each brother receives animals to a value of 135.

      In total there are 279 animals = 87 cattle (not a multiple of 4) + 192 sheep.

      Like

  • Unknown's avatar

    Jim Randell 10:24 am on 15 February 2022 Permalink | Reply
    Tags: by: G H Dickson   

    Brain-Teaser 878: Four twos make …? 

    From The Sunday Times, 4th June 1978 [link]

    Two maths pupils had been indulging in the traditional “Four Fours” recreation, (i.e. seeing how many consecutive integers from 1 up they could express by means of a string of just four 4s with the signs for addition, subtraction, multiplication or division (to obviate numerator/denominator) interspersed as required, along with brackets where needed for clarity, but (according to their rules) featuring no power indices nor other aids except that each expression may use one decimal point. Examples illustrating all this are:

    18 = (4 / .4) + 4 + 4
    28 = 4 × (4 + 4) – 4

    As a variant they then tried working with 2s instead of 4s but soon found that there is a certain integer, lower than both of the above, which defeats every effort to express it with only four 2s. But when they used the minimum number of 2s to express it, they found, under corresponding conditions, that they could express it in a number of different ways. Indeed they found two ways which used neither addition nor multiplication.

    What were those two expressions?

    This puzzle is included in the book The Sunday Times Book of Brain-Teasers: Book 2 (1981). The puzzle text above is taken from the book.

    [teaser878]

     
    • Jim Randell's avatar

      Jim Randell 10:24 am on 15 February 2022 Permalink | Reply

      See also: Teaser 1949-12-25.

      We can take the code for Teaser 1949-12-25, and change it to using four 2’s, and only the 4 basic mathematical operators.

      We find that we can generate all the numbers from 1 to 16:

      1 = 22 / 22
      2 = (2 / 2) + (2 / 2)
      3 = 2 + 2 − (2 / 2)
      4 = 2 + 2 + 2 − 2
      5 = 2 + 2 + (2 / 2)
      6 = (2 + 2) × 2 − 2
      7 = 2 + 2 / (2 × .2)
      8 = 2 + 2 + 2 + 2
      9 = (22 / 2) − 2
      10 = 22 / 2.2
      11 = (2 / .2) + (2 / 2)
      12 = (22 + 2) / 2
      13 = (22 / 2) + 2
      14 = (2 / .2) + 2 + 2
      15 = (2 + (2 / 2)) / .2
      16 = (2 + 2) × (2 + 2)
      17 = ???

      So we can’t express 17 using four 2’s. But as we can express 15 using four 2’s that means we can certainly express 17 using five 2’s:

      17 = ((2 + (2 / 2)) / .2) + 2

      But the question asks us to express it without using addition or multiplication:

      17 = 22 − ((2 / 2) / .2)
      17 = 22 − ((2 / .2) / 2)

      Like

  • Unknown's avatar

    Jim Randell 10:03 am on 28 December 2021 Permalink | Reply
    Tags: by: G H Dickson   

    Brain-Teaser 894: Prime consideration 

    From The Sunday Times, 24th September 1978 [link]

    At our local the other night I made the acquaintance of a chap called Michael and his wife Noelle. We talked a good bit about our respective families, our activities and our hobbies. When I happened to mention my interest in mathematical puzzles to Michael he said that he knew one at first hand which might give me some amusement. He proceeded to tell me that although he himself, his parents (who were born in different years), Noelle and their children (featuring no twins, triplets, etc.) had all been born in the nineteen-hundreds and none of them in a leap year, the numerical relationship between their years of birth was nevertheless in two respects a bit unusual.

    “In the first place”, he said, “just one of us has our year of birth precisely equal to the mean of all the others’ years of birth. But more remarkably the difference between my father’s year of birth and that of any one of the rest of us is a prime, and the same is true of that of my mother. And she, like Noelle here, had no child after she had passed her twenties”.

    And then with a grin he concluded, “So now you’ll know about the whole family and even, if you want, be able to figure out just how old Noelle is without having to be rude and ask her!”

    In which year was Noelle born? And how many children does she have?

    This puzzle is included in the book The Sunday Times Book of Brain-Teasers: Book 1 (1980). The puzzle text above is taken from the book.

    [teaser894]

     
    • Jim Randell's avatar

      Jim Randell 10:03 am on 28 December 2021 Permalink | Reply

      There are no multiple births for Noelle, but she could manage to have 2 children in a calendar year (by having one early in the year, and one late in the year).

      Also, if she was born at the end of the year (as is suggested by her name), it is possible to squeeze a child (or two) in during the calendar year containing her 30th birthday.

      In order to get a unique solution, we need to assume Michael and Noelle have more than 1 child (justified by his use of “children”).

      This Python program runs in 52ms.

      Run: [ @replit ]

      from enigma import (defaultdict, irange, Primes, subsets, div, printf)
      
      # check for leap years
      is_leap = lambda y: y % 4 == 0 and (y % 100 != 0 or y % 400 == 0)
      
      # primes less than 100
      primes = Primes(100)
      
      # find possible 19xx years
      years = list(y for y in irange(1900, 1978) if not is_leap(y))
      
      # look for viable mother -> children maps
      kids = defaultdict(list)
      for (m, c) in subsets(years, size=2):
        k = c - m
        if 16 < k < 31:
          kids[m].append(c)
      
      # choose a year for M's mother
      for (MM, Ms) in kids.items():
        # all other years must have a prime difference to MM
        ys1 = set(y for y in years if abs(y - MM) in primes)
      
        # find a viable birth year for M
        for M in Ms:
          if not (M in ys1): continue
      
          # and for his father
          for MF in ys1:
            k = M - MF
            if not (k > 15 and k in primes): continue
            # all other years must also have a prime difference to MF
            ys2 = set(y for y in ys1 if abs(y - MF) in primes).difference([M, MF])
      
            # now find a year for N
            for N in ys2:
              ks = sorted(ys2.intersection(kids.get(N, [])))
              if not ks: continue
      
              # no multiple births, so (0, 1, 2) children in each year
              for ns in subsets((0, 1, 2), size=len(ks), select="M"):
                k = sum(ns)
                if k < 2: continue
                # ages
                ages = [MF, MM, M, N]
                for (n, v) in zip(ns, ks):
                  if n: ages.extend([v] * n)
                t = sum(ages)
                # exactly one of the birth years is the mean year
                m = div(t, len(ages))
                if m is None or ages.count(m) != 1: continue
      
                # output solution
                printf("MF={MF} MM={MM} -> M={M}; N={N} -> {k} kids; {ages} -> {m}")
      

      Solution: Noelle was born in 1943. She has 4 children.

      Michael’s father was born in 1900 (which was not a leap year), and his mother in 1902.

      Michael was born in 1931 (prime differences of 31 and 29 to his father and mother), and his mother was 28 or 29 when he was born.

      Noelle was born in 1943 (prime differences of 43 and 41 to Michael’s father and mother), towards the end of the year.

      Her four children were born in 1961 (one towards the beginning of the year, when Noelle was 17, and one towards the end of the year, when she was 17 or 18), and in 1973 (one towards the beginning of the year, when Noelle was 29, and one towards the end of the year, when she was still 29).

      Like

  • Unknown's avatar

    Jim Randell 8:11 am on 23 September 2021 Permalink | Reply
    Tags: by: G H Dickson   

    Brain-Teaser 855: Pity the poor postman 

    From The Sunday Times, 4th December 1977 [link]

    Extract (genuine!) from a national daily, 27th January 1977:

    Pity the poor postman trying to deliver letters along Stonebow Road in the village of Drake’s Broughton, in north-west England. Due to local government confusion the road boasts five houses with the number 1, four others are number 2, three have number 4, and two are numbered 6.

    To add to the postman’s woes there are four families called Davies in Stonebow Road, plus two named Bridges, three named Barker, and two named Webb.

    On the unwarranted supposition that:

    (i) the occupants of the said houses included all of the said families; but
    (ii) the postman’s problem was somewhat alleviated by the fact that no two families of the same name had the same house-number; and
    (iii) the house-numbers of the Webbs totalled to more than did those of the Bridges, while those of all the families with two of the four names totalled the  same as did those of all the families with the other two names.

    What were the house-numbers of the Barkers and Webbs respectively?

    This puzzle is included in the book The Sunday Times Book of Brain-Teasers: Book 1 (1980). The puzzle text above is taken from the book.

    [teaser855]

     
    • Jim Randell's avatar

      Jim Randell 8:11 am on 23 September 2021 Permalink | Reply

      This Python program runs in 49ms.

      Run: [ @replit ]

      from enigma import (multiset, subsets, partitions, printf)
      
      # the pool of house numbers
      ns = multiset.from_pairs([(1, 5), (2, 4), (4, 3), (6, 2)])
      
      # choose 2 house numbers for the Bridges
      for Brs in subsets(ns.keys(), size=2):
        sBrs = sum(Brs)
      
        # choose 2 house number for the Webbs
        ns1 = ns.difference(Brs)
        for Ws in subsets(ns1.keys(), size=2):
          sWs = sum(Ws)
          if not (sWs > sBrs): continue
      
          # choose 4 numbers for the Davies
          ns2 = ns1.difference(Ws)
          for Ds in subsets(ns2.keys(), size=4):
            sDs = sum(Ds)
      
            # choose 3 numbers for the Barkers
            ns3 = ns2.difference(Ds)
            for Bas in subsets(ns3.keys(), size=3):
              sBas = sum(Bas)
      
              # consider partitions of the sums ...
              for (p1, p2) in partitions([sBrs, sWs, sDs, sBas], 2):
                # that give the same total
                if sum(p1) == sum(p2):
                  printf("Bridges = {Brs}; Webbs = {Ws}; Davies = {Ds}; Barkers = {Bas} [{p1}, {p2}]")
      

      Solution: The Barkers are at 1, 4, 6. The Webbs are at 1, 4.

      And the total sum of their numbers is 16.

      The Davies are at 1, 2, 4, 6, and The Bridges are at 1, 2.

      The total sum of their numbers is also 16.

      There are house numbers 1, 2, 2 remaining.

      Like

  • Unknown's avatar

    Jim Randell 9:23 am on 22 April 2021 Permalink | Reply
    Tags: by: G H Dickson   

    Brain-Teaser 737: Regular as clockwork 

    From The Sunday Times, 31st August 1975 [link]

    Our old watchmaker works weekdays 9:30am to 5pm as regular as, well, clockwork. I recently took there to be regulated two “8-day” striking clocks – the sort which fully wound will go nearly 8 days before stopping; they were keeping different times and each was wrong by an exact number of minutes per day, i.e. less than an hour in either case.

    He immediately wound the clocks fully, set them to the right time (which was an exact number of minutes after the hour) and put them up on a shelf for observation.

    The next Monday, when he went to take down the clocks to start regulating them, he found both of them just starting to strike 8 o’clock simultaneously, which was some hours plus an exact number of minutes past the correct time.

    What day and exact time was it when he originally set them?

    This puzzle is included in the book The Sunday Times Book of Brain-Teasers: Book 1 (1980). The puzzle text above is taken from the book.

    [teaser737]

     
    • Jim Randell's avatar

      Jim Randell 9:24 am on 22 April 2021 Permalink | Reply

      A clock that gained 1 hour a day would take 12 days (or 12.5 days clock time) to show the right time (but actually be 12 hours fast). Similarly a clock that lost 1 hour a day would take 12 days (or 11.5 day clock time) to show the right time (but actually be 12 hours slow).

      And the clocks we are interested would run out long before they achieved this.

      But if we look at both the clocks it would only take 6 days for them to both show the same time (i.e. have a difference of 12 hours between them).

      This would be achievable with the clocks in the puzzle.

      If the clocks were set at 2 o’clock on Tuesday afternoon, then at 2pm on the following Monday they would both read 8 o’clock (one of them having gained 6 hours, and the other having lost 6 hours). So the puzzle seems reasonable, and the solution is probably close to this, although the clocks we have to consider must only gain or lost at most 59 minutes a day.

      We are interested in when the difference between the clocks is a multiple of 12 hours. For clocks that show a difference of d minutes per day, the time t at which they show a difference that is a multiple k of 12 hours is:

      t = k × 720 × 1440 / d

      We know d is in the range [1, 118], t is less than 8 days. So:

      t < 8 × 1440
      ⇒ 720k < 8d
      ⇒ 90k < d

      Hence k = 1 and d is in the range [91, 118], and t is an exact number of minutes.

      This Python program examines possible (t, d) values, and eliminates t values that make impossible to finish on a Monday. It then looks for gain/loss values for the clocks that give an exact number of minutes when they are both showing the same time, give a start time that is during working hours. It runs in 47ms.

      Run: [ @replit ]

      from enigma import (irange, divisors_pairs, div, sprintf, fdiv, printf)
      
      # working in minutes
      R = 12 * 60  # repeat period of clocks
      D = 24 * 60  # minutes in a day
      W = 7 * D  # minutes in a week
      
      # work hours (9:30am - 5:00pm, Mon(= 0) to Fri(= 4)
      work = list([570 + x, 1020 + x] for x in irange(0, 4 * D, step=D))
      
      # check if time is during work hours
      def check(t):
        t %= W
        return any(x <= t <= y for (x, y) in work)
      
      def fmt(m):
        (d, m) = divmod(m % W, D)
        day = ("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun")[d]
        (h, m) = divmod(m, 60)
        return sprintf("{day} {h:02d}:{m:02d}")
      
      # find valid (d, t) pairs
      for (d, t) in divisors_pairs(R * D, every=1):
        if d < 91: continue
        if d > 118: break
      
        # calculate start window, for a finish during Monday's work hours
        a = (work[0][0] - t) % W
        b = (work[0][1] - t) % W
        if not (check(a) or check(b)): continue
      
        # look for times separated by d that give integer start times
        for x in irange(59, -59, step=-1):
          y = x - d
          if y < -59: break
      
          # calculate the time differences
          dy = div(t * (D + y), D)
          if dy is None: continue
      
          # clock Y is slow and showing 8am on Monday (= 480)
          # find out when it was set
          t0 = (480 - dy) % W
          if not check(t0): continue
      
          # output solution
          printf("start = {t0} [end = {end}; d={d}m t={t:g}d; x={x}m y={y}m]", t0=fmt(t0), end=fmt(t0 + t), t=fdiv(t, D))
      

      Solution: The clocks were originally set on Monday at 9:48am.


      The difference in the time the clocks show is 100 minutes per day, so after 7.2 days they are different by 720 minutes = 12 hours.

      One clock gains 45 minutes per day, and the other loses 55 minutes per day.

      So after 7.2 days the fast clock has gained 324 minutes (so it thinks it has been running for 7.425 days), and the slow clock has lost 396 minutes (so it thinks it has been running for 6.925 days).

      The slow clock is showing 8am, but it is actually 6h36m later than that, i.e. 2:36pm.

      And the fast clock is showing 8pm, but it is actually 5h24m earlier than that, i.e. 2:36pm.

      So the clocks are showing the same time at 2:36pm on Monday (which is during working hours), so they must have been set 7.2 days before this, i.e. one week and 4h48m earlier = 9:48am the previous Monday (also during working hours).

      Like

    • Frits's avatar

      Frits 10:26 pm on 22 April 2021 Permalink | Reply

      from enigma import div
      
      # between Friday 17:00 - Monday 09:30 there are 3870 minutes
      # between Monday 09:30 - Monday 17:00 there are 3870 + 6660 minutes
      
      # assume 3870 + M minutes have gone by 
      # number of days passed = (3870 + M) / 1440
      
      # loop over clock minutes running too slow or too fast
      for X in range(1, 60):
        for W in range(1, 60):
          # for variables x, w use values -1, 1 for sign of resp. numbers X and W 
          for x in [-1, 1]:
            for w in [-1, 1]:
              # avoid duplicate solutions
              if x * X >= w * W: continue
             
              # clocks strike at the same time 
              # 480 + X * no_days   (08:00)   or    1200 - X * no_days   (20:00)
              
              # (3 * x + 7) * 120  - x * X * (3870 + M) / 1440 == \
              # (3 * w + 7) * 120  - w * W * (3870 + M) / 1440",
              
              # calculate minutes
              M = div(518400 * (w - x) - (w * W - x * X) * 3870, w * W - x * X)
              if M is None: continue
              
              # maximum range Monday 09:30 - Monday 17:00
              if M > 6660: continue
              
              # gain has to be a whole number
              gain = div(X * (3870 + M),  1440)
              if gain is None: continue
              
              # time = real time (in minutes) the clocks strikes at the same time
              # "480 + gain" or "1200 - gain"
              time = (3 * x + 7) * 120  - x * gain
              
              # clocks were set (3870 + M) / 1440 days before
              # 9:30 = 570 minutes,  17:00 = 1020 minutes
              if not(570 <= (1440 + time - (3870 + M)) % 1440 <= 1020): continue
              
              days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
              
              h = (time - (3870 + M) % 1440) // 60
              m = (time - (3870 + M) % 1440) % 60
              
              d = (3870 + M) // 1440
              day = days[7 - d] 
             
              print(f"day = {day}, exact time {h}:{m}")
      

      Like

  • Unknown's avatar

    Jim Randell 9:52 am on 19 September 2019 Permalink | Reply
    Tags: by: G H Dickson   

    Brain-Teaser 501: [Missing weight] 

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

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

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

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

    What was the retailers missing weight?

    This puzzle was originally published with no title.

    [teaser501]

     
    • Jim Randell's avatar

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

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

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

      This Python program runs in 95ms.

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

      Solution: The missing weight is 9 kg.

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

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

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

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

      Like

  • Unknown's avatar

    Jim Randell 11:58 am on 30 July 2019 Permalink | Reply
    Tags: by: G H Dickson   

    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 8:01 am on 11 April 2019 Permalink | Reply
    Tags: by: G H Dickson   

    Brain-Teaser 470: Jacob’s ladder 

    From The Sunday Times, 31st May 1970 [link]

    Joseph’s garage, built at ground level on to the side wall of his house, had uniform external dimensions of (exactly) 10 ft. high by 10 ft. wide.

    Wishing to paint from the outside a top-floor window-frame over the garage, he positioned his longest ladder (whose length was over 30 ft.) with its foot on the ground at such a distance from the garage that its top rested against the house wall at the maximum height possible.

    Discovering, however, that despite this he could not reach up to the window, he borrowed his neighbour Jacob’s ladder and, positioning it similarly, found that he could now reach comfortably.

    With either ladder the length, distance and height referred to were all integral numbers of inches.

    How much longer was Jacob’s ladder than Joseph’s, and how much higher on the wall did it reach?

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

    [teaser470]

     
    • Jim Randell's avatar

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

      For a ladder of length k, the maximum height we could achieve would be k, if we laid it flat against the wall, but we can’t do that because there is a garage in the way. If we position it at some distance away from the garage, so that it reaches over the garage we find that as we move the foot of the ladder towards the garage the other end will reach higher up the wall, until the garage gets in our way.

      If the foot of the ladder is at a distance d from the wall, and a height h up the wall, and touches the garage at a point 120 inches from the wall and 120 inches above the ground, then:

      h = 120d / (d − 120)

      and the length of the ladder k is given by:

      k = √(d² + h²)

      This program increases d (in inches from 120) looking for integer heights with integer length ladders.

      Run: [ @repl.it ]

      from enigma import (irange, is_square, printf)
      
      # consider increasing values for d > 120
      for d in irange(121, 240):
      
        # calculate the corresponding height h
        (h, r) = divmod(120 * d, d - 120)
        if r != 0: continue
      
        # calculate the length of the ladder
        k = is_square(d * d + h * h)
        if k is None: continue
        # ladder must be longer than 30 ft
        if not (k > 360): continue
      
        printf("ladder length = {k}, distance = {d}, height = {h}")
      

      Solution: Jacob’s ladder was 4 ft. 3 in. longer than Joseph’s, and reached 5 ft. 3 in. higher.

      In the diagram:

      Jacob’s ladder (blue) is 442 inches long (= 36 ft. 10 in.), and reaches a height of 408 inches (= 34 ft.) on the wall.

      Joseph’s ladder (red) is 391 inches long (= 32 ft. 7 in.) and reaches a height of 345 inches (= 28 ft. 9 in.) on the wall.

      There is a further possible ladder (green) which is 350 inches (= 29 ft. 2 in.) and would reach a height of 280 inches (= 23 ft. 4 in.) on the wall, but this ladder is not longer than 30 ft.

      We can also swap the distance and height to position the ladders, but this results in a maximum distance rather than a maximum height achieved.

      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