Tagged: by: Rhombus Toggle Comment Threads | Keyboard Shortcuts

  • Unknown's avatar

    Jim Randell 12:26 pm on 24 June 2021 Permalink | Reply
    Tags: by: Rhombus   

    Brain-Teaser 787: Puzzlers’ office party 

    From The Sunday Times, 15th August 1976 [link]

    Brainbenders and Co., the noted games and puzzles manufacturers, held their office party recently.

    The eight from the planning department shared one round table. Pat Robinson and Ann arrived together. Miss Davis looked sensational in her new dress and Mr Armstrong’s suit was fresh from the cleaners.

    Red-haired John sat on Miss Jones’s right while Mary sat next-but-one to both Miss Brown and Miss Stevens. Joan only had eyes for Mr Evans, opposite her, while her neighbour, Edna, was interested in Fred, who was sitting beside Bill and next-but-one to Miss Stevens.

    Mr Smith was the only man between two girls and Miss Brown the only girl between two fellows. However, only two people sat opposite a person of their own sex.

    What was the seating plan?

    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.

    [teaser787]

     
    • Jim Randell's avatar

      Jim Randell 12:27 pm on 24 June 2021 Permalink | Reply

      I used the [[ SubstitutedExpression ]] solver from the enigma.py library to find viable assignments of first/last names to positions 0 to 7 around the table.

      The following run file finds the assignments of names to positions:

      #! python3 -m enigma -rr
      
      SubstitutedExpression
      
      # we have 8 first names:
      #  Pat, Ann, John, Mary, Joan, Edna, Fred, Bill
      #  A    B    C     D     E     F     G     H
      #
      # and 8 last names:
      #  Robinson, Jones, Davis, Armstrong, Brown, Stevens, Evans, Smith
      #  S         T      U      V          W      X        Y      Z
      --distinct="ABCDEFGH,STUVWXYZ"
      
      # and we need to assign each to a position 0-7
      --base=8
      
      # start with Pat Robinson in position 0
      --assign="A,0"
      --assign="S,0"
      
      # John sat on Jones' right
      "(C + 1) % 8 = T"
      
      # Mary sat next but 1 to Brown and Stevens
      "abs(D - W) in {2, 6}"
      "abs(D - X) in {2, 6}"
      
      # Joan was opposite Evans
      "(E + 4) % 8 = Y"
      
      # Joan was next to Edna
      "abs(E - F) in {1, 7}"
      
      # Fred was next to Bill, and next but 1 to Stevens
      "abs(G - H) in {1, 7}"
      "abs(G - X) in {2, 6}"
      
      # return the positions for each first name and last name
      --answer="((A, B, C, D, E, F, G, H), (S, T, U, V, W, X, Y, Z))"
      

      We are given the genders associated with 7 of the 8 surnames, so only Robinson remains undecided.

      The following Python program takes the output of the above run file, and performs the gender checks. It runs in 59ms.

      Run: [ @replit ]

      from enigma import (SubstitutedExpression, irange, tuples, printf)
      
      # load the solver for the names
      p = SubstitutedExpression.from_file("teaser787.run")
      
      # perform the gender checks
      def check(gs, Smith, Brown):
      
        # only 2 people sat opposite a person of the same gender
        # (i.e. there is exactly 1 pair)
        if not(sum(gs[i] == gs[i + 4] for i in irange(0, 3)) == 1): return False
      
        # find positions of gender X between gender Y
        def between(X, Y):
          for (j, i, k) in tuples(irange(0, 7), 3, circular=1):
            if gs[i] == X and gs[j] == gs[k] == Y:
              yield i
      
        # Smith is the only male between 2 females
        if not(set(between(0, 1)) == {Smith}): return False
        # Brown is the only female between 2 males
        if not(set(between(1, 0)) == {Brown}): return False
      
        # looks OK
        return True
      
      # find solutions for first/last names
      for (s, (fps, lps)) in p.solve(verbose=0):
      
        # assign the genders we know:
        # m = Mr Armstrong, Mr Evans, Mr Smith
        # f = Miss Davis, Miss Jones, Miss Brown, Miss Stevens
        # and choose the remaining value (Robinson)
        for g in (0, 1):
          # map gs: pos -> gender (0=male, 1=female)
          gs = dict(zip(lps, [g, 1, 1, 0, 1, 1, 0, 0]))
          if not check(gs, s['Z'], s['W']): continue
      
          # output solution
          last = dict(zip(lps, ["Robinson", "Jones", "Davis", "Armstrong", "Brown", "Stevens", "Evans", "Smith"]))
          first = dict(zip(fps, ["Pat", "Ann", "John", "Mary", "Joan", "Edna", "Fred", "Bill"]))
          for i in irange(0, 7):
            printf("{i}: ({x}) {first} {last}", i=i + 1, x="mf"[gs[i]], first=first[i], last=last[i])
          printf()
      

      Solution: The seating plan is (clockwise from Pat Robinson):

      1: Pat Robinson (f)
      2: Fred Armstrong (m)
      3: Bill Evans (m)
      4: Ann Brown (f)
      5: John Smith (m)
      6: Mary Jones (f)
      7: Joan Davis (f)
      8: Edna Stevens (f)

      Like

      • Jim Randell's avatar

        Jim Randell 4:03 pm on 24 June 2021 Permalink | Reply

        Or with all the code in a single file:

        from enigma import SubstitutedExpression, irange, tuples, printf
        
        # perform the gender checks
        def check(ns, gs, Smith, Brown):
          # map d: pos -> gender (0=male, 1=female)
          d = dict(zip(ns, gs))
        
          # only 2 people sat opposite a person of the same gender
          # (i.e. there is exactly 1 pair)
          if not(sum(d[i] == d[i + 4] for i in irange(0, 3)) == 1): return False
        
          # find positions of gender X between gender Y
          def between(X, Y):
            for (j, i, k) in tuples(irange(0, 7), 3, circular=1):
              if d[i] == X and d[j] == d[k] == Y:
                yield i
        
          # Smith is the only male between 2 females
          if not(set(between(0, 1)) == {Smith}): return False
          # Brown is the only female between 2 males
          if not(set(between(1, 0)) == {Brown}): return False
        
          # looks OK
          return True
        
        # we have 8 first names:
        #  Pat, Anne, John, Mary, Joan, Edna, Fred, Bill
        #  A    B     C     D     E     F     G     H
        #
        # and 8 last names:
        #  Robinson, Jones, Davis, Armstrong, Brown, Stevens, Evans, Smith
        #  S         T      U      V          W      X        Y      Z
        p = SubstitutedExpression([    
            "(C + 1) % 8 = T",  # John sat on Jones' right
            "abs(D - W) in {2, 6}",  # Mary sat next but 1 to Brown ...
            "abs(D - X) in {2, 6}",  # ... and Stevens
            "(E + 4) % 8 = Y",  # Joan was opposite Evans ...
            "abs(E - F) in {1, 7}",  # ... and next to Edna
            "abs(G - H) in {1, 7}",  # Fred was next to Bill ...
            "abs(G - X) in {2, 6}",  # ... and next but 1 to Stevens
            "check([S, T, U, V, W, X, Y, Z], [N, 1, 1, 0, 1, 1, 0, 0], Z, W)", # gender checks
          ],
          distinct=("ABCDEFGH", "STUVWXYZ"),
          base=8,  # assign each name a position 0-7
          s2d=dict(A=0, S=0),  # start with Pat Robinson in position 0
          d2i=dict((d, 'N') for d in irange(2, 7)),
          env=dict(check=check),
          answer="((A, B, C, D, E, F, G, H), (S, T, U, V, W, X, Y, Z), N)",
          verbose=0
        )
        
        # find solutions for first/last names, and Robinson's gender
        for (s, (fps, lps, g)) in p.solve():
          # output solution
          gs = dict(zip(lps, [g, 1, 1, 0, 1, 1, 0, 0]))
          last = dict(zip(lps, ["Robinson", "Jones", "Davis", "Armstrong", "Brown", "Stevens", "Evans", "Smith"]))
          first = dict(zip(fps, ["Pat", "Anne", "John", "Mary", "Joan", "Edna", "Fred", "Bill"]))
          for i in irange(0, 7):
            printf("{i}: ({x}) {first} {last}", i=i + 1, x="mf"[gs[i]], first=first[i], last=last[i])
          printf()
        

        Like

      • Frits's avatar

        Frits 11:30 am on 1 July 2021 Permalink | Reply

        Adding the following to the run member limits the possibilities to one.

        # Smith is the only male between 2 females
        # this must be John as Fred was next to Bill
        "C == Z",
        
        # Brown is the only female between 2 males
        # so Brown must be next to John
        "abs(C - W) in {1, 7} and (abs(G - W) in {1, 7} or abs(H - W) in {1, 7})"
        
        # only 2 people sat opposite a person of the same gender
        # so all males didn't sit opposite each other
        "4 not in [abs(C - G), abs(C - H)]"
        
        # male surnames are Armstrong, Evans and Smith
        "sorted([C, G, H]) == sorted([V, Y, Z])"
        

        Like

        • Jim Randell's avatar

          Jim Randell 2:36 pm on 1 July 2021 Permalink | Reply

          I wasn’t sure if the setter intended us to infer gender from first names (although clearly “Pat” is deliberately ambiguous).

          But it turns out that it is not necessary to do so to solve the puzzle, so I didn’t.

          Like

  • Unknown's avatar

    Jim Randell 7:16 am on 15 June 2021 Permalink | Reply
    Tags: by: Rhombus   

    Brain-Teaser 776: Christmas shopping 

    From The Sunday Times, 30th May 1976 [link]

    My three nieces Anne, Betty and Carole came to stay with me just before Christmas. When they arrived they handed over their “present” money, and as I wrote down the amounts (in pence) I noticed that they were 3-digit numbers  using all nine digits (zero excluded) and that Anne had more than Betty and Carole had as much as the other two together.

    I drove the girls into town to shop and as they entered the car to return home they again asked me to look after their money. As I jotted down the three  amounts I noticed that they were 3-digit numbers using all nine digits as before.

    Before I drove off they wanted to know how much each had spent. As I told them these amounts I was struck by the fact that they were 3-digit numbers again using all nine digits. I also added that Carole had spent exactly three-fifths of her money while Anne had spent a little more than three-fifths of hers.

    How much did the three girls have for the rest of their stay?

    This puzzle was included in the book The Sunday Times Book of Brain-Teasers: Book 1 (1980, edited by Victor Bryant and Ronald Postill). The puzzle text above is taken from the book.

    [teaser776]

     
    • Jim Randell's avatar

      Jim Randell 7:19 am on 15 June 2021 Permalink | Reply

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

      The following run file executes in 85ms.

      Run: [ @replit ]

      #! python3 -m enigma -rr
      
      SubstitutedExpression
      
      --digits="1-9"
      --distinct="ABCDEFGHI,JKLMNPQRS,TUVWXYZab"
      
      # initial amounts: Anne = ABC; Betty = DEF; Carole = GHI
      "{A} > {D}"  # ABC > DEF
      "{GHI} - {ABC} = {DEF}"  # GHI = ABC + DEF
      
      # final amounts: Anne = JKL; Betty = MNP; Carole = QRS
      # amounts spent: Anne = TUV; Betty = WXY; Carole = Zab
      "{ABC} - {TUV} = {JKL}"
      "{DEF} - {WXY} = {MNP}"
      "{GHI} - {Zab} = {QRS}"
      
      # Carole had spent 3/5 of her money
      "div(3 * {GHI}, 5) = {Zab}"
      
      # Anne had spent a little more than 3/5 of hers (say: > 60%, < 65%)
      "0.60 < fdiv({TUV}, {ABC}) < 0.65"
      
      # the answer is the final amounts
      --answer="({JKL}, {MNP}, {QRS})"
      

      Solution: The remaining amounts are: Anne = 245p; Betty = 169p; Carole = 378p.

      The initial amounts are:

      Anne: 627p
      Betty: 318p
      Carole: 945p

      And the amounts spent are:

      Anne: 382p (60.9%)
      Betty: 149p (46.9%)
      Carole: 567p (60.0%)

      Like

    • GeoffR's avatar

      GeoffR 10:27 am on 15 June 2021 Permalink | Reply

      
      % A Solution in MiniZinc 
      include "globals.mzn";
      
      % using same notations as Jim's solution 
      % starting amounts - Anne, Betty and Carole
      var 1..9:A; var 1..9:B; var 1..9:C;  
      var 1..9:D; var 1..9:E; var 1..9:F;
      var 1..9:G; var 1..9:H; var 1..9:I;
      var 100..999:ABC = 100*A + 10*B + C; % Anne
      var 100..999:DEF = 100*D + 10*E + F; % Betty
      var 100..999:GHI = 100*G + 10*H + I; % Carole
      
      var set of int: start = {A,B,C,D,E,F,G,H,I};
      constraint start == {1,2,3,4,5,6,7,8,9};
      
      % Anne had more than Betty and 
      % Carole had as much as the other two together.
      constraint ABC > DEF /\ GHI == ABC + DEF;
      
      % final amounts - Anne, Betty and Carole
      var 1..9:J; var 1..9:K; var 1..9:L;
      var 1..9:M; var 1..9:N; var 1..9:P;
      var 1..9:Q; var 1..9:R; var 1..9:S;
      var 100..999:JKL = 100*J + 10*K + L; % Anne
      var 100..999:MNP = 100*M + 10*N + P; % Betty
      var 100..999:QRS = 100*Q + 10*R + S; % Carole
      
      var set of int: final = {J,K,L,M,N,P,Q,R,S};
      constraint final == {1,2,3,4,5,6,7,8,9};
      
      % amounts spent - Anne, Betty and Carole
      var 1..9:T; var 1..9:U; var 1..9:V;
      var 1..9:W; var 1..9:X; var 1..9:Y;
      var 1..9:Z; var 1..9:a; var 1..9:b;
      var 100..999:TUV = 100*T + 10*U + V; % Anne
      var 100..999:WXY = 100*W + 10*X + Y; % Betty
      var 100..999:Zab = 100*Z + 10*a + b; % Carole
      
      var set of int: spent ={T,U,V,W,X,Y,Z,a,b};
      constraint spent == {1,2,3,4,5,6,7,8,9};
      
      % for Anne, Betty and Carole, amount_left = starting_amount - amount_spent
      constraint ABC - TUV == JKL
      /\ DEF - WXY == MNP /\ GHI - Zab == QRS;
      
      % Carole had spent 3/5 of her money
      constraint 3 * GHI == 5 * Zab;
      
      % Anne had spent a little more than 3/5 of her money (say less than 4/5)
      constraint 5 * TUV > 3 * ABC /\ 5 * TUV < 4 * ABC;
      
      solve satisfy;
      
      output ["Starting amounts(p) for Anne, Betty & Carole: " 
      ++ show(ABC) ++ ", " ++ show (DEF) ++ ", " ++ show(GHI)
      ++ "\nFinal amounts(p) for Anne, Betty & Carole: " 
      ++ show(JKL) ++ ", " ++ show(MNP) ++ ", " ++ show(QRS)
      ++ "\nAmounts spent(p) for Anne, Betty & Carole: " 
      ++ show(TUV) ++ ", " ++ show(WXY) ++ ", " ++ show(Zab)];
      
      % Starting amounts(p) for Anne, Betty & Carole: 627, 318, 945
      % Final amounts(p) for Anne, Betty & Carole: 245, 169, 378
      % Amounts spent(p) for Anne, Betty & Carole: 382, 149, 567
      % time elapsed: 0.38 s
      % ----------
      % ==========
      
      
      

      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