Enigmatic Code

Programming Enigma Puzzles

Enigma 1677: Six of one

From New Scientist #2843, 17th December 2011 [link]

Albion, Borough, City, Rangers and United have played a tournament in which each team played each of the other teams once. Two points were awarded for a win and one for a draw. In the final table the teams finished in alphabetical order, Albion with most points and United with fewest, no two teams having the same number of points. There was only one instance of two matches having the same score. No team scored more than 4 goals in any one match. In the course of the tournament each team scored 6 goals and conceded 6 goals.

Borough beat Albion 3-0. What were the scores in (a) Borough vs City and (b) Rangers vs United?

[enigma1677]

Advertisements

3 responses to “Enigma 1677: Six of one

  1. jimrandell 15 December 2011 at 12:01 am

    The following Python script runs in 470ms.

    from itertools import product
    from enigma import printf
    
    scores = (
      ((0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)),
      ((0, 0), (1, 1), (2, 2), (3, 3), (4, 4)),
      ((1, 0), (2, 0), (3, 0), (4, 0), (2, 1), (3, 1), (4, 1), (3, 2), (4, 2), (4, 3))
    )
    
    (AB, sAB) = (0, (0, 3))
    for (AC, AR, AU, BC, BR, BU, CR, CU, RU) in product((2, 1, 0), repeat=9):
      A = sum((AB, AC, AR, AU))
      B = sum((2-AB, BC, BR, BU))
      C = sum((2-AC, 2-BC, CR, CU))
      R = sum((2-AR, 2-BR, 2-CR, RU))
      U = sum((2-AU, 2-BU, 2-CU, 2-RU))
      if not(A > B > C > R > U): continue
    
      for (sAC, sAR, sAU) in product(scores[AC], scores[AR], scores[AU]):
        sA = [sAB, sAC, sAR, sAU]
        s1 = set(sA)
        if len(s1) < 3: continue
        if tuple(map(sum, zip(*sA))) != (6, 6): continue
    
        for (sBC, sBR, sBU) in product(scores[BC], scores[BR], scores[BU]):
          sB = [sBC, sBR, sBU]
          s2 = s1.union(sB)
          if len(s2) < 6: continue
          sB.append(tuple(reversed(sAB)))
          if tuple(map(sum, zip(*sB))) != (6, 6): continue
    
          for (sCR, sCU) in product(scores[CR], scores[CU]):
            sC = [sCR, sCU]
            s3 = s2.union(sC)
            if len(s3) < 8: continue
            sC.extend((tuple(reversed(x)) for x in (sAC, sBC)))
            if tuple(map(sum, zip(*sC))) != (6, 6): continue
    
            for sRU in scores[RU]:
              sR = [sRU]
              s4 = s3.union(sR)
              if len(s4) != 9: continue
              sR.extend((tuple(reversed(x)) for x in (sAR, sBR, sCR)))
              if tuple(map(sum, zip(*sR))) != (6, 6): continue
    
              sU = [tuple(reversed(x)) for x in (sAU, sBU, sCU, sRU)]
              if tuple(map(sum, zip(*sU))) != (6, 6): continue
    
              printf("BvC={sBC} RvU={sRU} [AvB={sAB} AvC={sAC} AvR={sAR} AvU={sAU} BvR={sBR} BvU={sBU} CvR={sCR} CvU={sCU}]")
    

    Solution: (a) Borough 0 – City 0, (b) Rangers 3 – United 1.

  2. jimrandell 16 December 2011 at 10:25 am

    This version runs in 90ms. It’s the same code, but instead of generating the scores for each team’s 4th match and then rejecting the ones that don’t give 6 goals for and 6 goals against, we generate the score directly based on the other three matches, and then check that it’s a valid score.

    from itertools import product
    from enigma import printf
    
    # possible scores for lose [0 points], draw [1 point] and win [2 points]
    scores = (
      ((0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)),
      ((0, 0), (1, 1), (2, 2), (3, 3), (4, 4)),
      ((1, 0), (2, 0), (3, 0), (4, 0), (2, 1), (3, 1), (4, 1), (3, 2), (4, 2), (4, 3))
    )
    
    (AB, sAB) = (0, (0, 3))
    # work out the points
    for (AC, AR, AU, BC, BR, BU, CR, CU, RU) in product((2, 1, 0), repeat=9):
      A = sum((AB, AC, AR, AU))
      B = sum((2-AB, BC, BR, BU))
      C = sum((2-AC, 2-BC, CR, CU))
      R = sum((2-AR, 2-BR, 2-CR, RU))
      U = sum((2-AU, 2-BU, 2-CU, 2-RU))
      if not(A > B > C > R > U): continue
    
      for (sAC, sAR) in product(scores[AC], scores[AR]):
        sAU = (6-sAB[0]-sAC[0]-sAR[0], 6-sAB[1]-sAC[1]-sAR[1])
        if not sAU in scores[AU]: continue
        s1 = set((sAB, sAC, sAR, sAU))
        if len(s1) < 3: continue
    
        for (sBC, sBR) in product(scores[BC], scores[BR]):
          sBU = (6-sAB[1]-sBC[0]-sBR[0], 6-sAB[0]-sBC[1]-sBR[1])
          if not sBU in scores[BU]: continue
          s2 = s1.union((sBC, sBR, sBU))
          if len(s2) < 6: continue
    
          for sCR in scores[CR]:
            sCU = (6-sAC[1]-sBC[1]-sCR[0], 6-sAC[0]-sBC[0]-sCR[1])
            if not sCU in scores[CU]: continue
            s3 = s2.union((sCR, sCU))
            if len(s3) < 8: continue
    
            sRU = (6-sAR[1]-sBR[1]-sCR[1], 6-sAR[0]-sBR[0]-sCR[0])
            if not sRU in scores[RU]: continue
            s4 = s3.union((sRU,))
            if len(s4) != 9: continue
    
            sU = (sAU, sBU, sCU, sRU)
            if tuple(map(sum, zip(*sU))) != (6, 6): continue
    
            printf("BvC={sBC} RvU={sRU} [AvB={sAB} AvC={sAC} AvR={sAR} AvU={sAU} BvR={sBR} BvU={sBU} CvR={sCR} CvU={sCU}]")
    
  3. martin 19 February 2013 at 7:12 am

    I remember solving that one also using Python. My solution was very heavy.
    I will dig in my “enigma library to compare.
    Have a nice day

Leave a Comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: