Tagged: by: E T Tweddell Toggle Comment Threads | Keyboard Shortcuts

  • Unknown's avatar

    Jim Randell 10:32 am on 6 July 2023 Permalink | Reply
    Tags: by: E T Tweddell   

    Brain-Teaser 900: World Cup goal scorers 

    From The Sunday Times, 5th November 1978 [link]

    The Soccotia World Cup soccer squad consists of two goalkeepers and sufficient outfield players to ensure that each of these latter play in exactly two games, of the three scheduled. Each player is also allocated a consecutive number starting with one, including the goalkeepers. Each outfield player is equally capable of playing in defence and attack, but will not change from one role to another during the same game.

    The manager selects the teams for each match such that the sum of the numbers of the outfield players remains constant for each game, and such that the sum of the numbers of the four defenders equals one half of the sum of the six attackers.

    In each game Soccotia scored one goal, each of which was scored by an attacking player, three different players  scoring one goal each.

    In the first game, the goal resulted from a five man move involving four passes. The move was started by a defender, who was the only defender in the move. Each pass was made to a player whose number was a fixed integer multiple of the passer.

    In the second game, the same four players were chosen to play in defence as in the first game, and the same defender started the five man/four pass move which led to the goal scored in this game. This time however the number of each player receiving the ball exceeded the number of the passer by a fixed integer.

    In the third game the five man/four pass move leading to the goal followed the same pattern as that scored in the second game.

    What were the numbers of the goalscorers in match order?

    News

    There are now 900 Teaser puzzles available on the site, so I thought it appropriate to post Teaser 900.

    [teaser900]

     
    • Jim Randell's avatar

      Jim Randell 10:32 am on 6 July 2023 Permalink | Reply

      In each match the team consists of 11 players (1 goalkeeper, 4 defenders, 6 attackers).

      In the 3 games with 30 slots for outfield (= non-goalkeeper) players, each member of the squad fills 2 slots, so there are 15 outfield members, and 17 members of the squad in total. So they are numbered from 1-17.

      This Python program starts by forming possible geometric and arithmetic sequences from the available numbers, and then selects attackers and defenders for each match based on the specified requirements. Once we have 3 matches we check there are 2 unused numbers for the goalkeepers, and then determine the scorers in each match.

      The program runs in 296ms.

      from enigma import (irange, subsets, repeat, div, multiset, printf)
      
      # numbers 1 .. 17
      ns = set(irange(1, 17))
      
      # form possible geometric and arithmetic sequences
      gseqs = list()
      aseqs = list()
      # consider the first 2 terms
      for (a, b) in subsets(sorted(ns), size=2):
        # geometric?
        n = div(b, a)
        if n:
          ss = tuple(repeat((lambda x: x * n), a, 4))
          if ns.issuperset(ss): gseqs.append(ss)
        # arithmetic?
        n = b - a
        ss = tuple(repeat((lambda x: x + n), a, 4))
        if ns.issuperset(ss): aseqs.append(ss)
      
      # choose a geometric sequence for the first game
      for seq1 in gseqs:
        # the sequence consists of 1d + 4a
        (d1, a1s) = (seq1[0], seq1[1:])
        # choose 2 more attackers to give an even sum (= 2t)
        for atts1 in subsets(ns.difference(seq1), size=2, fn=set):
          atts1.update(a1s)
          t = div(sum(atts1), 2)
          if t is None: continue
          # choose 3 defenders to bring their total to t
          for defs1 in subsets(ns.difference(atts1, {d1}), size=3, fn=set):
            defs1.add(d1)
            if sum(defs1) != t: continue
      
            # in the second game we have the same 4 defenders
            defs2 = defs1
            h2 = sum(defs2)
            # find an arithmetic sequence that starts with d1 ...
            for seq2 in aseqs:
              if seq2[0] != d1: continue
              # and ends in an attacker
              a2 = seq2[-1]
              if a2 == seq1[-1] or a2 in defs2: continue
              # any player in the sequence that is not a defender is an attacker
              a2s = set(seq2).difference(defs2)
              # find more attackers to give a sum of 2 * t
              for atts2 in subsets(ns.difference(defs2, a2s), size=6 - len(a2s), fn=set):
                atts2.update(a2s)
                if sum(atts2) != 2 * t: continue
      
                # find out who has already played twice
                m = multiset.from_seq(defs1, atts1, defs2, atts2)
                p2s = set(k for (k, v) in m.items() if v == 2)
                # find an arithmetic sequence for game 3 that doesn't involve p2s
                for seq3 in aseqs:
                  if not p2s.isdisjoint(seq3): continue
                  # the sequence starts with a defender and ends with an attacker
                  a3 = seq3[-1]
                  if a3 == seq1[-1] or a3 == seq2[-1]: continue
                  d3 = seq3[0]
                  # choose 3 more defenders to bring the sum to t
                  for defs3 in subsets(ns.difference(p2s, {d3, a3}), size=3, fn=set):
                    defs3.add(d3)
                    if sum(defs3) != t: continue
                    # any player in the sequence that is not a defender is an attacker
                    a3s = set(seq3).difference(defs3)
                    # find more attackers to give a sum of 2 * h3
                    for atts3 in subsets(ns.difference(p2s, defs3, a3s), size=6 - len(a3s), fn=set):
                      atts3.update(a3s)
                      if sum(atts3) != 2 * t: continue
      
                      # find the goalkeepers (not involved in any match so far)
                      gs = ns.difference(defs1, atts1, defs2, atts2, defs3, atts3)
                      if len(gs) != 2: continue
                      # find the scorers
                      ss = (seq1[-1], seq2[-1], seq3[-1])
      
                      # output solution
                      fmt = sorted
                      printf("1: defs={defs1} atts={atts1} {seq1}", defs1=fmt(defs1), atts1=fmt(atts1))
                      printf("2: defs={defs2} atts={atts2} {seq2}", defs2=fmt(defs2), atts2=fmt(atts2))
                      printf("3: defs={defs3} atts={atts3} {seq3}", defs3=fmt(defs3), atts3=fmt(atts3))
                      printf("goalies = {gs}", gs=fmt(gs))
                      printf("scorers = {ss}")
                      printf()
      

      Solution: The goalscorers were: 16, 9, 8.


      The squad for the first match was:

      1: defenders = (1, 3, 11, 13); attackers = (2, 4, 8, 12); sequence = 1 → 2 → 4 → 8 → 16

      This is the only possible geometric sequence using the allowed numbers.

      The numbers of the defenders sum to 28, and the numbers of the attackers sum to 56.

      The squad for the second match was:

      2: defenders = (1, 3, 11, 13); attackers = (5, 6, 7, 9, 14, 15); sequence = 1 → 3 → 5 → 7 → 9

      And the squad for the third match was one of the following:

      3: defenders = (2, 4, 6, 16); attackers = (5, 7, 8, 9, 13, 15); sequence = 4 → 5 → 6 → 7 → 8
      3: defenders = (2, 4, 7, 15); attackers = (5, 6, 8, 9, 12, 16); sequence = 4 → 5 → 6 → 7 → 8
      3: defenders = (4, 5, 7, 12); attackers = (2, 6, 8, 9, 15, 16); sequence = 4 → 5 → 6 → 7 → 8

      Each of the outfield player has played in 3 matches, and the remaining members of the squad, 10 and 17, are the goalkeepers.

      The goal scorers are the final players in the three sequences: 16, 9, 8.

      Like

    • Frits's avatar

      Frits 8:22 pm on 6 July 2023 Permalink | Reply

      from itertools import combinations
      
      N = 17
      
      # return all arithmetic sequences in sorted seq, len=5 [x, k + x, ... , 4k + x]
      def ametric(seq): 
        for x in seq[:-4]:
          for k in range(1, 5):
            if 4 * k + x > seq[-1]: break 
            if all(x + i * k in seq for i in range(5)):
              yield (x, 4 * k + x)                             # yield first and last
              
      # decompose <t> into <n> different numbers, min/max, excluding <xs> elements 
      def decompose(t, n, xs, m=1, M=17, s=[]):
        if n == 1:
          if m <= t <= M and t not in xs:
            yield s + [t]
        else:
          # still n - 1 numbers to follow with minimal sum m+1 + m+2 + .. + m+n-1
          # or (n - 1)m + n(n-1)/2  
          for x in range(m, min(M + 1, t - (n - 1) * m + n * (n - 1 ) // 2 + 1)):
            if x not in xs:
              yield from decompose(t - x, n - 1, xs, x + 1, M, s + [x])
              
         
      # round 1: defs = [fd, x, y, z], atts = {k*fd, k**2fd, k**3fd, k**4fd, a, b}
      # geometric sequences
      for fd, geo in [(fd, {fd * m**i for i in range(5)}) 
                      for fd in range(1, int(N**.25) + 1) 
                      for m in range(2, int((N / fd)**.25) + 1)]: 
        s1 = max(geo)                                             # scorer in round 1
        # choose 2 remaining attackers in round 1           
        for a, b in combinations(set(range(1, N + 1)).difference(geo), 2):
          if (a + b) % 2: continue                                    # a + b is even
          atts_1 = geo.difference([fd]) | {a, b}
          sum_atts = sum(atts_1)
          # can we make defender sum (minus fd) from choosing 3 from leftovers?
          for d in decompose(sum_atts // 2 - fd, 3, {fd} | atts_1):
            d = {fd} | set(d)
            sumd = sum(d)
            
            # make an arithmetic sequence [fd, k + fd, ... , 4k + fd]
            for k in range(1, 5):
              # different scorer must be an attacker
              if (s2 := 4 * k + fd) == s1 or s2 in d: continue 
              # already known attackers in round 2  
              atts_2_1 = set(fd + i * k for i in range(5)).difference(d)
              # only one attacker played in both round 1 and round 2
              # so exactly 10 outfield players remain for round 3
              if len(both := atts_1 & atts_2_1) > 1: continue
      
              # choose remaining attackers in round 2
              for d2 in decompose(sum_atts - sum(atts_2_1), 6 - len(atts_2_1), 
                                  d | atts_2_1 | (atts_1 if both else set())):
                atts_2 = atts_2_1 | set(d2)
                # only one attacker played in both round 1 and round 2
                if len(p11 := atts_1 | atts_2) != 11: continue
            
                # pick players who played only one game in round 1 and 2
                p3 = sorted(p for p in p11 if p not in atts_1 or p not in atts_2)
                # sum of the numbers of the outfield players remains constant 
                if sum(p3) != 3 * sumd: continue
      
                # build list of possible defenders
                defss = list(decompose(sumd, 4, set(range(1, N + 1)).difference(p3)))
               
                # can we make an arithmetic sequence [x, k + x, ... , 4k + x]?
                for (f, s3) in ametric(p3):
                  # three different players scoring one goal each
                  if s3 in {s1, s2}: continue
                  # the sequence starts with a defender and ends with an attacker
                  if any(s3 not in defs and f in defs for defs in defss): 
                    print(f"answer: {s1}, {s2} and {s3}")    
      

      Like

  • Unknown's avatar

    Jim Randell 7:58 am on 3 May 2022 Permalink | Reply
    Tags: by: E T Tweddell   

    Brain-Teaser 693: Ready … 

    From The Sunday Times, 27th October 1974 [link]

    The Phytteness School marathon attracted 16 entrants this year. Each of the five houses entered a team of three runners, and the field was made up by the maths master, Des Chappelle. The school houses were competing for the trophy. The number of points by each entrant would be equal to his finishing position.

    The five houses tied for the cup, their totals being equal, although no two competitors tied for the same position. In order to determine the order in which the houses would hold the cup (they had agreed to hold it for 73 days each), they multiplied the finishers’ positions together in each house. The house with the smallest product, Black, would hold the cup first and so on to the house with the largest product, Blue, who hold it last. Unfortunately, Green and White houses still tied, and had to be separated by the toss of a coin.

    Des noted later that no house had had two finishers in consecutive positions, although Green house would have achieved this had he not managed to get between two of their runners right on the line.

    In what positions did the Red house runners finish?

    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.

    [teaser693]

     
    • Jim Randell's avatar

      Jim Randell 8:00 am on 3 May 2022 Permalink | Reply

      There are T(16) = 136 points available, but Des finished between two of the other runners, so he must have finished with 2 – 15 points. And the remaining positions must be shared between the 5 houses (3 positions each) to give the same sum.

      This Python program chooses a position for Des that give viable possible totals for each house, and then partitions the remaining positions among the houses. The groupings are then sorted by product, and the 3 groups in the middle of the field must have 2 products between them. The group with the unique product are Red.

      The program runs in 59ms (internal run time is 312µs).

      Run: [ @replit ]

      from enigma import (tri, tuples, irange, div, diff, multiply, group, filter2, singleton, printf)
      
      # total number of points
      T = tri(16)
      
      # check increasing integer sequence <s> has no consecutive elements
      check = lambda s: all(y - x > 1 for (x, y) in tuples(s, 2))
      
      # partition the values into <k>-length groups, each sums to <t>
      def partition(vs, k, t, ss=[]):
        if len(vs) == k:
          if sum(vs) == t and check(vs):
            yield ss + [tuple(vs)]
        else:
          v0 = vs[0]
          for (i, v1) in enumerate(vs):
            if i == 0: continue
            v2 = t - (v0 + v1)
            if not (v2 > v1): break
            if v2 in vs:
              s = (v0, v1, v2)
              if check(s):
                yield from partition(diff(vs, s), k, t, ss + [s])
      
      # consider position for D (between 2 others)
      for D in irange(2, 15):
        # calculate points for each house
        H = div(T - D, 5)
        if H is None: continue
      
        # partition the remaining positions into groups of 3
        for ss in partition(diff(irange(1, 16), [D]), 3, H):
          # sort the groups by product (largest first)
          ss.sort(key=multiply, reverse=1)
          # find the products of the middle three (G, W, R)
          p = group(ss[1:-1], by=multiply)
          if len(p.keys()) != 2: continue
          Rs = Ws = Gs = None
          for (k, vs) in p.items():
            if len(vs) == 1:
              # red has a unique product
              Rs = vs[0]
            else:
              # green/white have shared products; green has D - 1 and D + 1
              (Gs, Ws) = filter2((lambda s: D - 1 in s and D + 1 in s), vs, fn=singleton)
          if Rs and Ws and Gs:
            # output solutions
            printf("D={D}; H={H}")
            printf("houses = {ss}")
            printf("-> blue = {ss[0]}")
            printf("-> green = {Gs}")
            printf("-> white = {Ws}")
            printf("-> red = {Rs}")
            printf("-> black = {ss[-1]}")
            printf()
      

      Solution: Red house finished 2nd, 9th, 14th.

      The points awarded were:

      Des = 11
      Blue = (5, 7, 13); sum = 25; product = 455
      Green = (3, 10, 12); sum = 25; product = 360
      White = (4, 6, 15); sum = 25; product = 360
      Red = (2, 9, 14); sum = 25; product = 252
      Black = (1, 8, 16); sum = 25; product = 128

      Like

    • GeoffR's avatar

      GeoffR 10:32 am on 3 May 2022 Permalink | Reply

      
      % A Solution in MiniZinc
      include "globals.mzn";
      
      var 2..15: des;  % Maths master - Des Chappelle
      
      var 1..16: a; var 1..16: b;var 1..16: c;  % Blue's points
      constraint b - a != 1 /\ c - b != 1 /\ b > a /\ c > b;
      
      var 1..16: d; var 1..16: e;var 1..16: f;  % Green's points
      constraint e - d != 1 /\ f - e != 1 /\ e > d /\ f > e;
      
      var 1..16: g; var 1..16: h;var 1..16: i;  % White's points 
      constraint h - g != 1 /\ i - h != 1 /\ h > g /\ i > h;
      
      var 1..16: j; var 1..16: k;var 1..16: l;  % Red's points 
      constraint k - j != 1 /\ l - k != 1 /\ k > j /\ l > k;
      
      var 1..16: m; var 1..16: n;var 1..16: o;  % Black's points
      constraint n - m != 1 /\ o - n != 1 /\ n > m /\ o > n;
      
      % No two competitors tied for the same position
      constraint all_different ([des,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o]);
      
      % The five houses tied for the cup, their totals being equal
      constraint a + b + c == d + e + f /\ a + b + c == g + h + i
      /\ a + b + c == j + k + l /\ a + b + c == m + n + o;
      
      % Black's points have the smallest product
      constraint m * n * o < j * k * l /\  m * n * o < g * h * i
      /\ m * n * o < d * e * f /\ m * n * o < a * b * c;
      
      % Blue's points have the largest product
      constraint a * b * c > d * e * f /\ a * b * c > g * h * i
      /\ a * b * c > j * k * l /\ a * b * c > m * n * o;
      
      % The product of Green's points equals the product of White's points
      constraint d * e * f == g * h * i;
      
      % Location of Des' points in relation to the Green house points
      constraint (des - d == 1 /\ e - des == 1 ) 
      \/ (des - e == 1 /\ f - des == 1);
      
      solve satisfy;
      
      output ["Des = " ++ show(des) ++ "\n" ++
      "Blue:   [a,b,c] = " ++ show([a,b,c]) ++ "\n" ++
      "Green:  [d,e,f] = " ++ show([d,e,f]) ++ "\n" ++
      "White:  [g,h,i] = " ++ show([g,h,i]) ++ "\n" ++
      "Red:    [j,k,l] = " ++ show([j,k,l]) ++ "\n" ++
      "Black:  [m,n,o] = " ++ show([m,n,o]) ];
      
      % Des = 11
      % Blue:   [a,b,c] = [5, 7, 13]
      % Green:  [d,e,f] = [3, 10, 12]
      % White:  [g,h,i] = [4, 6, 15]
      % Red:    [j,k,l] = [2, 9, 14]  <<< Answer
      % Black:  [m,n,o] = [1, 8, 16]
      % ----------
      % ==========
      
      

      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